理解为什么拉链是一个 Comonad

这是我上一个问题 回答的后续。

假设我需要使用函数 def f(a:A, leftNeighbors:List[A]): BList[A]的每个项目 a:A映射到 b:B并生成 List[B]

显然,我不能仅仅在列表中调用 map,但是我可以使用列表 拉链。Zipper 是在列表中移动的光标。它提供对当前元素(focus)及其邻居的访问。

现在我可以用 def f'(z:Zipper[A]):B = f(z.focus, z.left)代替我的 f,并将这个新函数 f'传递给 Zipper[A]cobind方法。

cobind的工作原理是这样的: 它用拉链调用 f',然后移动拉链,用 新的“移动”拉链调用 f',再次移动拉链,依此类推... 直到拉链到达列表的末尾。

最后,cobind返回一个类型为 Zipper[B]的新拉链,可以将其转换为列表,从而解决了这个问题。

现在注意 cobind[A](f:Zipper[A] => B):Zipper[B]bind[A](f:A => List[B]):List[B]之间的对称性,这就是为什么 ListMonad,而 ZipperComonad

这说得通吗?

2919 次浏览

As this question is popping up regularly in the top of the "unanswered" list, let me just copy my comment as an answer here - nothing considerably more constructive has appeared since a year ago anyway.

A List can be viewed as a comonad just as well (in multiple ways), while a Zipper can be cast as a monad (also in many ways). The difference is in whether you are conceptually focused on "appending" data constructively to a state machine (that's what the Monad interface is about), or "extracting" state from it "deconstructively" (that's what the Comonad does).

It is not easy to answer the question, stated as "does this understanding make sense", however. In some sense it does, in another it does not.