如何指定在 class 的匹配中引入的具有独立类型参数的类型
How to specify the type introduced in a match of class with independent type parameter
我关注了 Runar Bjarnason 关于自由单子的演讲:http://functionaltalks.org/2014/11/23/runar-oli-bjarnason-free-monad/
我从他的初始示例中得到了以下代码(我使用名称 Continuation 而不是 Bind,使用 Box 而不是 F - 我现在更喜欢它们):
object TestFreeMonads
{
sealed trait Interact[A]
case class Ask(prompt: String) extends Interact[String]
case class Tell(msg: String) extends Interact[Unit]
sealed trait Free[Box[_], A] {
def flatMap[B](f: A => Free[Box, B]): Free[Box, B] =
this match {
case Return(a) => f(a)
case Continuation(v, cont ) => Continuation(v, cont andThen (_ flatMap f) )
// The following line does not compile: missing parameter type for expanded function ((<x: error>) => cont(x).flatMap(f))
// case Continuation(v, cont ) => Continuation(v, cont(_).flatMap(f) )
// This line does compile:
// case Continuation(v, cont ) => Continuation[Box, Any, B](v, cont(_).flatMap(f) )
}
def map[B](f: A => B): Free[Box, B] = flatMap(a => Return(f(a)))
}
case class Return[Box[_], A](a: A) extends Free[Box, A]
case class Continuation[Box[_], I, A](v: Box[I], cont: I => Free[Box, A]) extends Free[Box, A]
def lift[Box[_], A](v: Box[A]): Free[Box, A] = Continuation(v, (a: A) => Return(a))
implicit def liftInteract[A](v: Interact[A]) : Free[Interact, A] = lift(v)
def prog: Free[Interact, Unit] = {
for {
first <- Ask("First Name")
last <- Ask("Last Name")
_ <- Tell(s"Hello, $first $last")
} yield ()
}
}
我不明白为什么这一行编译:case Continuation(v, cont ) => Continuation(v, cont andThen (_ flatMap f) )
但这一行不编译:case Continuation(v, cont ) => Continuation(v, cont(_).flatMap(f) )
.
第三行 case Continuation(v, cont ) => Continuation[Box, Any, B](v, cont(_).flatMap(f) )
也可以编译,但有点冗长,我使用 Any 作为 I 类型参数的值,我认为这是有问题的。理想情况下,我应该以某种方式声明 v 的类型并使用它,但这似乎不可能。
最终 v 的类型为 I,但它有点隐藏。
我用的是 scala 2.13.1:
...
scalaVersion := "2.13.1"
scalacOptions += "-feature"
scalacOptions += "-language:implicitConversions"
...
尝试绑定类型变量i
(小写)
case Continuation(v, cont: Function1[i, _]) => Continuation(v, cont(_: i).flatMap(f))
你也可以使用类型模式
case c: Continuation[Box, i, A] => Continuation(c.v, c.cont(_: i).flatMap(f))
我关注了 Runar Bjarnason 关于自由单子的演讲:http://functionaltalks.org/2014/11/23/runar-oli-bjarnason-free-monad/
我从他的初始示例中得到了以下代码(我使用名称 Continuation 而不是 Bind,使用 Box 而不是 F - 我现在更喜欢它们):
object TestFreeMonads
{
sealed trait Interact[A]
case class Ask(prompt: String) extends Interact[String]
case class Tell(msg: String) extends Interact[Unit]
sealed trait Free[Box[_], A] {
def flatMap[B](f: A => Free[Box, B]): Free[Box, B] =
this match {
case Return(a) => f(a)
case Continuation(v, cont ) => Continuation(v, cont andThen (_ flatMap f) )
// The following line does not compile: missing parameter type for expanded function ((<x: error>) => cont(x).flatMap(f))
// case Continuation(v, cont ) => Continuation(v, cont(_).flatMap(f) )
// This line does compile:
// case Continuation(v, cont ) => Continuation[Box, Any, B](v, cont(_).flatMap(f) )
}
def map[B](f: A => B): Free[Box, B] = flatMap(a => Return(f(a)))
}
case class Return[Box[_], A](a: A) extends Free[Box, A]
case class Continuation[Box[_], I, A](v: Box[I], cont: I => Free[Box, A]) extends Free[Box, A]
def lift[Box[_], A](v: Box[A]): Free[Box, A] = Continuation(v, (a: A) => Return(a))
implicit def liftInteract[A](v: Interact[A]) : Free[Interact, A] = lift(v)
def prog: Free[Interact, Unit] = {
for {
first <- Ask("First Name")
last <- Ask("Last Name")
_ <- Tell(s"Hello, $first $last")
} yield ()
}
}
我不明白为什么这一行编译:case Continuation(v, cont ) => Continuation(v, cont andThen (_ flatMap f) )
但这一行不编译:case Continuation(v, cont ) => Continuation(v, cont(_).flatMap(f) )
.
第三行 case Continuation(v, cont ) => Continuation[Box, Any, B](v, cont(_).flatMap(f) )
也可以编译,但有点冗长,我使用 Any 作为 I 类型参数的值,我认为这是有问题的。理想情况下,我应该以某种方式声明 v 的类型并使用它,但这似乎不可能。
最终 v 的类型为 I,但它有点隐藏。
我用的是 scala 2.13.1:
...
scalaVersion := "2.13.1"
scalacOptions += "-feature"
scalacOptions += "-language:implicitConversions"
...
尝试绑定类型变量i
(小写)
case Continuation(v, cont: Function1[i, _]) => Continuation(v, cont(_: i).flatMap(f))
你也可以使用类型模式
case c: Continuation[Box, i, A] => Continuation(c.v, c.cont(_: i).flatMap(f))