Ich habe einige Probleme damit, die Gegenfunktion von Haskells sequence
-Funktion zu entwerfen, von der Hoogle sagt, dass sie noch nicht existiert. So verhält es sich:
Mein Problem ist eine Funktion wie folgt:
%Vor%Damit es sich so verhält:
%Vor%Ich weiß nicht, ob das möglich ist, weil ich irgendwann die Monade verlassen würde, aber ich habe einen Anfang gemacht, obwohl ich nicht weiß, wie man einen Haltepunkt für diese rekursive Funktion setzt:
%Vor% Mir ist klar, dass ich einen Haltepunkt brauche, wenn m
hier gleich return []
ist, aber nicht alle Monaden Eq
Instanzen haben, also wie kann ich das machen? Ist das überhaupt möglich? Wenn ja, warum und warum nicht? Bitte sag mir das.
Es ist in der Tat nicht möglich, eine Funktion unsequence
allein mit Monaden zu erstellen. Der Grund ist:
return
erstellen. [a] -> a
ist nicht sicher). >>=
), die einen Wert aus einer monadischen Struktur (falls vorhanden) sicher entfernt, verarbeitet und eine andere sichere monadische Struktur zurückgibt. Daher ist es sicher, aus einem Wert eine monadische Struktur zu erstellen. Es ist jedoch nicht sicher, einen Wert aus einer monadischen Struktur zu entfernen.
Angenommen, wir hätten eine Funktion extract :: Monad m => m a -> a
, die einen Wert aus einer monadischen Struktur "sicher" entfernen könnte. Wir könnten dann unsequence
wie folgt implementieren:
Es gibt jedoch keinen sicheren Weg, um einen Wert aus einer monadischen Struktur zu extrahieren. Daher geben unsequence []
und unsequence Nothing
undefined
zurück.
Sie können jedoch eine unsequence
-Funktion für Strukturen erstellen, die sowohl monadisch als auch comonadisch sind. A Comonad
ist wie folgt definiert:
Eine comonadische Struktur ist das Gegenteil einer monadischen Struktur. Insbesondere:
duplicate
sicher eine neue comonadische Struktur aus einem Wert erstellt. Denken Sie daran, dass die Definition von unsequence
sowohl return
als auch extract
benötigt? Sie können nicht sicher eine neue comonadische Struktur aus einem Wert erstellen (d. H., Comonadische Strukturen haben nicht return
). Daher ist die Funktion unsequence
wie folgt definiert:
Interessanterweise arbeitet sequence
an einfach monadischen Strukturen. Man könnte also annehmen, dass unsequence
auf intuitive Weise auf comonadischen Strukturen basiert. Allerdings nicht, weil Sie zuerst die Liste aus der comonadischen Struktur extrahieren und dann jedes Element der Liste in eine monadische Struktur einfügen müssen.
Die allgemeine Version der Funktion unsequence
konvertiert eine comonadische Listenstruktur in eine Liste monadischer Strukturen:
Andererseits funktioniert die Funktion sequence
auf einfach monadischen Strukturen, weil Sie die Liste der monadischen Strukturen einfach in eine monadische Listenstruktur falten, indem Sie alle Monaden verketten:
Ich hoffe, das hilft.
Sie können kein unsequence :: (Monad m) => m [a] -> [m a]
haben. Das Problem liegt bei Listen: Sie können nicht sicher sein, wie viele Elemente Sie mit einer Liste erhalten, und das kompliziert jede sinnvolle Definition von unsequence
.
Interessanterweise, wenn Sie absolut, 100% sicher sind, dass die Liste innerhalb der Monade unendlich ist, könnten Sie etwas schreiben wie:
%Vor%Und es würde funktionieren!
Stellen Sie sich auch vor, dass wir einen Pair
funktor herumliegen haben. Wir können unsequencePair
als
Im Allgemeinen stellt sich heraus, dass Sie unsequence
nur für Funktoren mit der Eigenschaft definieren können, dass Sie immer zwei Werte zusammen "zippen" können, ohne Informationen zu verlieren. Unendliche Listen (in Haskell ist ein möglicher Typ für sie Cofree Identity
) sind ein Beispiel. Der Pair
-Funktor ist ein anderer. Aber keine konventionellen Listen oder Funktoren wie Maybe
oder Either
.
Im Paket distributive
, Es gibt eine Typklasse namens Distributive
, die diese Eigenschaft einkapselt. Ihr unsequence
heißt dort distribute
.