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