首页 > 解决方案 > 如果 M 是单子,如何将 List[M[List[A]]] 正确组合成 M[List[A]]?

问题描述

我有包装列表的单子。我想将这些 monad 组合起来形成一个包含所有列表连接的 monad。

M[List[A]] + M[List[A]] ==> M[List[A]]

为了实现这一点,我做了以下(伪代码)

(1 to 10).foldLeft(Option(List(0)))((accumulator, i) => {
  for {
    prev <- accumulator
    more <- Option(List(i))
  } yield prev ++ more
})

这似乎可以编译,但我觉得它应该比这更简单和更短。有什么改进的想法吗?

标签: scalafunctional-programmingmonadsapplicativescala-cats

解决方案


有一个实例Traverse[List]。每一个Monad[M]都是 的特例Applicative[M]。因此,如果您有一个

List[M[List[A]]]

您应该可以使用sequenceinTraverse[List]Applicative[M]首先将其转换为

M[List[List[A]]]

然后使用mapfromFunctor[M]flatten它进入

M[List[A]]

就像是

val lists: List[Option[List[A]]] = ???
val optLists: Option[List[List[A]]] = Traverse[List].sequence(lists)
val optList: Option[List[A]] = optLists.map(_.flatten)

在 的情况下Option


推荐阅读