foldr
ist eines dieser komischen Werkzeuge wie Fahrräder, die wirklich einfach zu bedienen sind, sobald man den Dreh raus hat, aber schwer von Anfang an zu lernen. Nach einigen Jahren Erfahrung, bin ich wirklich gut darin gewesen, Probleme zu erkennen, die ich mit foldr
lösen kann, und zwar sofort und korrekt, aber es könnte leicht eine Weile dauern, um herauszufinden, was genau ich getan habe Detail zu erklären!
Vom praktischen Standpunkt denke ich normalerweise an foldr
in vage Fortsetzung-passender Sprache. Das Ignorieren der „einfachen“ Fall, in dem foldr
nur auf drei Argumente angewendet wird, sieht eine Anwendung von foldr
wie folgt aus:
foldr go finish xs acc1 acc2 ... where
finish acc1 acc2 ... = ?
go x cont acc1 acc2 ... = ?
acc1
usw. sind Akkumulatoren bestanden „von links nach rechts“.Das Ergebnis besteht konzeptuell aus einem einzelnen Wert, der "von rechts nach links" übergeben wird.
finish
erhält die Endwerte der Akkumulatoren und erzeugt etwas vom Ergebnistyp. Es ist in der Regel der einfachste Teil zu schreiben, weil
foldr go finish [] acc1 acc2 ...
=
finish acc1 acc2 ...
Also, wenn Sie nur herausfinden, was Sie wollen Falte zu erzeugen, schreiben finish
ziemlich mechanisch ist.
go
erhält ein einzelnes Containerelement, eine "Fortsetzung" und die Akkumulatoren. Er übergibt modifizierte Werte, wenn diese Akkumulatoren zur Fortsetzung "weiterleiten", um ein Ergebnis zu erhalten, und verwendet dieses Ergebnis, um ein eigenes Ergebnis zu erstellen.
foldl
ist ein besonders einfacher Fall, weil seine go
Funktion nur das Ergebnis zurückgibt, das es vom Falten des Rests des Containers mit einem neuen Akkumulatorargument erhält. Ich denke, es ist ein bisschen aufschlussreicher, ein Beispiel zu betrachten, das ein bisschen mehr tut. Hier ist eine, die einen Container mit Zahlen nimmt und eine Liste von Paaren erstellt, die eine laufende Summe und ein laufendes Produkt darstellen.
sumsProducts :: (Num n, Foldable f) => f n -> [(n, n)]
sumsProducts xs = foldr go finish xs 0 1
where
finish total prod = [(total, prod)]
go x cont total prod =
(total, prod) : cont (x + total) (x * prod)
1: Parameter Ihrer 'g' Funktion, 2.' const x = \ y -> x' – Carsten