Это ответ на ответ на мой предыдущий вопрос.
Предположим, мне нужно сопоставить каждый элемент a:A от List[A] до b:B с помощью функции def f(a:A, leftNeighbors:List[A]): B и сгенерировать List[B].
Очевидно, я не могу просто вызвать map в списке, но я могу использовать список zipper. Застежка-молния - это курсор для перемещения по списку. Он обеспечивает доступ к текущему элементу (focus) и его соседям.
Теперь я могу заменить my f на def f'(z:Zipper[A]):B = f(z.focus, z.left) и передать эту новую функцию f' в cobind метод Zipper[A].
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.
Имеет ли смысл?