Beim Lesen dieses klassischen Papiers bin ich auf Paramorphismen fixiert. Leider ist der Abschnitt ziemlich dünn und die Wikipedia-Seite sagt nichts.
Meine Haskell-Übersetzung lautet:
para :: (a -> [a] -> b -> b) -> b -> [a] -> b
para f base = h
where
h [] = base
h (x:xs) = f x xs (h xs)
Aber ich verstehe das nicht - ich habe keine Intuition für die Typensignatur oder das gewünschte Ergebnis.
Was ist ein Paramorphismus und was sind einige nützliche Beispiele in Aktion?
Ja, ich habe diese Fragen gesehen , aber sie behandeln Paramorphismen nicht direkt und verweisen nur auf Ressourcen , die als Referenz hilfreich sein können, aber nicht als Lernmaterial.
haskell
recursion
functional-programming
higher-order-functions
Matt Fenwick
quelle
quelle
para f base xs = foldr (uncurry f) base $ zip xs (tail $tails xs)
, denkt nach.para f base xs = foldr g base (init $ tails xs) where g (x:xs) = f x xs
. Dies erinnert an Common Lispmaplist
.Antworten:
Ja, das ist
para
. Vergleiche mit Katamorphose oderfoldr
:Einige Leute nennen Paramorphismen "primitive Rekursion", während Katamorphismen (
foldr
) "Iteration" sind.Wenn
foldr
den beiden Parametern für jedes rekursive Unterobjekt der Eingabedaten ein rekursiv berechneter Wert zugewiesen wird (hier ist dies das Ende der Liste), erhaltenpara
die Parameter sowohl das ursprüngliche Unterobjekt als auch den daraus rekursiv berechneten Wert.Eine Beispielfunktion, die sich gut ausdrückt,
para
ist die Sammlung der richtigen Suffizien einer Liste.damit
Möglicherweise ist es noch einfacher
in dem der "cons" -Zweig sein rekursiv berechnetes Argument ignoriert und nur den Schwanz zurückgibt. Faul ausgewertet findet die rekursive Berechnung nie statt und der Schwanz wird in konstanter Zeit extrahiert.
Sie können festlegen ,
foldr
mitpara
ganz leicht; es ist ein wenig schwieriger zu definieren ,para
ausfoldr
, aber es ist durchaus möglich, und jeder sollte wissen , wie es geht!Der Trick , um die Definition
para
mitfoldr
ist eine rekonstruieren Kopie der Originaldaten, so dass wir bei jedem Schritt Zugriff auf eine Kopie des Schwanzes gewinnen, auch wenn wir keinen Zugriff auf das Original hatten. Am Ende wirdsnd
die Kopie der Eingabe verworfen und nur der Ausgabewert angegeben. Es ist nicht sehr effizient, aber wenn Sie an Ausdruckskraft interessiert sind, erhaltenpara
Sie nicht mehr alsfoldr
. Wenn Sie diesefoldr
-kodierte Version von verwendenpara
, dauertsafeTail
es schließlich linear, das Ende Element für Element zu kopieren.Das war's also: Es
para
ist eine bequemere Version, mitfoldr
der Sie sofort auf das Ende der Liste sowie auf den daraus berechneten Wert zugreifen können.Im allgemeinen Fall wird mit einem Datentyp gearbeitet, der als rekursiver Fixpunkt eines Funktors generiert wurde
du hast
und wieder sind die beiden zueinander definierbar, mit
para
definiertencata
mit dem gleichen „eine Kopie“ TrickAuch dies
para
ist nicht aussagekräftiger alscata
, aber bequemer, wenn Sie einen einfachen Zugriff auf Unterstrukturen der Eingabe benötigen.Edit: Ich erinnerte mich an ein anderes schönes Beispiel.
Betrachten Sie binäre Suchbäume, die durch
Fix TreeF
where angegeben werdenund versuchen Sie, die Einfügung für binäre Suchbäume zuerst als
cata
, dann als zu definierenpara
. Sie werden diepara
Version viel einfacher finden, da Sie an jedem Knoten einen Teilbaum einfügen müssen, den anderen aber beibehalten müssen.quelle