scala - 如果 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
})
这似乎可以编译,但我觉得它应该比这更简单和更短。有什么改进的想法吗?
解决方案
有一个实例Traverse[List]
。每一个Monad[M]
都是 的特例Applicative[M]
。因此,如果您有一个
List[M[List[A]]]
您应该可以使用sequence
inTraverse[List]
来Applicative[M]
首先将其转换为
M[List[List[A]]]
然后使用map
fromFunctor[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
。
推荐阅读
- c# - 将十进制格式化为长度为 9 的字符串,在 '.' 之前有 2 位数字(0 填充)和 6 之后
- git - 开发/主控的 git push 失败
- java - 等待任何完成的可调用返回值,只要它在可调用列表中完成
- reactjs - 元素类型无效,反应
- python - 使用熊猫数据框上的名称将图像从一个文件夹复制到另一个文件夹
- php - Doctrine JOIN ... ON ... 在注释中
- sql-server - 根据其他列的数据更新表别名的列数据
- subdomain - 为 virtuoso 安装创建子域
- javascript - Discord.JS v12 - 通过 ID 查找用户并踢他们
- visual-studio - 在 Visual Studio 中运行具有不同数据源的两个项目