5 Haskell – Vorbemerkungen zu Typen 5.1 Typen

5 Haskell – Vorbemerkungen zu Typen
5.1
Typen
Intuitiv unterteilt man die Objekte, die man mit einer Programmiersprache manipulieren will, in disjunkte
Mengen, etwa: Zeichen, ganze Zahlen, Listen, Bäume und Funktionen:
I Objekte verschiedener Mengen haben unterschiedliche Eigenschaften,
(Zeichen und auch ganze Zahlen sind bspw. anzuordnen, Funktionen sind dies nicht)
I für die Objekte verschiedener Mengen sind unterschiedliche Operationen sinnvoll.
(eine Funktion kann angewandt werden, eine ganze Zahl kann mit 0 verglichen werden, aber auf einen
Wahrheitswert kann man nicht addieren, etc.)
Programmiersprachen (wie auch Haskell) formalisieren diese Intuition mittels eines Typsystems.
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
47
Ein Typ definiert
O
1 eine Menge von gleichartigen Objekten (Wertevorrat, „Domain“) und
O
2 Operationen, die auf diese Objekte anwendbar sind (Interface).
Einige Basis-Typen:
Objektmenge
Ganze Zahlen
Zeichen
Wahrheitswerte
Fließkommazahlen
Typname
Integer
Char
Bool
Double
Operationen (Bsp.)
+, max, <
ord, toUpper, <
&&, ==, not
*, /, round
Typkonstruktoren konstruieren aus beliebigen Typen α, β neue Typen:
Objektmenge
Funktionen von α nach β
Listen von α-Objekten
Paare von α, β-Objekten
Typkonstruktor
α -> β
[α]
(α,β)
Operationen (Bsp.)
$ (apply)
head, reverse, length
fst, snd
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
48
Die Notation x :: α (x has type α) wird vom Haskell-Compiler eingesetzt, um anzuzeigen, daß das
Objekt x den Typ α besitzt. Umgekehrt können wir so dem Compiler anzeigen, daß x eine Instanz des
Typs α sein soll.
Beispiel 5.1
2 :: Integer
’X’ :: Char
0.05 :: Double
ord :: Char -> Integer
round :: Double -> Integer
[2,3] :: [Integer]
head :: [α] -> α
(’a’,(2,True)) :: (Char,(Integer,Bool))
snd :: (α,β) -> β
Die Typen der Funktionen head und snd enthalten Typvariablen α und β. Dies entspricht der Beobachtung, daß snd das zweite Element eines Paares bestimmen kann, ohne Details der gepaarten
Objekte zu kennen oder Operationen auf diese anzuwenden. Analog für head (→ Polymorphie, siehe
Kapitel 11).
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
49
Interpretation komplexer Typen
Beispiel 5.2
“Decodierung” des Typs der Prelude-Funktion
unzip :: [(α,β)] -> ([α],[β])
unzip
unzip
unzip
unzip
unzip
::
::
::
::
::
...
[ ... ]
[(α,β)]
[(α,β)]
[(α,β)]
->
->
->
->
->
...
...
...
(...,...)
([α],[β])
unzip [(x1,y1 ), . . . ,(xn,yn )]
_
unzip ist eine Funktion . . .
. . . die eine Liste
. . . von Paaren als Argument hat
. . . und ein Paar
. . . von Listen als Ergebnis liefert.
([x1, . . . ,xn], [y1 , . . . ,yn ])
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
50
Currying und der Typkonstruktor ->
Erinnerung. Mittels Currying kann eine Funktion mehrerer Argumente sukzessive auf ihre Argumente
angewandt werden (s. Abschnitt 3.1).
Frage: Welchen Typ hat die Funktion (der Operator) + daher konsequenterweise
(mit x :: Integer, y :: Integer)?
x+y
≡
((+ x) y)
Antwort:
O
1 Der Teilausdruck (+ x) besitzt den Typ Integer -> Integer,
O
2 damit hat + also den Typ Integer -> (Integer -> Integer).
Vereinbarung:
-> ist rechts-assoziativ. Schreibe daher kürzer
(+) :: Integer -> Integer -> Integer
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
51
Haskell besitzt einen Mechanismus zur Typinferenz, der für (fast) jedes Objekt x den zugehörigen Typ
α automatisch bestimmt. Darauf kommt Kapitel 11 zurück.
Haskell ist
streng typisiert, d.h. eine Operation kann niemals auf Objekte angewandt werden, für die sie nicht
definiert wurde.
statisch typisiert, d.h. schon zur Übersetzungszeit und nicht während des Programmlaufs wird
sichergestellt, daß Programme keine Typfehler enthalten.
(im Haskell-Interpreter werden inkorrekt typisierte Ausdrücke sofort zurückgewiesen)
Beispiel 5.3
Typische Typfehlermeldung:
Prelude> fst
[2,3]
::::::::::::::
<interactive>:1:
Couldn’t match ‘(α, β)’ against ‘[γ]’
Expected type: (α, β)
Inferred type: [γ]
In the first argument of ‘fst’, namely ‘[2, 3]’
Prelude>
© 2003 T. Grust · Funktionale Programmierung: 5. Haskell – Vorbemerkungen zu Typen
52