2014-12-03 19 views
14

powielać Dlaczego podczas definiowania funkcji powielaćComonad funkcję

duplicate :: w a -> w (w a)  

dla typeclass Comonad (link) trzeba modyfikować wszystkie elementy „w kontekście” (czyli zmienić elementy inne niż prąd wartość kontekstu). Dlaczego po prostu użyć czegoś podobnego do return w Monadzie?

Przykład (suwak):

data Z a = Z [a] a [a]  

dlaczego nie można po prostu określić duplikat jak

duplicate z = Z [] z []  

Starałem się czerpać wymóg dla powielać funkcji z zasadami Comonad, ale zawsze kończy się duplikatem, który po prostu owija element bardzo podobnie do powracając w monadę bez potrzeby robienia czegokolwiek innego.

Jeden blog post mówi:

duplikat jest nieco trudniejsze do uchwycenia. Z suwaka listowego musimy zbudować zamek listy suwaków listowych. Znaczenie za to (potwierdzone przez prawo comonad że każdy przypadek musi spełnić) jest to, że porusza się wewnątrz struktury powielane zwraca oryginalną strukturę, zmienione przez tego samego ruchu

Ale ja nie rozumiem, dlaczego to musi być w ten sposób. FMap w przepisach Comonad zawsze dotyczy owiniętego elementu, a potem ten jeden element jest zawsze „rozpakować” z ekstraktu, dlaczego przeszkadza robi nic innego w powielać funkcję inną niż tylko owijanie argument powielać ?

Czy możesz wskazać, co przegapiłem? Czuję, że gdzieś popełniłem jakiś oczywisty błąd, ale po prostu nie mogę tego zrozumieć.

Z góry dziękuję za odpowiedzi!

+0

Być może zainteresuje Cię to pytanie o wyprowadzanie instancji komandodowych dla zamków błyskawicznych ogólnie dla każdego innego typu. http://stackoverflow.com/q/25554062/414413 Jeśli tak, sprawdź ekstensywne rozwiązanie dla hodowcy z częściowymi równaniami różniczkowymi lub moje rozwiązanie z drugą pochodną. – Cirdec

+0

Dzięki za link, przewinąłem go, próbując znaleźć odpowiedź na moje pytanie, ale teraz, kiedy poleciłeś to wyraźnie, widzę, że ma mnóstwo nowych rzeczy, o które mógłbym się zastanowić. Z pewnością zajrzę w to. – Jackie

Odpowiedz

6

Ważne jest, aby robić z niego inne rzeczy niż po prostu extract. Intuicyjnie, jeśli jedyną rzeczą, którą możesz zrobić, to wyodrębnić wartość, wtedy typ zawiera tylko jedną wartość, więc powielenie tej jednej wartości powoduje duplikowanie wszystkiego. Nie jest to prawda w ogóle, i nie jest prawdą w przypadku zamków błyskawicznych.

Ustawy Comonad są tylko ustawami o kategorii w przebraniu funkcji typu w a -> b. Ponieważ pochodzą one z kategorii, łatwiej jest o nich mówić kategoriami niż kategoriami Comonad. extract to tożsamość tej kategorii, a =<= to operator kompozycji.

-- | Right-to-left 'Cokleisli' composition 
(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c 
f =<= g = f . extend g 

Wiemy również, że extend f = fmap f . duplicate, więc możemy napisać

f =<= g = f . fmap g . duplicate 

Wygląda to dość łatwe do rozsądku o.Teraz wyposażyliśmy Twój typ Z w inną funkcję, o której możemy porozmawiać. isFirst zwróci true tylko wtedy, gdy Z reprezentuje wartość na pozycji na liście bez niczego przed nią.

Rozważmy teraz, co się stanie, gdy użyjemy isFirst z trzema kategoriami praw. Wydaje się, że jedyne dwa, które wydają się natychmiast mieć zastosowanie, to to, że extract jest lewą i prawą tożsamością kompozycji według =<=. Ponieważ obalamy to tylko, musimy znaleźć jedynie kontrprzykład. Podejrzewam, że jeden z extract =<= isFirst lub isFirst =<= extract zakończy się niepowodzeniem dla wejścia Z [1] 2 []. Oba powinny być takie same, jak isFirst $ Z [1] 2 [], czyli False. Najpierw spróbujmy extract =<= isFirst, co powinno się udać.

extract =<= isFirst    $ Z [1] 2 [] 
extract . fmap isFirst . duplicate $ Z [1] 2 [] 
extract . fmap isFirst $ Z []   (Z [1] 2 []) [] 
extract    $ Z [] (isFirst (Z [1] 2 [])) [] 
extract    $ Z [] False     [] 
           False 

Kiedy spróbujemy isFirst =<= extract, nie będziemy mieli tyle szczęścia.

isFirst =<= extract    $ Z [1] 2 [] 
isFirst . fmap extract . duplicate $ Z [1] 2 [] 
isFirst . fmap extract $ Z []   (Z [1] 2 []) [] 
isFirst    $ Z [] (extract (Z [1] 2 [])) [] 
isFirst    $ Z [] 2      [] 
True 

Kiedy straciliśmy informacje o strukturze. W rzeczywistości straciliśmy informacje o wszystkim, co przyszło wszędzie, z wyjątkiem jednego centralnego punktu zamka błyskawicznego. Prawidłowy duplicate miałby cały "dodatkowy zamek błyskawiczny wszędzie w kontekście utrzymującym wartość w tej lokalizacji i kontekście tej lokalizacji.

Zobaczmy, co możemy wywnioskować z tych przepisów. Niewielką ręką machając ręką na temat kategorii funkcji, widzimy, że =<= extract jest , a to musi być funkcja tożsamości. Najwyraźniej odkrywam na nowo, w jaki sposób prawa są zapisane w dokumentacji dla Control.Category. To pozwala nam napisać coś jak

z = (=<= extract)    z 
z = fmap extract . duplicate $ z 

Teraz z ma tylko jeden konstruktor, więc możemy podstawić że w

Z left x right = fmap extract . duplicate $ Z left x right 

Od one rodzaj dwóch egzemplarzach, wiemy, to musi wrócić tego samego konstruktora.

Z left x right = fmap extract $ Z lefts (Z l x' r) rights 

Jeśli zastosujemy fmap do tego Z mamy

Z left x right = Z (fmap extract lefts) (extract (Z l x' r)) (fmap extract rights) 

Jeśli podzielimy to przez części konstruktora Z mamy trzy równania

left = fmap extract lefts 
x = extract (Z l x' r) 
right = fmap extract rights 

To mówi nam, że co najmniej wynik duplicate (Z left x right) musi zawierać:

  • lista z taką samą długość jak left na lewej stronie
  • Z z x w środku na środkowym
  • liście z tej samej długości co right dla prawej strony

Co więcej, widzimy, że wartości średnie na listach po lewej i prawej stronie muszą być takie same, jak wartości oryginalne na tych listach.Biorąc pod uwagę tylko to jedno prawo wiemy wystarczająco, aby wymagać innej struktury dla wyniku duplicate.

+0

Cześć Cirdec, przybijałeś to. Próbowałem wymyślić samemu kontrprzykład, ale zawsze celowałem w punkt centralny i nigdy nie próbowałem sprawdzać kontekstu (jak ma to twoje 'isFirst'). Nie tylko jest to poprawna odpowiedź, ale zawiera dodatkowe przydatne informacje na ten temat. Uaktualnianie i oznaczanie jako zaakceptowanej odpowiedzi. – Jackie