To jest kontynuacja odpowiedzi na moje poprzednie pytanie.
Załóżmy, że trzeba mapować każdy element a:A
od List[A]
do b:B
z funkcji def f(a:A, leftNeighbors:List[A]): B
i generować List[B]
.
Oczywiście nie mogę po prostu zadzwonić map
na listę, ale mogę użyć suwaka listy . Zamek błyskawiczny to kursor do poruszania się po liście. Zapewnia dostęp do bieżącego elementu ( focus
) i jego sąsiadów.
Teraz mogę zastąpić mój f
z def f'(z:Zipper[A]):B = f(z.focus, z.left)
i przekazać tę nową funkcję f'
do cobind
metody Zipper[A]
.
Że cobind
działa tak: to połączenia, które f'
z zamkiem, a następnie przesuwa suwak, rozmowy f'
z nowym „przeniesione” na zamek błyskawiczny, znowu i tak dalej, i tak porusza się na zamek błyskawiczny ... aż osiągnie koniec listy.
Na koniec cobind
zwraca nowy typ zamka błyskawicznego Zipper[B]
, który można przekształcić na listę, dzięki czemu problem został rozwiązany.
Zwróć teraz uwagę na symetrię między cobind[A](f:Zipper[A] => B):Zipper[B]
a bind[A](f:A => List[B]):List[B]
Dlatego List
jest a Monad
i Zipper
jest a Comonad
.
Czy jest sens ?