【问题标题】:How to specify the type introduced in a match of class with independent type parameter如何指定在具有独立类型参数的类的匹配中引入的类型
【发布时间】:2020-02-21 11:43:52
【问题描述】:

我关注了 Runar Bjarnason 关于免费 monad 的演讲: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$1: error>) => cont(x$1).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 ) =&gt; Continuation(v, cont andThen (_ flatMap f) ) 而不是这一行:case Continuation(v, cont ) =&gt; Continuation(v, cont(_).flatMap(f) )。

第三行case Continuation(v, cont ) =&gt; 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"
...

【问题讨论】:

    标签: scala free-monad


    【解决方案1】:

    尝试绑定类型变量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))
    

    【讨论】:

    • 是的,都可以编译。我更喜欢第一个,构造函数模式。我不确定两者之间是否存在性能差异。这也可以编译:case Continuation(v: Box[i], cont ) =&gt; Continuation(v, cont(_: i).flatMap(f) ) 尽管它给了我一个警告。我想关键是用小写字母指定类型参数。我错过了。
    猜你喜欢
    • 2020-02-09
    • 2016-04-02
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 2023-03-04
    • 1970-01-01
    • 2019-02-21
    • 2021-10-07
    相关资源
    最近更新 更多