如果 M 是 monad,如何将 List[M[List[A]]] 正确组合到 M[List[A]] 中?
How to properly combine List[M[List[A]]] into M[List[A]] if M is a monad?
我有包装列表的单子。我想将这些 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
})
这似乎可以编译,但我觉得它应该比这更简单 更短。有什么改进的想法吗?
我认为 semigroup(或 SemigroupK)可能是您正在寻找的抽象
有一个 Traverse[List]
的实例。
每个 Monad[M]
都是 Applicative[M]
的特例。因此,如果您有
List[M[List[A]]]
您应该可以在 Traverse[List]
中使用 sequence
和 Applicative[M]
来首先将其转换为
M[List[List[A]]]
然后用map
从Functor[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
的情况下。
我有包装列表的单子。我想将这些 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
})
这似乎可以编译,但我觉得它应该比这更简单 更短。有什么改进的想法吗?
我认为 semigroup(或 SemigroupK)可能是您正在寻找的抽象
有一个 Traverse[List]
的实例。
每个 Monad[M]
都是 Applicative[M]
的特例。因此,如果您有
List[M[List[A]]]
您应该可以在 Traverse[List]
中使用 sequence
和 Applicative[M]
来首先将其转换为
M[List[List[A]]]
然后用map
从Functor[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
的情况下。