Was ist Bananensplit und Fusion in der funktionalen Programmierung?

22

Diese Begriffe wurden in meinem Universitätslehrgang erwähnt. Schnelles googeln hat mich auf einige Studienarbeiten hingewiesen, aber ich suche nach einer einfachen Erklärung.

Gaurav Abbi
quelle
@jozefg: Danke für den Link zu deinem Beitrag. Eine Frage dazu. In dem Satz "Eine Algebra in diesem Sinne ist ein Paar aus einem Objekt C und einer Karte FC → C." soll C wirklich ein Objekt oder eher eine Kategorie sein? Mit anderen Worten, ich bin nicht sicher, ob F einen Funktor in einer Kategorie bezeichnet, und die F-Algebren sind die von diesem Funktor induzierten Algebren, ob F ein bestimmter Pfeil von einem Objekt auf sich selbst ist.
Giorgio,
Cist ein Objekt in irgendeiner Kategorie (sagen wir mal CC), Fist ein Funktor von CC -> CCdaher wird es CCauf sich selbst abgebildet. Jetzt F CC -> CCist nur ein normaler Pfeil in der Kategorie CC. Eine FAlgebra ist also ein Objekt C : CCund ein Pfeil F C -> CinCC
Daniel Gratzer

Antworten:

4

Obwohl bereits 2 Antworten gegeben wurden, glaube ich, dass der "Bananensplit" hier noch nicht erklärt wurde.

Es ist in der Tat definiert in "Funktionale Programmierung mit Bananen, Linsen, Umschlägen und Stacheldraht, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991"; Dieser Artikel ist (für mich) schwer zu lesen, da er häufig Squiggol verwendet. "Ein Tutorial zur Universalität und Ausdruckskraft von Fold, Graham Hutton, 1999" enthält jedoch eine Definition, die einfacher zu analysieren ist:

Als ein einfaches erstes Beispiel für die Verwendung von fold Tupel zu erzeugen, sollten Sie die Funktion sumlength dass berechnet die Summe und Länge einer Liste von Zahlen:

sumlength :: [Int] → (Int,Int)
sumlength xs = (sum xs, length xs)

Durch eine einfache Kombination der Definitionen der Funktionen Summe und Länge unter Verwendung der Falte gegeben früher die Funktion sumlength kann als eine einzelne Anwendung neu definiert wird von falten , dass erzeugt ein Paar von Zahlen aus einer Liste von Zahlen:

sumlength = fold (λn (x, y) → (n + x, 1 + y)) (0, 0)

Diese Definition ist effizienter als die ursprüngliche Definition, da nur ein einziger Durchlauf über die Argumentliste erfolgt und nicht zwei separate Durchläufe. Verallgemeinert aus diesem Beispiel jedes Paar von Anwendungen der Falte kann immer auf die gleiche Liste kombiniert werden , um eine einzelne Anwendung zu geben , faltet , dass erzeugt ein Paar, unter Berufung auf das so genannte ‚Banana Split‘ Eigentum der Falte (Meijer, 1992) . Der seltsame Name dieser Eigenschaft rührt von der Tatsache her, dass der Fold- Operator manchmal in Klammern (| |) geschrieben wird, die Bananen ähneln, und der Pairing-Operator manchmal als Split bezeichnet wird. Daher kann ihre Kombination als Bananensplit bezeichnet werden!

Klaas van Schelven
quelle
19

Dies ist also ein Verweis auf einen Artikel von Meijer und einigen anderen mit dem Titel " Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire ". Die Grundidee ist, dass wir jeden rekursiven Datentyp annehmen können, wie zum Beispiel

 data List = Cons Int List | Nil

und wir können die Rekursion in eine Typvariable ausklammern

 data ListF a = Cons Int a | Nil

Der Grund, warum ich das angehängt habe, Fist, dass dies jetzt ein Funktor ist! Es erlaubt uns auch, Listen zu imitieren, aber mit einem Twist: Um Listen zu erstellen, müssen wir den Listentyp verschachteln

type ThreeList = ListF (ListF (ListF Void)))

Um unsere ursprüngliche Liste wiederherzustellen, müssen wir diese unendlich verschachteln . Das wird uns einen Typ geben, ListFFwo

  ListF ListFF == ListFF

Dazu definieren Sie einen "Fixpunkttyp"

  data Fix f = Fix {unfix :: f (Fix f)}
  type ListFF = Fix ListF

Als Übung sollten Sie überprüfen, ob dies unserer obigen Gleichung entspricht. Jetzt können wir endlich definieren, was Bananen (Katamorphismen) sind!

  type ListAlg a = ListF a -> a

ListAlgs ist der Typ von "Listenalgebren", und wir können eine bestimmte Funktion definieren

  cata :: ListAlg a -> ListFF -> a
  cata f = f . fmap (cata f) . unfix

Außerdem

  cata :: ListAlg a -> ListFF -> a
  cata :: (Either () (Int, a) -> a) -> ListFF -> a
  cata :: (() -> a) -> ((Int, a) -> a) -> ListFF -> a
  cata :: a -> (Int -> a -> a) -> ListFF -> a
  cata :: (Int -> a -> a) -> a -> [Int] -> a

Ähnlich aussehend? cataist genau das gleiche wie rechts falten!

Was wirklich interessant ist, ist, dass wir dies über mehr als nur Listen hinweg tun können. Jeder Typ, der mit diesem "Fixpunkt eines Funktors" definiert ist, hat ein cataund um sie zu berücksichtigen, müssen wir nur die Typensignatur lockern

  cata :: (f a -> a) -> Fix f -> a

Dies ist eigentlich inspiriert von einem Stück Kategorietheorie, über das ich geschrieben habe , aber dies ist das Fleisch der Haskell-Seite.

Daniel Gratzer
quelle
2
ist es erwähnenswert , dass die Bananen sind (| |) Klammern , dass die ursprüngliche Papier Verwendungen Cata definieren
jk.
7

Obwohl Jozefg eine Antwort lieferte, bin ich mir nicht sicher, ob es die Frage beantwortet hat. Das "Fusionsgesetz" wird in der folgenden Abhandlung erläutert:

Ein Tutorial zur Universalität und Ausdruckskraft von Fold, GRAHAM HUTTON, 1999

Grundsätzlich heißt es, dass man unter bestimmten Bedingungen die Zusammensetzung einer Funktion kombinieren ("verschmelzen") und so im Grunde genommen zu einer einzigen Falte falten kann

h · fold gw = fold fv

Die Voraussetzungen für diese Gleichstellung sind

hw = v
h (gxy) = fx (hy)

Das "Bananensplit" - oder "Bananensplitgesetz" stammt aus dem Artikel

Funktionale Programmierung mit Bananen, Linsen, Umschlägen und Stacheldraht, Erik Meijer Maarten Fokkinga, Ross Paterson, 1991

Leider ist der Artikel sehr schwer zu entschlüsseln, da er den Bird-Meertens-Formalismus verwendet, so dass ich weder den Kopf noch den Schwanz daraus machen konnte. Soweit ich das "Bananensplit-Gesetz" verstanden habe, heißt es, dass Sie zwei Falten, die auf dasselbe Argument angewendet werden, zu einer einzigen Falte zusammenfassen können.

Jackie
quelle