Funktionale Programmierung mit Haskell/ Der Interpreter ghci
In diesem Buch beschränken wir uns auf den Glasgow Haskell Compiler ghc, der sehr verbreitet ist und die meisten Funktionen bietet. Den ghc bezieht man über die gängigen Haskell-Seiten (siehe Quellen und Weiterführende Hinweise, [1] zum Download und [3] für die Dokumentation. Mit ghci
ruft man den Compiler interaktiv auf.
ghci als Taschenrechner
BearbeitenHier eine erste "Aufwärmübung" mit dem ghci :
$>ghci
GHCi, version 6.10.4: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> 3+3 -- Hinter zwei Minuszeichen kann man einen Kommentar schreiben
6
Prelude> 4.0 * 3.2 -- Multiplikation zweier Zahlen
12.8
Prelude>10^2 -- Exponentialfunktion mit ganzen Zahlen geht so
100
Prelude> 10**2.4 -- Exponentialfunktion mit gebrochenen Zahlen geht so
251.18864315095797
Prelude> pi -- Haskell kennt auch pi
3.141592653589793
Prelude> 8*4+4 -- Punkt vor Strich geht wie erwartet
36
Prelude>8*(4+4) -- Klammerrechnung ebenso
64
Prelude> it + 5 -- hinter it steckt immer der zuletzt errechnete Wert, hier also 64
69
Prelude> :quit -- Ein Doppelpunkt leitet ein ghci-Kommando ein. Mit :q oder :quit wird der Compiler verlassen
Leaving GHCi.
$>
Funktionen im ghci
BearbeitenFunktionen werden in den nächsten Kapiteln intensiv behandelt; an dieser Stelle folgt nur ein Blick auf deren allgemeine Eigenschaften. Beim Start von ghci stehen schon einige wichtige Funktionen zur Verfügung, die im Modul Prelude zusammengefasst sind (daher auch der Ausdruck Prelude>
im Prompt des ghci). Drückt man im ghci zwei Mal den Tabulator, werden alle aktuell zur Verfügung stehenden Funktionen angezeigt. Zwei davon sind div
und mod
zur Division von ganzen Zahlen. Sie werden normalerweise in polnischer Notation verwendet, können aber auch (mit Hochkommas versehen) mit infix-Notation verwendet werden. Parameter sind Klammern nur erlaubt, wenn sie je einen Parameter beinhalten:
Prelude> div 10 3 -- 10 geteilt durch 3 ist 3 (der Rest der Division wird nicht berücksichtigt)
3
Prelude> mod 10 3 -- 10 geteilt durch 3 ist 3, Rest 1 (hier wird nur der Rest berücksichtigt)
1
Prelude> 10 `mod` 3 -- Man kann die Funktion auch mit infix-Notation schreiben, dann muss sie in Hochkomma gesetzt werden
1
Prelude> sqrt 16 -- Die Quadratwurzel-Funktion hat nur einen Operanden
4.0
Prelude> sqrt (8+sqrt 64) -- Die Klammernsetzung bei Haskell ist bei verschachtelten Ausdrücken wichtig
4.0
Prelude> div (10) (3) -- Auch einzelne Parameter können geklammert werden
3
Prelude> (10) `mod` 3 -- Auch einzelne Parameter können geklammert werden
1
Prelude> (10) `mod` (3) -- Auch einzelne Parameter können geklammert werden
1
Prelude> sum [1,2,3] -- Diese Summenfunktion bezieht sich auf eine Liste mit drei Werten
6
Prelude>:q -- verlassen des ghci
Leaving GHCi.
$>
Es fällt auf, dass sqrt
die Zahl 4.0 mit einer Nachkommastelle liefert, und sum
die Zahl 6 ohne Nachkommastellen ausgibt. Dazu später mehr.
Variablen im ghci
BearbeitenIm ghci können Variablen verwendet werden. Eine solche Zuweisung muss mit dem Befehl let
eingeleitet werden, möglich sind auch Anweisungen mit let
/in
oder let
/where
. Variablen müssen immer mit einem Kleinbuchstaben beginnen, danach dürfen Großbuchstaben, Ziffern und einige Sonderzeichen folgen:
Prelude> let a = 2 -- Zuweisung der Zahl 2 an die Variable a
Prelude> a -- So wird der Wert der Variablen a ausgegeben
2
Prelude> let b = 2*a -- Rechnen mit Variablen geht wie erwartet
Prelude> b -- So wird der Wert der Variablen b ausgegeben
4
Prelude> let a=2; b=7 in (a+b)*5 -- Mehrere Variablen in einer let/in-Anweisung, der Wert wird sofort ausgegeben.
45
Prelude> let x=y*2 where y=2 -- Mehrere Variablen in einer let/where-Zuweisung, der Wert wird nicht sofort ausgegeben.
Prelude> x
4
Prelude> y -- Die y-Variable war nur temporär, der ghci kennt sie jetzt nicht mehr
<interactive>:17:1: Not in scope: `y'
Prelude> let a = "Hallo Welt" -- Jetzt steckt hinter der Variablen a ein String
Prelude> a
"Hallo Welt"
Prelude> let b = 2*a -- Klar, dass das nicht geht: Einen String kann man nicht multiplizieren
<interactive>:3:2: parse error on input `='
Prelude> let A=4 -- Fehler: Variablen müssen mit Kleinbuchstaben beginnen
<interactive>:20:5: Not in scope: data constructor `A'
Prelude> let a = 2*a -- Fehler! Wenn der Wert der Variablen a abgefragt wird, geht der ghci in eine Endlosschleife!
- Die rekursive Zuweisung
let a = 2*a
ist in vielen Programmiersprachen ganz normal, aber in Haskell ist sie keine gute Idee. Haskell erlaubt zwar die Definition wegen der Lazy Evaluation, aber beim Abfragen von a gerät der ghci in eine Endlos-Schleife.
- Im obigen Beispiel wird
a
erst als numerischer Wert verwendet und später als String. Das klappt im ghci, aber in einem Haskell-Programm ist eine Verwendung der gleichen Variablen für verschiedene Datentypen wegen der strikten Typisierung unmöglich.
weitere ghci-Funktionen
BearbeitenPrelude> :!pwd -- mit :! wird der folgende Befehl an das Betriebssystem abgesetzt, hier die Ausgabe des Directories
/Users/Ladon/haskell
Prelude> :{ -- Befehle können auch über mehrere Zeilen gehen
Prelude | let {x=7;
Prelude | y=10;z=x*y;
Prelude | }
Prelude | :}
Prelude> z
70
Prelude> :show bindings -- Zeigt die aktuell im ghci verwendeten Variablen an.
z :: Integer = 70
x :: Integer = 7
y :: Integer = 10
it :: Integer = 70
Prelude>8 == 4+4 -- So sieht ein Vergleich aus: Wenn acht gleich vier plus vier ist, erscheint TRUE als Wahrheitswert
True
Prelude>8 == 4+5 -- Ein Vergleich, der fehlschlägt
False
Prelude>