Dies ist eine Fortsetzung der Antwort auf meine vorherige Frage.
Angenommen , ich brauche jedes Element zur Karte a:A
von List[A]
zu b:B
mit Funktion def f(a:A, leftNeighbors:List[A]): B
und erzeugen List[B]
.
Natürlich kann ich nicht einfach anrufen map
auf der Liste , aber ich kann die Liste verwenden Reißverschluss . Der Reißverschluss ist ein Cursor zum Bewegen in einer Liste. Es bietet Zugriff auf das aktuelle Element ( focus
) und seine Nachbarn.
Jetzt kann ich meine f
durch ersetzen def f'(z:Zipper[A]):B = f(z.focus, z.left)
und diese neue Funktion f'
an die cobind
Methode von übergeben Zipper[A]
.
Das cobind
funktioniert so: Es ruft das f'
mit dem Reißverschluss auf, bewegt dann den Reißverschluss, ruft f'
mit dem neuen "verschobenen" Reißverschluss auf, bewegt den Reißverschluss wieder und so weiter und so fort ... bis der Reißverschluss das Ende der Liste erreicht.
Schließlich wird cobind
ein neuer Reißverschluss vom Typ zurückgegeben Zipper[B]
, der in die Liste umgewandelt werden kann, sodass das Problem gelöst ist.
Beachten Sie nun die Symmetrie zwischen cobind[A](f:Zipper[A] => B):Zipper[B]
und bind[A](f:A => List[B]):List[B]
Deshalb List
ist a Monad
und Zipper
ist a Comonad
.
Macht das Sinn ?
quelle
Antworten:
Da diese Frage regelmäßig ganz oben auf der "unbeantworteten" Liste auftaucht, möchte ich hier nur meinen Kommentar als Antwort kopieren - seit einem Jahr ist ohnehin nichts wesentlich Konstruktiveres aufgetaucht.
A
List
kann genauso gut als Comonade angesehen werden (auf verschiedene Arten), während AZipper
als Monade besetzt werden kann (auch in vielerlei Hinsicht). Der Unterschied besteht darin, ob Sie sich konzeptionell darauf konzentrieren, Daten konstruktiv an eine Zustandsmaschine anzuhängen (Monad
darum geht es in der Schnittstelle) oder den Zustand "dekonstruktiv" daraus zu extrahieren (darumComonad
geht es).Es ist jedoch nicht einfach, die Frage zu beantworten, die lautet: "Ist dieses Verständnis sinnvoll?". In gewissem Sinne tut es das, in einem anderen nicht.
quelle