Scala 确保我的trait的type参数是Monad
我已经写了这个代码Scala 确保我的trait的type参数是Monad,scala,Scala,我已经写了这个代码 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 } trait输入[F[]]{ def read:F[字符串] def wr
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
}
trait输入[F[]]{
def read:F[字符串]
def write(str:String):F[单位]
def getName:F[String]=for{
_trait Input[F[\u]:Monad]
将创建隐式构造函数参数,trait不能有构造函数参数(直到Scala 3)。def testFunc[F[\u]:Monad]
将创建隐式参数。例如:
def testFunc[F[_]: Monad](arg: Int) = ???
class TestClass[F[_]: Monad] {}
将工作,因为它被转换为:
def testFunc[F[_]](arg: Int)(implicit ev: Monad[F]) = ???
class TestClass[F[_]](implicit val ev: Monad[F]) {}
也就是说,[F[\u]:Monad]
是[F[\u]]
和隐式valev:Monad[F]
的语法糖。在Scala 3之前,traits没有构造函数来传递参数
对于您的情况,例如,如果您确实需要在trait内部将F
约束为Monad
,那么:
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)
}
也就是说,你对实现者说,“你可以实现Input
,只要你有Monad[F]
”。然后你可以像这样使用它:
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())
}
但对我来说,似乎有点不对劲。你在traitInput
中定义了一些效果,并在同一个trait中正确地使用了它们。至少对我来说这很奇怪。可能getName
应该在其他地方。问题不在于“因为约束在实际实现中起作用”。问题只是trait Input[F][\u]:Monad]
将创建一个隐式构造函数参数,traits不能有构造函数参数(在Scala 3之前)。正如前面提到的:“traits不能有构造函数参数”,但是抽象类可以,还有一些其他原因。
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())
}