Понимание того, почему Zipper является Comonad
Это ответ на ответ на мой предыдущий вопрос.
Предположим, мне нужно сопоставить каждый элемент 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
.
Имеет ли смысл?
Ответы
Ответ 1
Поскольку этот вопрос регулярно появляется в верхней части списка "без ответа", позвольте мне просто скопировать мой комментарий в качестве ответа здесь - ничего более конструктивного не появилось с года назад в любом случае.
A List
также можно рассматривать как комонад (по-разному), а Zipper
можно отличить как монаду (также по-разному). Разница заключается в том, концептуально ли вы концептуально сосредоточены на "добавлении" данных на конечный автомат (что означает интерфейс Monad
) или "извлечение" из него "деконструктивно" (что делает Comonad
),.
Нелегко ответить на вопрос, заявляя, что "понимает ли это понимание смысл". В некотором смысле это происходит, а в другом - нет.