Programmieren in Haskell Stefan Janssen Programmieren in Haskell Typen in Haskell Allgemeines zu Typen Vordefinierte Datentypen Listen Stefan Janssen Universität Bielefeld AG Praktische Informatik October 15, 2014 Typen in Haskell Haskell verwendet strong typing: Jeder Wert hat einen Typ; Funktionen dürfen nur auf Argumente des richtigen Typs angewandt werden Typen können vom Compiler geprüft werden Typisierung kostet keinen Rechenaufwand zur Laufzeit Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typen in Haskell Haskell verwendet strong typing: Jeder Wert hat einen Typ; Funktionen dürfen nur auf Argumente des richtigen Typs angewandt werden Typen können vom Compiler geprüft werden Typisierung kostet keinen Rechenaufwand zur Laufzeit Haskell verwendet parametrischen Typ-Polymorphismus Funktionen können allgemeine Typen mit Typ-Parametern haben; z.B. map:: (a -> b) -> [a] -> [b] Bei der Anwendung einer polymorphen Funktion konkretisiert sich ihr Typ Haskell verwendet Typ-Klassen – davon später mehr. Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Datentypen Programmieren in Haskell Ein Datentyp ist eine Mengen von Werten, worauf Operationen (Funktionen) definiert werden können. eingebaute Datentypen sind vordefiniert und haben oft eine besondere Notation benutzerdefinierte Datentypen werden durch Typdefinitionen eingeführt; haben Standard-Notation Typdeklarationen geben zu neuen Namen den Typ ihres Werts an Typdeklarationen sind optional. Sie dienen hauptsächlich der Lesbarkeit. Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Funktionstypen 1 Der wichtigste Datentyp ist die Funktion, allgemein a -> b Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Funktionstypen 1 1 2 3 4 Der wichtigste Datentyp ist die Funktion, allgemein a -> b Konkrete Funktionen haben speziellere Typen, z.B. > power :: Int -> Int -> Int > isqrt :: Int -> Float > id :: a -> a > id x = x Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Funktionstypen 1 1 2 3 4 1 2 Der wichtigste Datentyp ist die Funktion, allgemein a -> b Konkrete Funktionen haben speziellere Typen, z.B. > power :: Int -> Int -> Int > isqrt :: Int -> Float > id :: a -> a > id x = x Mehrstellige Funktionen und Funktionen höherer Ordnung ergeben sich, wenn man für a und b selbst wieder Funktionstypen einsetzt > (+):: Int -> Int -> Int > (:):: a -> [ a ] -> [ a ] 3 4 > map :: (a - > b ) -> [ a ] -> [ b ] map ist also eine zweistellige Funktion, deren erstes Argument selbst eine Funktion ist Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Gestaffelte Funktionen Programmieren in Haskell Stefan Janssen 1 1 1 Mehrstelligen Funktionen gibt man den “gestaffelten” Typ a -> b -> c ... -> y -> z -- 25 - stellig was (per Definition von ->) das Gleiche ist wie a -> ( b -> ( c ...( y -> z )...)) aber etwas anderes als (a ,b ,c ,... , y ) -> z Das letzte wäre eine 1-stellige Funktion mit einem 25-Tupel als Argument. Allgemeines zu Typen Vordefinierte Datentypen Listen Eingebaute Datentypen: Zahlen Programmieren in Haskell Elementare eingebaute Datentypen in Haskell sind: Ganze Zahlen (Integer, Int) Funktionen darauf sind z.B.: +, -, *, div, mod, ^ Fließkommazahlen (Float, Double) +, /, ^, sqrt Konstanten können mehreren Typen angehören: Wert mögl. Typen 1, -5, 100, 0.314e1 Int, Integer, Float, Double 2.0, 2e3, 3.14e0 Float, Double 1,-5, 120 Int, Integer Integer sind ganze Zahlen beliebiger Stellenzahl Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typklasse Num Fractional Integral Eingebaute Datentypen: Bool, Char, String Programmieren in Haskell Stefan Janssen Wahrheitswerte (Bool): True, False &&, ||, not Allgemeines zu Typen Zeichen (Char): ’a’, ’A’, ’\’ ... Vordefinierte Datentypen Zeichenketten (String), wobei String = [Char] "abraham", "2XG5", "" ... Listen Listen ([a]) [], :, ++, reverse, take, drop Listen sind polymorph und kommen gleich noch ausführlicher! Typen von Ausdrücken Programmieren in Haskell Ausdrücke haben Typen: Stefan Janssen 1 2 3 4 5 6 7 8 9 42 :: Int 3 + 4 :: Int 4.2 :: Float True :: Bool " Hallo Welt ! " :: String -- bzw . [ Char ] [1 ,2 ,3] :: [ Int ] [] :: [ a ] [[]] :: [[ a ]] Hier sind einige Typen spezieller als es sein muss! Allgemeines zu Typen Vordefinierte Datentypen Listen Typinferenz in Ausdrücken Programmieren in Haskell Stefan Janssen Hugs> :t (1+2) 1 + 2 :: Num a => a Hugs> :t (4.2) 4.2 :: Fractional a => a Hugs> :t 2/3 2 / 3 :: Fractional a => a Klasse => ... nennt man einen Typkontext Allgemeines zu Typen Vordefinierte Datentypen Listen Typen einschränken Durch explizite Typ-Angaben kann man den allgemeinsten Typ einschränken: Programmieren in Haskell Stefan Janssen Hugs> 2 / 3 0.6666666666666 Allgemeines zu Typen Hier wird für 1 und 2 ein Typ der Klasse Fractional a abgeleitet. Jetzt die Einschränkung: Hugs> (2::Int) ERROR - Cannot *** Instance *** Expression / (3::Int) infer instance : Fractional Int : 2 / 3 Vordefinierte Datentypen Listen Typen einschränken Durch explizite Typ-Angaben kann man den allgemeinsten Typ einschränken: Programmieren in Haskell Stefan Janssen Hugs> 2 / 3 0.6666666666666 Allgemeines zu Typen Hier wird für 1 und 2 ein Typ der Klasse Fractional a abgeleitet. Jetzt die Einschränkung: Hugs> (2::Int) ERROR - Cannot *** Instance *** Expression / (3::Int) infer instance : Fractional Int : 2 / 3 Hugs> (2::Int) ‘div‘ (3::Int) 0 Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Beispiele für Typklassen Eq Überprüfung auf Gleichheit. In der Klasse Eq sind die Operationen == und /= definiert. Instanzen z.B.: Int, Float, Double, String Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Beispiele für Typklassen Eq Überprüfung auf Gleichheit. In der Klasse Eq sind die Operationen == und /= definiert. Instanzen z.B.: Int, Float, Double, String Ord Ordnungsrelation. In der Klasse Ord sind die Operationen <,>,<=,>= definiert. Instanzen z.B.: Int, Float, Double, String Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Beispiele für Typklassen Eq Überprüfung auf Gleichheit. In der Klasse Eq sind die Operationen == und /= definiert. Instanzen z.B.: Int, Float, Double, String Ord Ordnungsrelation. In der Klasse Ord sind die Operationen <,>,<=,>= definiert. Instanzen z.B.: Int, Float, Double, String Num Umfasst die numerischen Typen, z.B. Int, Float, Double Operationen: +,-,* Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Typklassen In Haskell sind Typen in Klassen organisiert. Typen sind dabei Instanzen von Klassen. Beispiele für Typklassen Eq Überprüfung auf Gleichheit. In der Klasse Eq sind die Operationen == und /= definiert. Instanzen z.B.: Int, Float, Double, String Ord Ordnungsrelation. In der Klasse Ord sind die Operationen <,>,<=,>= definiert. Instanzen z.B.: Int, Float, Double, String Num Umfasst die numerischen Typen, z.B. Int, Float, Double Operationen: +,-,* Show Werte eines Typs der Instanz der Klasse Show ist, lassen sich ausgeben Z.B. Int, Float, Double, String Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Definition von Typklassen Programmieren in Haskell Stefan Janssen Natürlich kann man selbst Typklassen neu definieren (später in Einheit 16) bestehende Typklassen erweitern konkrete Datentypen zu Instanzen von Typklassen machen Das entspricht in etwa den abstrakten Klassen oder Interfaces in Java, die durch konkrete Klassen implementiert werden. Allgemeines zu Typen Vordefinierte Datentypen Listen Tupel-Typen Notation ( a1, a2, a3, ... ) vordefinierte Funktionen: fst snd ... Komponenten können verschiedene Typen haben vs. Liste Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Tupel-Typen Notation ( a1, a2, a3, ... ) vordefinierte Funktionen: fst snd ... Komponenten können verschiedene Typen haben vs. Liste Example 1 2 fst :: (a , b ) -> a fst (x , y ) = x 3 4 5 snd :: (a , b ) -> b snd (_ , y ) = y Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Void Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Unit-Datentyp in Haskell: () Vordefinierte Datentypen einziges Element: () Listen vergleichbar mit void in C/Java Listen in der funktionalen Programmierung Programmieren in Haskell Listen gibt es in allen Programmiersprachen, aber in der funktionalen Programmierung werden sie besonders viel benutzt. Dafür gibt es einen polymorphen Datentyp für Listen aus Elementen von beliebigem, aber gleichem Typ viele vordefinierte Funktionen auf Listen eine spezielle Notation für Listen, Listenbeschreibungen ähnlich der mathematischen Mengen-Notation Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren (:) :: a -> [a] -> [a] ”Cons” [] :: [a] ”Nil” Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren (:) :: a -> [a] -> [a] ”Cons” [] :: [a] ”Nil” [1..10] Typ-Notation: [a], [Int] usw. Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren (:) :: a -> [a] -> [a] ”Cons” [] :: [a] ”Nil” [1..10] Typ-Notation: [a], [Int] usw. Main> 1:2:3:4:[] [1,2,3,4] Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Der polymorphe Listen-Typ [a] Notation: [1,2,3,4] – geschönte Notation 1:2:3:4:[] – Standard-Notation mit Konstruktoren (:) :: a -> [a] -> [a] ”Cons” [] :: [a] ”Nil” [1..10] Typ-Notation: [a], [Int] usw. Main> 1:2:3:4:[] [1,2,3,4] Example 1 2 3 > length ’ :: [ a ] -> Int > length ’ [] = 0 > length ’ ( a : as ) = 1 + length ’ as Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Listenbeschreibungen Programmieren in Haskell 1 2 3 4 Listenbeschreibungen sind der mathematischen Stefan Mengen-Notation nachempfunden. Janssen Beispiel: Allgemeines sm = [ x | x <- " abraham " , x < ’i ’] zu Typen pairs = [( a , b +1) | a <- " aber " , b <- [1 ,2 ,3]] Vordefinierte Datentypen evenodd = [( a ,b , a + b ) | a <- [1..10] , b <- [11..20] , Listen even a == odd b ] Listenbeschreibungen Programmieren in Haskell 1 2 3 4 1 2 Listenbeschreibungen sind der mathematischen Stefan Mengen-Notation nachempfunden. Janssen Beispiel: Allgemeines sm = [ x | x <- " abraham " , x < ’i ’] zu Typen pairs = [( a , b +1) | a <- " aber " , b <- [1 ,2 ,3]] Vordefinierte Datentypen evenodd = [( a ,b , a + b ) | a <- [1..10] , b <- [11..20] , Listen even a == odd b ] Allgemeine Form: [ f x y ... | x <- X , cond x , y <- Y , cond x y , ...] X, Y, ...: Listen, aus denen Elemente kommen cond: Bedingungen, die diese erfuellen muessen f x y ...: Elemente der neuen Listen, die aus den ausgewaehlten x, y,... berechnet werden Listenbeschreibungen für Zahlenfolgen Programmieren in Haskell 1 2 3 4 5 6 Besonders komfortable Notation gibt es für Zahlenfolgen: l1 = [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10] l2 = [1..10] l3 = [1..] l4 = [1 ,5..42] l5 = [1 ,5 ..] l6 = [10 ,8 .. 1] Aufsteigende und absteigende Zahlenfolgen; die Differenz der beiden ersten Zahlen gibt die Schrittweite und Richtung an, .. bedeutet Fortsetzung, bis zum Endwert wenn angegeben, sonst unendlich. Stefan Janssen Allgemeines zu Typen Vordefinierte Datentypen Listen Mehr über Listen Programmieren in Haskell Stefan Janssen Allgemeines zu Typen Es folgen viele Beispiele von Funktionen über Listen. Siehe Datei listintro.lhs Vordefinierte Datentypen Listen