Ensure that the type parameter for my trait is a Monad









up vote
1
down vote

favorite












I have written this code



trait Input[F[_]] 
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



This code doesn't compile obviously because the compiler has no way of knowing that the type F supports flatmap. So I change my code to



import scalaz._
import Scalaz._
trait Input[F[_] : Monad]
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



but now I get compile time error traits cannot have type parameters with context bounds.



So how can I specify constraints on my type parameter so that it always supports flatmap?










share|improve this question

















  • 1




    As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
    – jwvh
    Nov 11 at 7:35















up vote
1
down vote

favorite












I have written this code



trait Input[F[_]] 
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



This code doesn't compile obviously because the compiler has no way of knowing that the type F supports flatmap. So I change my code to



import scalaz._
import Scalaz._
trait Input[F[_] : Monad]
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



but now I get compile time error traits cannot have type parameters with context bounds.



So how can I specify constraints on my type parameter so that it always supports flatmap?










share|improve this question

















  • 1




    As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
    – jwvh
    Nov 11 at 7:35













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I have written this code



trait Input[F[_]] 
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



This code doesn't compile obviously because the compiler has no way of knowing that the type F supports flatmap. So I change my code to



import scalaz._
import Scalaz._
trait Input[F[_] : Monad]
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



but now I get compile time error traits cannot have type parameters with context bounds.



So how can I specify constraints on my type parameter so that it always supports flatmap?










share|improve this question













I have written this code



trait Input[F[_]] 
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



This code doesn't compile obviously because the compiler has no way of knowing that the type F supports flatmap. So I change my code to



import scalaz._
import Scalaz._
trait Input[F[_] : Monad]
def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = for
_ <- write("What is your name")
name <- read
yield name



but now I get compile time error traits cannot have type parameters with context bounds.



So how can I specify constraints on my type parameter so that it always supports flatmap?







scala






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 10 at 20:04









Knows Not Much

10.1k2598196




10.1k2598196







  • 1




    As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
    – jwvh
    Nov 11 at 7:35













  • 1




    As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
    – jwvh
    Nov 11 at 7:35








1




1




As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
– jwvh
Nov 11 at 7:35





As has been noted: "traits can't have constructor parameters," but an abstract class can, and there are a few other reasons you might prefer an abstract class instead of a trait.
– jwvh
Nov 11 at 7:35













1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:



def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad]


Will work because it is translated to:



def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F])


I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.



For your case, if you really need to inside a trait to constraint F to a Monad for example, then:



trait Input[F[_]] 
val M: Monad[F]

def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)



I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:



object Main extends App

class IOInput extends Input[IO]
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))


val impl = new IOInput

println(impl.getName.unsafeRunSync())



P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.






share|improve this answer


















  • 2




    The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
    – Alexey Romanov
    Nov 11 at 7:11










  • @AlexeyRomanov, thanks, updated
    – muradm
    Nov 11 at 7:17











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242943%2fensure-that-the-type-parameter-for-my-trait-is-a-monad%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:



def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad]


Will work because it is translated to:



def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F])


I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.



For your case, if you really need to inside a trait to constraint F to a Monad for example, then:



trait Input[F[_]] 
val M: Monad[F]

def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)



I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:



object Main extends App

class IOInput extends Input[IO]
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))


val impl = new IOInput

println(impl.getName.unsafeRunSync())



P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.






share|improve this answer


















  • 2




    The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
    – Alexey Romanov
    Nov 11 at 7:11










  • @AlexeyRomanov, thanks, updated
    – muradm
    Nov 11 at 7:17















up vote
1
down vote



accepted










trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:



def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad]


Will work because it is translated to:



def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F])


I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.



For your case, if you really need to inside a trait to constraint F to a Monad for example, then:



trait Input[F[_]] 
val M: Monad[F]

def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)



I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:



object Main extends App

class IOInput extends Input[IO]
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))


val impl = new IOInput

println(impl.getName.unsafeRunSync())



P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.






share|improve this answer


















  • 2




    The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
    – Alexey Romanov
    Nov 11 at 7:11










  • @AlexeyRomanov, thanks, updated
    – muradm
    Nov 11 at 7:17













up vote
1
down vote



accepted







up vote
1
down vote



accepted






trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:



def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad]


Will work because it is translated to:



def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F])


I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.



For your case, if you really need to inside a trait to constraint F to a Monad for example, then:



trait Input[F[_]] 
val M: Monad[F]

def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)



I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:



object Main extends App

class IOInput extends Input[IO]
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))


val impl = new IOInput

println(impl.getName.unsafeRunSync())



P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.






share|improve this answer














trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3). def testFunc[F[_]: Monad] would create an implicit parameter. For instance:



def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad]


Will work because it is translated to:



def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F])


I.e. [F[_]: Monad] is syntactic sugar for [F[_]] with implicit val ev: Monad[F]. And traits has no constructor to pass parameters until Scala 3.



For your case, if you really need to inside a trait to constraint F to a Monad for example, then:



trait Input[F[_]] 
val M: Monad[F]

def read: F[String]
def write(str: String) : F[Unit]
def getName : F[String] = M.flatMap(write("What is your name"))(_ => read)



I.e. you are saying to one who implements, that "you can implement Input, as soon as you have Monad[F]". Then you can use it like:



object Main extends App

class IOInput extends Input[IO]
override val M: Monad[IO] = Monad[IO]
override def read: IO[String] = IO("red")
override def write(str: String): IO[Unit] = IO(println(s"write: $str"))


val impl = new IOInput

println(impl.getName.unsafeRunSync())



P.S. But for me, it seems like something is wrong. You are kinda defining effects in trait Input and using them right in the same trait. Reads weird for me at least. Probably getName should be somewhere else.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 11 at 7:17

























answered Nov 10 at 20:29









muradm

732419




732419







  • 2




    The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
    – Alexey Romanov
    Nov 11 at 7:11










  • @AlexeyRomanov, thanks, updated
    – muradm
    Nov 11 at 7:17













  • 2




    The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
    – Alexey Romanov
    Nov 11 at 7:11










  • @AlexeyRomanov, thanks, updated
    – muradm
    Nov 11 at 7:17








2




2




The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
– Alexey Romanov
Nov 11 at 7:11




The problem is not "Because constraints work on actual implementations." It's just that trait Input[F[_]: Monad] would create an implicit constructor parameter and traits can't have constructor parameters (until Scala 3).
– Alexey Romanov
Nov 11 at 7:11












@AlexeyRomanov, thanks, updated
– muradm
Nov 11 at 7:17





@AlexeyRomanov, thanks, updated
– muradm
Nov 11 at 7:17


















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53242943%2fensure-that-the-type-parameter-for-my-trait-is-a-monad%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

Barbados

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3