Funktionale Programmierung mit Haskell/ Der Interpreter ghci

Aus Wikibooks

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[Bearbeiten]

Hier eine erste "Aufwärmübung" mit dem ghci :

Dialog in 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.
$>
Hinweis: Die Eingabe $> ghci steht für den Aufruf des ghci aus einer Unix-Shell

Funktionen im ghci[Bearbeiten]

Funktionen 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:

Dialog in ghci
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[Bearbeiten]

Im 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:

Dialog in ghci
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[Bearbeiten]

Dialog in ghci
Prelude> :!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>
Hinweis: die Kommentare, die mit -- beginnen, sind hier nur zur Erläuterung angefügt. In einem echten ghci-Dialog dürfen sie nicht verwendet werden, da sie das Ergebnis verfälschen.