在Monad上实现`sequence`

时间:2013-11-17 22:45:05

标签: scala monads

正在进行另一项练习以Functional Programming in Scala实施Monad.sequence(),我的回答与官方/已知的正确答案不同:

  

def序列[A](lma:列表[F [A]]):F [列表[A]]

Official

def sequence[A](lma: List[F[A]]): F[List[A]] =
  lma.foldRight(unit(List[A]()))((ma, mla) => map2(ma, mla)(_ :: _))
我是:

def sequence[A](lma: List[F[A]]): F[List[A]] = F(lma.flatten)

F Option的示例:

scala> val x: List[Option[Int]] = List( Some(1), None)
x: List[Option[Int]] = List(Some(1), None)

scala> Some(x.flatten)
res1: Some[List[Int]] = Some(List(1))

我的回答(或其精神)在这里合法吗?

我得到以下编译时异常,但我确定它是否与我对类型构造函数缺乏理解有关。

  

Monad.scala:15:错误:未找到:值F
                 F(lma.flatten)

1 个答案:

答案 0 :(得分:5)

当您撰写Option(1)时,实际发生的是您在apply随播广告对象上调用Option方法。这只与Option类型非常间接相关 - 具体来说,如果你只有一个类型变量引用{{},那么通常无法获得Something伴随对象(这是一个值) 1}}类型。事实上,并不能保证伴随对象存在,即使它确实存在,它的Something方法也可能返回一些完全不是apply类型实例的东西。在SomethingX.apply(...)以及案例类的情况下X确实返回List这一事实完全是一个惯例问题。

此处问题的另一部分是对Option的调用。如果您查看the docsList.flatten的“完整签名”,您会看到它有一个隐含的参数:

flatten

这意味着您只能在def flatten[B](implicit asTraversable: (A) => GenTraversableOnce[B]): List[B] 上使用它,如果List[A]可以隐式转换为某种A。对于任何旧的monad来说,情况并非如此。

我鼓励你向自己证明这些事情,但是尝试与练习中的其他一些monad一起实施,看看事情发生了什么。