Funktionale Programmierung mit Haskell
Aus Wikibooks
Dieses Buch steht im Regal Programmierung.
Dieses Wikibook richtet sich in erster Linie an Informatik-Studenten die sich im Grundstudium mit Haskell rumquälen müssen und nach einer einfachen und klaren Anleitung suchen. Natürlich sind auch alle anderen interessierten Leser willkommen.
Inhaltsverzeichnis |
[Bearbeiten] Einleitung
Die funktionale Programmiersprache Haskell unterscheidet sich grundsätzlich von imperativen Programmiersprachen wie zum Beispiel C, C++ oder Basic. Der größte Unterschied liegt wohl darin, dass in Haskell keine "Seiteneffekte" möglich sind. Das bedeutet, dass es keine Variablen wie in anderen Programmiersprachen gibt. Des weiteren ist der Rückgabewert einer Funktion ausschließlich von den Eingabewerten abhängig. Es gibt keine Schleifen und man gibt dem Computer auch keine Befehle, die er abzuarbeiten hat.
Das Wichtigste, um Haskell zu lernen, ist viel selbst auszuprobieren und selbst zu schreiben. Es geht nicht darum sich die Syntax einzuprägen, sondern um das Lernen, rekursiv zu denken und zu programmieren. Gerade für Leute, die vorher schon mit imperativen Programmiersprachen gearbeitet haben, ist diese Umstellung am Anfang schwierig.
Mit Haskell kann man mit nur wenigen Zeilen Code sehr viel bewerkstelligen und auch viele Probleme sehr elegant lösen. Nach einer gewissen Eingewöhnungsphase ist man auch in der Lage, einen fertigen Quellcode zu verstehen, jedoch sind auch hier Kommentare im Quelltext sinnvoll!
[Bearbeiten] Voraussetzungen
Was braucht man zum Haskell programmieren? Als erstes sollte man sich einen Haskell-Interpreter zulegen. Die 2 verbreitetsten sind wohl der Glasgow Haskell Compiler (GHC) und Haskell User's Gofer System (Hugs). Beide sind auf der Haskell Homepage für verschiedene Betriebssysteme erhältlich. Zudem stellen die meisten Linux-Distributionen fertige Pakete für GHC und/oder Hugs zur Verfügung. Beide Programme sind sich sehr ähnlich und welches man bevorzugt ist Geschmackssache.
Hat man nun den Interpreter seiner Wahl installiert startet man ihn durch Aufruf in der Befehlszeile. Unter Linux sollte ein einfacher Aufruf von "hugs" oder "ghci" ausreichend sein. Unter Windows muss man gegebenenfalls den Installationspfad beachten und die exe-Datei direkt starten.
[Bearbeiten] Grundlagen
[Bearbeiten] Erste Schritte mit dem Interpreter
Hat man den Interpreter gestartet so erblickt man in der untersten Zeile das Wort "Prelude" gefolgt von einem ">". Das Wort vor dem ">" bezeichnet immer das Modul das momentan geladen ist. Prelude ist das Standardmodul in Haskell. Darin befinden sich die grundlegenden Haskell-Funktionen. Diese umfassen z.B. grundlegende mathematische Funktionen wie Addition, Multiplikation usw.. Ein kleines Beispiel:
Prelude>6+7 13 Prelude>
Die Eingabe 6+7 versteht der Interpreter als einen Funktionsaufruf der Funktion (+) mit den Parametern 6 und 7. Das Ergebnis wird berechnet und ausgegeben, danach wartet der Interpreter auf einen neuen Funktionsaufruf. Ein alternativer gleichwertiger Aufruf wäre:
Prelude>(+) 6 7
Und liefert auch das gleiche Ergebnis. Das "+" alleine, ohne Klammerung, ist die infix-Version der Funktion (+). Fügt man nun die Klammern hinzu so müssen beide Parameter nachgestellt werden. Bei "-", "/" und "*" funktioniert dies analog. (+) ist also eine Funktion, sie erhält 2 Eingabeparameter und liefert einen Rückgabewert zurück. Das dies so ist wird in ihrer Signatur festgehalten. Schauen wir uns einmal die Signatur von (+) an:
Prelude>:type (+) (+):: Num a => a -> a -> a Prelude>
Der Kryptische Ausdruck "Num a => a -> a -> a" ist also die Signatur dieser Funktion. "Num a" bedeutet das a für einen beliebigen numerischen Wert steht, dies kann sowohl eine ganze Zahl oder auch eine Gleitkommazahl sein. Die drei mit Pfeilen getrennten a's stehen für drei numerische Werte. Das letzte a ist der Rückgabewert, die davor sind die Eingabeparameter. Jede Funktion in Haskell besitzt eine Signatur.
Der Befehl ":type <expr>" gibt die Signatur eines Ausdrucks zurück, es handelt sich hierbei aber nicht um eine Funktion. Interpreterbefehle beginnen mit einem ":". durch die Eingabe von ":q" oder ":quit" kann man den Interpreter beenden. Durch ":?" erhält man eine Liste aller möglichen Interpreterbefehle.
Noch ein weiteres Beispiel:
Prelude>div 10 4 2 Prelude>10 `div` 4 2 Prelude>
Die Funktion div führt eine ganzzahlige Division durch. Dabei wird der Rest einfach abgeschnitten. Hier ist jetzt `div` die infix-Variante von div. Dieser Trick funktioniert übrigens bei allen Funktionen mit 2 Parametern. So ist auch "10 `mod` 3" gleichbedeutend mit "mod 10 3" (mod liefert den Rest einer ganzzahligen Division).
Aber der Interpreter kann noch mehr. Es folgt ein weiteres kleines Beispiel, indem Listen zum Einsatz kommen. Listen sind sehr mächtig in Haskell.
Prelude>sum [1,2,3,4] 10 Prelude>
Die Funktion sum bekommt eine Liste von numerischen Werten als Eingabe, und liefert die Summe ihrer Elemente zurück. Eine kleine Abwandlung mit der Funktion product dazu:
Prelude>product [1..4] 24 Prelude>
Diesmal wurde die Funktion product verwendet, die das Produkt der Elemente zurück liefert. Noch zu erwähnen wäre das anstatt jedes Element einzeln aufzulisten hier eine abgekürzte Schreibweise verwendet wird. Durch [1..4] werden ganzzahlige Werte ergänzt. Würde man stattdessen [1,3..9] schreiben, würden nur die ungeraden ganzzahligen Werte dazwischen Eingefügt werden. Die Möglichkeiten hier sind sehr großzügig, auch unendliche Listen sind möglich (zb. [1..]), aber mit Vorsicht zu genießen, da dadurch Endlosschleifen entstehen können (Mit Strg + C bricht man einen Rechenvorgang im Interpreter ab). Durch das obige Beispiel lässt sich einfach die Fakultät einer Zahl berechnen, wenn man die vier austauscht.
[Bearbeiten] Das erste Programm
Haskellprogramme werden in Dateien mit der Endung ".hs" gespeichert. Zum Erstellen eignet sich ein beliebiger Texteditor. Geladen werden diese dann im Interpreter durch den Befehl ":load <[Pfad/]Dateiname>". Es folgt die Haskellvariante eines "Hello World" Programms:
x :: [Char] x = "Hello World!"
Zuerst erfolgt die Signatur der Funktion x, x erhält keine Eingabeparameter und gibt eine Liste von Zeichen zurück. Man kann die Signatur auch weglassen und der Interpreter wird dies automatisch übernehmen, doch es dient der besseren Lesbarkeit diese einzufügen.
Gefolgt von der Definition von x. Zu beachten ist, dass x keine Variable ist. Würde man darunter eine weitere Zeile mit x = "blabla" einfügen, würde dies unweigerlich zu einer Fehlermeldung führen. Um nun das Programm zu testen, muss zuerst die Datei geladen werden (durch :load bzw. :l gefolgt vom Dateinamen). Nun verändert sich das Prelude zu einem Main. Main ist das neue Modul das aus der Datei geladen wurde. Das Modul Prelude ist dennoch verfügbar und dessen Funktionen können immer noch aufgerufen werden.
Um nun die Konstante ( = eine Funktion ohne Eingabeparameter) x aufzurufen, einfach x eintippen.
Main> x "Hello World!"

