Este es un seguimiento de la respuesta a mi pregunta anterior.
Supongamos que necesito asignar cada elemento a:A
de List[A]
a b:B
con función def f(a:A, leftNeighbors:List[A]): B
y generar List[B]
.
Obviamente, no puedo simplemente llamar map
a la lista, pero puedo usar la cremallera de la lista . La cremallera es un cursor para moverse por una lista. Proporciona acceso al elemento actual ( focus
) y sus vecinos.
Ahora puedo reemplazar my f
con def f'(z:Zipper[A]):B = f(z.focus, z.left)
y pasar esta nueva función f'
al cobind
método de Zipper[A]
.
Las cobind
obras de este tipo: llama que f'
con el cierre, a continuación, mueve la cremallera, llamadas f'
con el nuevo "movidas" de la cremallera, la cremallera se mueve de nuevo y así sucesivamente, y así sucesivamente ... hasta que la cremallera llega al final de la lista.
Finalmente, cobind
devuelve una nueva cremallera de tipo Zipper[B]
, que se puede transformar a la lista y así se soluciona el problema.
Ahora observe la simetría entre cobind[A](f:Zipper[A] => B):Zipper[B]
y. bind[A](f:A => List[B]):List[B]
Por eso List
es a Monad
y Zipper
es a Comonad
.
Tiene sentido ?
Respuestas:
Como esta pregunta aparece regularmente en la parte superior de la lista de "sin respuesta", permítanme simplemente copiar mi comentario como respuesta aquí; de todos modos, no ha aparecido nada considerablemente más constructivo desde hace un año.
A también
List
se puede ver como una comónada (de múltiples formas), mientras que aZipper
se puede convertir en una mónada (también de muchas formas). La diferencia está en si te enfocas conceptualmente en "agregar" datos de manera constructiva a una máquina de estado (de eso se trata laMonad
interfaz), o en "extraer" el estado de ella "deconstructivamente" (eso es lo queComonad
hace).Sin embargo, no es fácil responder a la pregunta, planteada como "¿tiene sentido este entendimiento"? En cierto sentido lo hace, en otro no.
fuente