Woher kommen die foldl / foldr-Implementierungen von Foldable für binäre Bäume in haskell?

8

Ich arbeite durch Lernen Sie ein Haskell, und ich bin auf dem Abschnitt über Monoids. In diesem Abschnitt definiert der Autor die foldMap-Methode für einen Baum wie folgt:

%Vor%

Was gut funktioniert und ist total baller. Dann sagt er: "Jetzt, wo wir eine faltbare Instanz für unseren Baumtyp haben, bekommen wir foldr und foldl kostenlos!" und zeigt den folgenden Code:

%Vor%

Jetzt bin ich verwirrt. Nirgends wurde eine Implementierung für Foldl oder Foldr für Trees geschrieben. Die Funktionen scheinen ähnlich wie die Faltkarte zu funktionieren, aber den anfänglichen Akkumulator als den Kopf des Baumes zu setzen und dann über das entsprechende Monoid zu falten. Aber es kann nicht wirklich so funktionieren, weil foldl und foldr allgemeinere Funktionen als die Monoiden '+' und '*' als Argumente. Wo werden foldl und foldr tatsächlich implementiert, wie funktionieren sie, und warum führt die Definition von foldMap dazu, dass sie existieren?

    
MYV 26.05.2013, 08:11
quelle

2 Antworten

14

Sehen Sie sich die Quelle von Foldable an. . Er definiert foldr mit foldMap und umgekehrt, also reicht es aus, die für Sie bequemere zu definieren (obwohl die Implementierung beider Möglichkeiten Ihnen einige Leistungsvorteile bringen kann):

%Vor%

Sehen wir uns an, was hier an einem Beispiel passiert. Nehmen wir an, wir werden eine Liste mit [i, j, k] falten. Die rechte Falte mit f und z ist

%Vor%

Dies kann alternativ als

ausgedrückt werden %Vor%

Mit f konvertieren wir jedes Element der Liste in einen Endomorphismus am b und komponieren sie zusammen . Endomorphismen bilden nun ein Monoid, das in Haskell mit Endo ausgedrückt wird: sein mempty ist nur id und mappend ist . . Also können wir es als

umschreiben %Vor%

und wir können den inneren Teil als foldMap (Endo . f) [i, j, k] ausdrücken.

Zusammenfassend: Die Schlüsselidee ist, dass Endomorphismen über einer Domäne ein Monoid bilden und f :: a -> (b -> b) Elemente von a in Endomorphismen über b abbildet.

Das Gegenteil wird ausgedrückt als

%Vor%

Hier haben wir f :: a -> m , wobei m ein Monoid ist, und wenn wir es mit mappend zusammensetzen, erhalten wir mappend . f :: a -> (m -> m) , was ein Element x vom Typ a und eine Funktion für m ergibt. Das konvertiert u :: m in mappend (f u) k . Und dann benutzt es diese Funktion, um alle Elemente der Struktur zu falten.

    
Petr Pudlák 26.05.2013, 11:06
quelle
3

Von Ссылка :

%Vor%

Sie haben also Standardimplementierungen (in diesem Fall sogar zirkulär). Deshalb gibt es einen Kommentar: "Minimale vollständige Definition: foldMap oder foldr." in der Beschreibung der Klasse Foldable type (siehe Ссылка )

Ein einfacheres Beispiel für diese Technik ist die Klasse Eq type, wobei (==) und (/=) in Bezug aufeinander definiert sind, aber natürlich müssen Sie mindestens eine davon in einer Instanz implementieren (sonst Sie erhalten eine Endlosschleife).

    
Landei 26.05.2013 10:46
quelle

Tags und Links