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