在Monad上实现`sequence`

Kev*_*ith 5 monads scala

在另一个练习中实现Monad.sequence()斯卡拉函数式编程,我的回答来自官方不同/知到是正确的答案:

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

官方:

def sequence[A](lma: List[F[A]]): F[List[A]] =
  lma.foldRight(unit(List[A]()))((ma, mla) => map2(ma, mla)(_ :: _))
Run Code Online (Sandbox Code Playgroud)

矿:

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))
Run Code Online (Sandbox Code Playgroud)

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

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

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

Tra*_*own 5

当你写作时Option(1),实际发生的是你在同伴对象apply上调用方法Option.这只与Option类型非常间接相关- Something如果你只有一个引用类型的类型变量,那么通常无法获得伴随对象(这是一个值)Something.事实上,并不能保证伴随对象甚至存在,即使它确实存在,它的apply方法也可能返回一些完全不是该Something类型实例的东西.在和和案例类的情况下X.apply(...)确实返回的事实完全是一个惯例问题.XListOption

这里问题的另一部分是对此的呼吁List.flatten.如果你flatten文档中查看"完全签名" ,你会发现它有一个隐含的参数:

def flatten[B](implicit asTraversable: (A) => GenTraversableOnce[B]): List[B]
Run Code Online (Sandbox Code Playgroud)

这意味着你只能在一个List[A]if 上使用它,A可以隐式转换成GenTraversableOnce某种形式.对于任何旧的monad来说,情况并非如此.

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