最佳答案
这是我上一个问题 回答的后续。
假设我需要使用函数 def f(a:A, leftNeighbors:List[A]): B
将 List[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]
之间的对称性,这就是为什么 List
是 Monad
,而 Zipper
是 Comonad
。
这说得通吗?