Developer Community

Funktionales Programmieren mit Beispielen in Haskell und Java

05.09.2017

Funktionales Programmieren gibt es schon seit der Erfindung von Lisp in den 60er Jahren, und es war auch kurze Zeit in der Entwicklung von K.I. ein nennenswerter Teil der Softwareentwicklung. Nachdem dann durch den Boom von objektorientierter Programmierung funktionale Sprachen in den Hintergrund geraten sind, gibt es heute wieder Tendenzen funktionale Elemente in Mainstream-Sprachen aufzunehmen.
Eine der striktesten Verfechter des funktionalen Paradigmas ist die Programmiersprache Haskell, und um den Ursprung einiger Features, die nun mit Java 8 Einzug halten zu kennen, betrachten wir Beispiele aus Haskell und vergleichen diese mit entsprechendem Java Code.

Was macht funktionales Programmieren aus?

Die wichtigste Eigenschaft ist es eine Funktion als Parameter bzw. Rückgabewert für eine andere Funktion benutzen zu können. Die Idee dahinter ist es Algorithmen parametrisieren zu können, das einfachste Beispiel wäre eine generische Sortierfunktion, die eine Liste von Personen nach "Nachname" oder "Alter" sortiert - je nachdem welche Vergleichsfunktion ich mit übergebe.
Ein weiteres bekanntes Beispiel für Funktionales Programmieren ist in Clustersystemen wie Hadoop, wo über "map & fold" große Datenmengen verarbeitet werden. Daten werden dabei mit `map` und einer Funktion transformiert und mit `fold` zu einem Endergebnis aggregiert.
Der Vorteil dabei ist, dass die Funktion `map` mehrere kleinere Datenmengen genauso transformiert wie eine riesige, dadurch kann die Arbeit auf mehrere Cores/Rechner parallelisiert werden. 

Weitere Konzepte die man von Haskell abschauen kann

Daten sind in Haskell per Default "immutable", was imperformant klingt, aber in der Praxis wenig problematisch ist - die Vorteile, die sich daraus ergeben sind weit einfacheres paralleles Programmieren da kein Thread Daten eines anderen Threads manipulieren kann. "Shared memory" zu verwenden ist möglich,
aber durch intelligente Abstraktion stark vereinfacht und weitaus weniger fehleranfällig.
IO-Interaktionen mit User, Netzwerk, etc. sind immer gekapselt und sind leicht von reinen Funktionen unterscheidbar, sodass bei Fehlern debugging selten notwendig ist, da das Eingrenzen dieser weit leichter wird.
Ein weiteres Feature von Haskell ist das starke Typsystem in dem viele Fehler schon zur Compiletime abgefangen werden. Java hat aufgrund seiner Historie einige Schwächen, die explizite Typcasts notwendig machen, was recht fehleranfällig ist. So kann z.B. die Verwendung von "Arrays" zu Laufzeitfehlern führen, während "Generics", die übrigens Phil Wadler, einer der Erfinder von Haskell, eingeführt hat, bessere Compiler-Prüfungen ermöglichen. 

Zusatzmaterial

Die Haskell Syntax ist für Anfänger mehr als nur gewöhnungsbedürftig, ist aber durchaus mit etwas Aufwand zu verstehen, alle Beispiele sind in Java nachempfunden, wobei manchmal Details, die sich erfahrene Entwickler dazu denken können weggelassen wurden, um sich auf die Idee konzentrieren zu können bzw. Platz zu sparen.
Das Kapitel "Funktor" und der Abschnitt "Typinferenz" waren als Bonusmaterial für Interessierte geplant und sind im Vortrag nicht vorgekommen. 
Das Zusatzmaterial finden Sie auch hier...