Es ist wichtig, wenn Sie andere Dinge mit dem Typ als einfach extract
daraus machen können. Intuitiv, wenn das einzige, was Sie tun können, ist, den Wert zu extrahieren, dann enthält der Typ nur einen Wert, also verdoppelt das Duplizieren dieses einen Wertes alles. Dies trifft im Allgemeinen nicht zu und gilt nicht für Reißverschlüsse.
Die Comonad
Gesetze sind nur die Kategorie-Gesetze über Funktionen des Typs w a -> b
verkleidet. Da diese aus Kategorien stammen, könnte es leichter sein, sie in Bezug auf eine Kategorie als in Bezug auf die Comonad
Gesetze zu begründen. extract
ist die Identität dieser Kategorie und =<=
ist der Kompositionsoperator.
-- | Right-to-left 'Cokleisli' composition
(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c
f =<= g = f . extend g
Wir wissen auch, dass extend f = fmap f . duplicate
, so können wir
f =<= g = f . fmap g . duplicate
Das sieht ziemlich einfach, an die Vernunft schreiben.Jetzt rüsten wir Ihren Typ Z
mit einer anderen Funktion aus, über die wir sprechen können. isFirst
gibt nur dann true zurück, wenn Z
einen Wert an einer Position in einer Liste mit nichts davor darstellt. Jetzt
isFirst :: Z a -> Bool
isFirst (Z [] _ _) = True
isFirst _ = False
, lassen Sie uns überlegen, was passiert, wenn wir isFirst
mit den drei Kategorie Gesetze verwenden. Die einzigen zwei, die es scheint, sind unmittelbar darauf anwendbar, dass extract
eine linke und rechte Identität für die Zusammensetzung von =<=
ist. Da wir das nur widerlegen, brauchen wir nur ein Gegenbeispiel zu finden. Ich vermute, dass einer von extract =<= isFirst
oder isFirst =<= extract
für den Eingang Z [1] 2 []
ausfallen wird. Beide sollten gleich sein wie isFirst $ Z [1] 2 []
, was False
ist. Wir versuchen zuerst extract =<= isFirst
, was passiert.
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
Wenn wir isFirst =<= extract
versuchen wir nicht so viel Glück.
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
Wenn wir duplicate
d verloren wir Informationen über die Struktur. In der Tat verloren wir Informationen über alles, was überall kam außer dem einzigen Schwerpunkt des Reißverschlusses. Die korrekte duplicate
würde einen ganzen 'nother Zipper überall im Kontext haben, der den Wert an dieser Position und den Kontext dieses Standorts hält.
Mal sehen, was wir aus diesen Gesetzen ableiten können. Mit einer kleinen Hand, die über die Kategorie von Funktionen winkt, können wir sehen, dass =<= extract
fmap extract . duplicate
ist, und dies muss die Identitätsfunktion sein. Anscheinend entdecke ich wieder, wie die Gesetze in der Dokumentation für Control.Category
geschrieben sind. Auf diese Weise können wir so etwas wie
z = (=<= extract) z
z = fmap extract . duplicate $ z
Jetzt schreiben, z
hat nur einen Konstruktor, so können wir ersetzen, dass in
Z left x right = fmap extract . duplicate $ Z left x right
Von sie von doppelten geben, wissen wir, es muss den gleichen Konstruktor zurück.
Z left x right = fmap extract $ Z lefts (Z l x' r) rights
Wenn wir fmap
dieser Z
gelten haben wir
Z left x right = Z (fmap extract lefts) (extract (Z l x' r)) (fmap extract rights)
Wenn wir dies durch die Teile des Z
Konstruktor aufgeteilt haben wir drei Gleichungen
left = fmap extract lefts
x = extract (Z l x' r)
right = fmap extract rights
Dies sagt uns, dass mindestens das Ergebnis von duplicate (Z left x right)
muss halten:
- eine Liste mit der gleichen Länge wie
left
für die linke Seite
- ein
Z
mit x
in der Mitte für die Mitte
- einer Liste mit der gleichen Länge wie
right
für die rechte Seite
Außerdem können wir sehen, dass die mittleren Werte in den Listen auf der linken und rechten Seite die gleichen wie die ursprünglichen Werte in diesen Listen sein müssen.Wenn wir nur dieses eine Gesetz betrachten, wissen wir genug, um eine andere Struktur für das Ergebnis von duplicate
zu verlangen.
Sie könnten diese Frage zum Ableiten von comonad-Instanzen für Reißverschlüsse generisch für jeden differenzierbaren Typ interessieren. http://stackoverflow.com/q/25554062/414413 Wenn ja, überprüfen Sie die umfangreiche Lösung des Schweinarbeiters mit partiellen Differentialgleichungen oder meine Lösung mit einer zweiten Ableitung. – Cirdec
Danke für den Link, ich habe darüber gescrollt, als ich versucht habe, eine Antwort auf meine Frage zu finden, aber jetzt, wo du es ausdrücklich empfohlen hast, sehe ich, dass es eine Menge neuer Sachen für mich zum Nachdenken gibt. Ich werde mich definitiv darum kümmern. – Jackie