这是 answer 的后续内容我之前的问题。
假设我需要使用函数 def f 将
并生成 List[A]
的每个项目 a:A
映射到 b:B
(a:A, leftNeighbors:List[A]): BList[B]
。
显然我不能只在列表上调用map
,但我可以使用列表zipper。 zipper 是在列表中移动的光标。它提供对当前元素(焦点
)及其邻居的访问。
现在我可以用 def f'(z:Zipper[A]):B = f(z.focus, z.left)
替换我的 f
并通过这个新函数 f'
与 Zipper[A]
的 cobind
方法相结合。
cobind
的工作原理如下:它用 zipper 调用 f'
,然后移动 zipper ,用 f'
调用 < em>new“移动” zipper ,再次移动 zipper ,依此类推……直到 zipper 到达列表末尾。
最后,cobind
返回一个Zipper[B]
类型的新 zipper ,可以将其转换为列表,从而解决问题。
现在请注意 cobind[A](f:Zipper[A] => B):Zipper[B]
和 bind[A](f:A => List [B]):List[B]
这就是为什么 List
是一个 Monad
而 Zipper
是一个 Comonad
.
有意义吗?
最佳答案
由于这个问题经常出现在“未回答”列表的顶部,所以让我在这里复制我的评论作为答案 - 无论如何,自一年前以来没有出现任何更具建设性的问题。
List
也可以被视为一个 comonad(以多种方式),而 Zipper
可以被视为一个 monad(也以多种方式)。区别在于,您在概念上是专注于将数据建设性地“追加”到状态机(这就是 Monad 接口(interface)的作用),还是“解构性地”从中“提取”状态(这就是 Monad 接口(interface)的作用)。 Comonad
确实如此)。
然而,回答“这种理解是否有意义”的问题并不容易。从某种意义上来说确实如此,但从另一种意义上来说则不然。
关于scala - 了解为什么 Zipper 是 Comonad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24013339/