Programmierung · Konzepte · Haskell
Was ist eine Funktion höherer Ordnung?
In den meisten Sprachen ist eine Funktion etwas, das man aufruft. In der funktionalen Programmierung ist eine Funktion auch ein Wert: Man kann sie in einer Variablen ablegen, an eine andere Funktion übergeben und eine als Ergebnis zurückbekommen. Eine Funktion höherer Ordnung ist genau die, die eines der beiden letzten Dinge tut. Dieser Leitfaden erklärt, was eine Funktion höherer Ordnung ist, warum map, filter und fold die klassischen Beispiele sind, wie sie Schleifen ersetzen und wie sie in Haskell aussehen.
Die kurze Definition
Eine Funktion höherer Ordnung ist eine Funktion, die eine oder mehrere Funktionen als Argument nimmt, eine Funktion als Ergebnis zurückgibt oder beides. Eine Funktion, die keines von beidem tut — die nur einfache Werte wie Zahlen oder Zeichenketten nimmt und zurückgibt — heißt Funktion erster Ordnung. Der Begriff „höhere Ordnung“ bedeutet schlicht, dass sie auf Funktionen arbeitet, so wie eine gewöhnliche Funktion auf Daten arbeitet.
Das funktioniert nur in einer Sprache, in der Funktionen Werte erster Klasse sind: Dinge, die man benennen, übergeben und zurückgeben kann, genau wie eine Ganzzahl. Haskell, JavaScript, Python, Swift und viele andere behandeln Funktionen so, und das macht Funktionen höherer Ordnung überhaupt erst möglich.
Die drei Klassiker: map, filter und fold
Fast jede funktionale Codebasis stützt sich auf drei Funktionen höherer Ordnung. Jede nimmt eine Funktion als Argument und wendet sie auf eine Sammlung an:
- map wendet eine Funktion auf jedes Element einer Liste an und gibt eine neue Liste der Ergebnisse zurück.
map (+1) [1,2,3]ergibt[2,3,4]— die Funktion(+1)ist das Argument. - filter behält nur die Elemente, für die eine Funktion wahr zurückgibt.
filter even [1,2,3,4]ergibt[2,4]— hier istevendie übergebene Funktion. - fold (auch reduce genannt) reduziert eine Liste auf einen einzigen Wert, indem es die Elemente paarweise verknüpft.
foldr (+) 0 [1,2,3]addiert sie zu6— der Verknüpfungsschritt(+)ist das Funktionsargument.
In jedem Fall lieferst du das kleine Stück Logik — erhöhen, „ist gerade“, addieren — und die Funktion höherer Ordnung übernimmt das Durchlaufen der Liste. Du beschreibst, was mit jedem Element geschehen soll, nicht die Mechanik des Wie beim Durchlaufen.
Wie sie Schleifen ersetzen
In einer imperativen Sprache schriebe man eine Schleife mit Zähler, Akkumulator und explizitem Index. Dieselbe Absicht, mit einer Funktion höherer Ordnung ausgedrückt, passt in eine einzige Zeile, weil die Iteration bereits in map oder fold eingebaut ist. Deshalb stützt sich rein funktionaler Code, der veränderliche Schleifenzähler vermeidet, so stark auf diese Funktionen und auf Rekursion — beide zusammen decken die Arbeit ab, die anderswo Schleifen erledigen. List-Comprehensions sind oft eine lesbare Kurzform für dieselbe Kombination aus map und filter.

Eine Funktion zurückgeben: hier wird es mächtig
Die andere Hälfte der Definition — Funktionen, die Funktionen zurückgeben — ist genauso verbreitet. Eine Funktion kann eine neue, spezialisierte Funktion bauen und zurückgeben. Ein klassisches Beispiel ist ein „Multiplikator-Erzeuger“: Du gibst ihm eine Zahl, und er gibt eine Funktion zurück, die ihre Eingabe mit dieser Zahl multipliziert. Rufe ihn mit 3 auf, und du erhältst eine „mal drei“-Funktion, die du wie jede andere verwenden kannst. Der Erzeuger ist höherer Ordnung, weil sein Ergebnis selbst eine Funktion ist.
In Haskell ist das durch Currying in die Sprache eingewoben: Jede Funktion mit mehreren Argumenten ist in Wahrheit eine Kette von Funktionen mit je einem Argument, von denen jede die nächste zurückgibt. Deshalb funktioniert map (+1) — (+1) ist die Additionsfunktion mit einem bereits gelieferten Argument, die eine Funktion zurückgibt, die noch das andere erwartet. Diese partielle Anwendung sind Funktionen höherer Ordnung in Aktion, oft ohne dass man es bemerkt.
Funktionen höherer Ordnung in Haskell
Haskell macht die Idee in seinen Typsignaturen sichtbar. Der Typ von map wird als map :: (a -> b) -> [a] -> [b] geschrieben. Lies von links nach rechts: Das erste Argument (a -> b) ist selbst eine Funktion — das ist der Teil höherer Ordnung — gefolgt von einer Liste von a, die eine Liste von b erzeugt. Die Pfeile machen auf dem Papier sichtbar, dass eine Funktion übergeben wird. Dasselbe Muster erscheint in filter :: (a -> Bool) -> [a] -> [a] und in der gesamten Standardbibliothek.
Oft übergibst du diese Funktionen inline als Lambdas, kleine anonyme Funktionen, die mit einem Backslash geschrieben werden, etwa map (\x -> x * x) [1,2,3], um jedes Element zu quadrieren. Ob du eine benannte Funktion, einen Operatorabschnitt wie (*2) oder ein Lambda übergibst — es ist derselbe Mechanismus: eine Funktion, die als Wert in eine Funktion höherer Ordnung reist.
Warum sie wichtig sind
Funktionen höherer Ordnung erlauben es, die gemeinsame Form einer Berechnung herauszulösen — „mit jedem Element etwas tun“, „die passenden behalten“, „alle verknüpfen“ — und sie mit unterschiedlicher, eingesteckter Logik wiederzuverwenden. Das Ergebnis: weniger wiederholter Code, Code, der näher an seiner Absicht liest, und kleine, testbare, komponierbare Logikbausteine. Sie sind der Baustein, auf dem ein Großteil der funktionalen Programmierung von Haskell ausgedrückt wird, und kombiniert mit Haskells verzögerter Auswertung erlauben sie sogar, über konzeptionell unendliche Listen zu mappen und zu filtern.
Die ehrlichen Kompromisse
Funktionen höherer Ordnung erfordern etwas Eingewöhnung: Ein foldr oder eine Kette aus map . filter zu lesen ist eine Fertigkeit, und tief verschachtelte Lambdas können schwer nachvollziehbar werden. Funktionen überallhin zu übergeben kann zudem einen Stack-Trace weniger eindeutig machen, wenn etwas schiefgeht. Der Gewinn — deutlich weniger sich wiederholender Iterationscode und neu kombinierbare Logik — erklärt, warum sie sich weit über funktionale Sprachen hinaus verbreitet haben, bis in das alltägliche JavaScript, Python und Swift. Mit Maß eingesetzt, machen sie Code kürzer und klarer; übertrieben eingesetzt, können sie ihn verschleiern wie jedes andere Werkzeug.
Häufig gestellte Fragen
Was ist eine Funktion höherer Ordnung in einfachen Worten?
Eine Funktion höherer Ordnung ist eine Funktion, die eine andere Funktion als Argument nimmt, eine Funktion als Ergebnis zurückgibt oder beides. Statt nur mit einfachen Daten wie Zahlen und Zeichenketten zu arbeiten, arbeitet sie mit Funktionen. Klassische Beispiele sind map, filter und fold, die jeweils eine kleine Funktion nehmen und sie auf eine Liste anwenden.
Ist map eine Funktion höherer Ordnung?
Ja. map nimmt eine Funktion als erstes Argument und wendet sie auf jedes Element einer Liste an, wobei eine neue Liste der Ergebnisse zurückgegeben wird. Da eines seiner Argumente selbst eine Funktion ist, ist map ein Musterbeispiel für eine Funktion höherer Ordnung — ebenso wie filter und fold aus demselben Grund.
Was ist der Unterschied zwischen einer Funktion höherer und erster Ordnung?
Eine Funktion erster Ordnung nimmt und gibt nur gewöhnliche Werte zurück, etwa Zahlen oder Zeichenketten. Eine Funktion höherer Ordnung nimmt eine oder mehrere Funktionen als Argument oder gibt eine Funktion zurück, oder beides. Der Unterschied liegt darin, ob die Funktion nur auf Daten oder auch auf andere Funktionen arbeitet.
Gibt es Funktionen höherer Ordnung nur in Haskell?
Nein. Es gibt sie in jeder Sprache, die Funktionen als Werte erster Klasse behandelt — Werte, die man ablegen, übergeben und zurückgeben kann. Haskell, JavaScript, Python, Swift und viele andere unterstützen sie. Haskell macht die Idee durch seine Typsignaturen und das Currying besonders sichtbar, aber das Konzept ist weit verbreitet.
Eine Linux-Maschine, um deinen Haskell-Code zu bauen und auszuführen
Diese Funktionen höherer Ordnung wirklich auszuprobieren — sie in GHCi zu laden, ein Projekt mit map und fold zu bauen und es dann auszuführen — gelingt auf einer richtigen Linux-Maschine reibungsloser als auf einem Laptop. Ein Cloud-Server gibt dir volle Kontrolle, um GHC und eine Haskell-Toolchain in einer sauberen Umgebung zu installieren und per SSH zu erreichen. Infomaniak — ein Schweizer, datenschutzfreundlicher Anbieter — bietet Cloud-Server genau dafür.
Infomaniak Cloud ansehen →Affiliate-Link — er unterstützt diese kostenlosen Leitfäden.
Stöbere in weiteren klaren Erklärungen in unserem Leitfaden-Index.