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 ?