Folgen Sie der Monaden-Funktion in Haskell

8

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:

%Vor%

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.

    
AJFarmar 07.12.2014, 13:04
quelle

2 Antworten

10

Es ist in der Tat nicht möglich, eine Funktion unsequence allein mit Monaden zu erstellen. Der Grund ist:

  1. Sie können sicher und einfach eine monadische Struktur aus einem Wert mit return erstellen.
  2. Es ist jedoch nicht sicher, einen Wert aus einer monadischen Struktur zu entfernen. Zum Beispiel können Sie ein Element nicht aus einer leeren Liste entfernen (d. H. Eine Funktion vom Typ [a] -> a ist nicht sicher).
  3. Daher haben wir eine spezielle Funktion (d. h. >>= ), 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:

%Vor%

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:

%Vor%

Eine comonadische Struktur ist das Gegenteil einer monadischen Struktur. Insbesondere:

  1. Sie können einen Wert aus einer comonadischen Struktur sicher extrahieren.
  2. Sie können jedoch nicht sicher eine neue comonadische Struktur aus einem Wert erstellen, weshalb die Funktion 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:

%Vor%

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:

%Vor%

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:

%Vor%

Ich hoffe, das hilft.

    
Aadit M Shah 07.12.2014, 14:54
quelle
10

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

schreiben %Vor%

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 .

    
danidiaz 07.12.2014 14:14
quelle