Reißverschluss-Comonaden, generisch
Bei jedem Containertyp können wir den (elementorientierten) Reißverschluss bilden und wissen, dass diese Struktur eine Comonade ist. Dies wurde vor kurzem in wunderbarem Detail untersuchteine weitere Frage zum Stapelüberlauf für folgenden Typ:
data Bin a = Branch (Bin a) a (Bin a) | Leaf a deriving Functor
mit folgendem reißverschluss
data Dir = L | R
data Step a = Step a Dir (Bin a) deriving Functor
data Zip a = Zip [Step a] (Bin a) deriving Functor
instance Comonad Zip where ...
Es ist der Fall, dassZip
ist einComonad
obwohl die Konstruktion seiner Instanz ein wenig haarig ist. Das gesagt,Zip
vollständig mechanisch abgeleitet werden kannTree
und (ich glaube) jeder auf diese Weise abgeleitete Typ ist automatisch einComonad
Daher sollte es meiner Meinung nach so sein, dass wir diese Typen und ihre Comonaden generisch und automatisch konstruieren können.
Ein Verfahren zum Erreichen der Allgemeinheit für die Reißverschlusskonstruktion ist die Verwendung der folgenden Klassen- und Typenfamilie
data Zipper t a = Zipper { diff :: D t a, here :: a }
deriving instance Diff t => Functor (Zipper t)
class (Functor t, Functor (D t)) => Diff t where
data D t :: * -> *
inTo :: t a -> t (Zipper t a)
outOf :: Zipper t a -> t a
Das ist (mehr oder weniger) in den Haskell Cafe-Threads und auf Conal Elliotts Blog aufgetaucht. Diese Klasse kann für die verschiedenen algebraischen Kerntypen instanziiert werden und bietet somit einen allgemeinen Rahmen, um über die Ableitungen von ADTs zu sprechen.
Meine Frage ist also letztendlich, ob wir schreiben können oder nicht
instance Diff t => Comonad (Zipper t) where ...
die verwendet werden könnten, um die oben beschriebene spezifische Comonad-Instanz zu subsumieren:
instance Diff Bin where
data D Bin a = DBin { context :: [Step a], descend :: Maybe (Bin a, Bin a) }
...
Leider hatte ich kein Glück, eine solche Instanz zu schreiben. Ist der,inTo
/outOf
Unterschrift ausreichend? Wird noch etwas benötigt, um die Typen einzuschränken? Ist diese Instanz überhaupt möglich?