Esta é uma continuação da resposta à minha pergunta anterior.
Suponha que eu precise mapear cada item a:A
de List[A]
para b:B
com função def f(a:A, leftNeighbors:List[A]): B
e gerar List[B]
.
Obviamente, não posso apenas chamar map
a lista, mas posso usar o zíper da lista . O zíper é um cursor para mover em uma lista. Ele fornece acesso ao elemento atual ( focus
) e seus vizinhos.
Agora posso substituir o meu f
por def f'(z:Zipper[A]):B = f(z.focus, z.left)
e passar essa nova função f'
para o cobind
método de Zipper[A]
.
As cobind
funciona assim: ele chama a f'
com o zíper, então move o zíper, chamadas f'
com o novo "movidos" zipper, move o zíper de novo e assim por diante, e assim por diante ... até o zíper chega ao fim da lista.
Por fim, o cobind
retorna um novo zíper do tipo Zipper[B]
, que pode ser transformado para a lista e assim o problema é resolvido.
Agora observe a simetria entre cobind[A](f:Zipper[A] => B):Zipper[B]
e bind[A](f:A => List[B]):List[B]
é por isso que List
é um Monad
e Zipper
é um Comonad
.
Isso faz sentido ?
fonte
Respostas:
Como esta pergunta está aparecendo regularmente no topo da lista de "não respondidas", deixe-me apenas copiar meu comentário como uma resposta aqui - nada muito mais construtivo apareceu desde um ano atrás, de qualquer maneira.
A também
List
pode ser visto como uma comonada (de várias maneiras), enquanto aZipper
pode ser lançado como uma mônada (também de várias maneiras). A diferença é se você está conceitualmente focado em "anexar" dados construtivamente a uma máquina de estado (é disso queMonad
trata a interface) ou em "extrair" o estado dela "desconstrutivamente" (é isso queComonad
ela faz).Não é fácil responder à pergunta, afirmada como "esse entendimento faz sentido", no entanto. Em certo sentido, sim, em outro, não.
fonte