Universität Bielefeld Programmieren in Haskell Giegerich Programmieren in Haskell WS 2011/2012 Robert Giegerich Universität Bielefeld AG Praktische Informatik October 30, 2013 Algebraic Datatypes Musik Algebraische Datentypen Universität Bielefeld Programmieren in Haskell Neue Datentypen werden als algebraische Datentypen eingeführt. Werte des Datentyps sind Formeln, die aus Konstruktoren zusammengesetzt sind Konstruktoren sind Funktionen, die man deklarieren, aber nicht definieren muss. Konstruktornamen fangen mit Großbuchstaben an. Algebraische Datentypen können polymorph sein und Typ-Parameter haben. Meistens sind sie rekursiv - ein Wert kann einen Teil-Wert des gleichen Typs enthalten. Giegerich Algebraic Datatypes Musik Beispiel Universität Bielefeld Programmieren in Haskell Giegerich 1 2 data Bool = True | False keine Typ-Parameter, nicht rekursiv, nur zwei Werte Konstruktoren sind True und False → beide null-stellig (nullary (data) constructor) Funktionen nutzen pattern matching auf den Konstruktoren, z.B. der Operator &&: 1 2 False && y = False True && y = y Algebraic Datatypes Musik Apropos Konstruktor Universität Bielefeld Programmieren in Haskell Giegerich Algebraic Datatypes 1 „Konstruktor“ meint immer (Daten-)Konstruktor. Einen Typnamen mit Parametern nennt man gelegentlich „Typ-Konstruktor“ data T a b = ... Typ-Konstruktor T “konstruiert” aus Typen a und b den Typ T a b Musik Beispiel 1 2 3 1 data Einheit = Celsius | Fahrenheit | Kelvin Neuer Typ mit genau drei Werten. Universität Bielefeld Programmieren in Haskell Giegerich Algebraic Datatypes Musik data Temperatur = Temp Float Einheit (Einziger) Konstruktor Temp hat zwei Argumente, deren Typen deklariert werden. 1 2 data Temp = Temp Float Einheit -- erlaubt und -- ueblich ! → Typkonstruktoren und (Daten-)Konstruktoren haben getrennte Namensräume Beispiel Universität Bielefeld Programmieren in Haskell Giegerich 1 Temp 506 Kelvin :: Temperatur celsius2kelvin celsius2kelvin t :: Float -> Temperatur = Temp ( t + 273.15) Kelvin Algebraic Datatypes Musik 1 2 3 4 5 6 kel vin2fahrenheit :: Float -> Temperatur kel vin2fahrenheit t = Temp ( t *9/5 -459.67) Fahrenheit Das Beispiel ist inkonsequent, weil das Argument selbst nicht vom Typ Temperatur ist. Beispiel Universität Bielefeld Programmieren in Haskell Giegerich 1 2 3 4 5 6 7 8 Temperatur-Umrechnung: conv :: Temperatur -> Einheit -> Temperatur conv ( Temp t Celsius ) Celsius = Temp t Celsius conv ( Temp t Celsius ) Kelvin = Temp ( t + 273.15) Kelvin conv ( Temp t Kelvin ) Fahrenheit = Temp ( t *9/5 -459.67) Fahrenheit ... Algebraic Datatypes Musik Algebraische Datentypen Universität Bielefeld Programmieren in Haskell Giegerich Allgemeine Form der Deklaration: data T a1 . . . am = C1 t11 . . . t1n1 ... Cr tr 1 . . . trnr T Typkonstruktor Ci (Daten-)Konstruktoren ai Typvariablen tij Typen oder Typvariablen | | Algebraic Datatypes Musik Beispiel: Listen Universität Bielefeld Programmieren in Haskell Giegerich 1 2 Wenn man Listen noch einführen müßte ... data List a = Cons a ( List a ) | Nil polymorhper Typ (Typ-Parameter a) → Algebraischer Datentyp List ist rekursiv definiert eingebaute Listentyp erlaubt syntaktischen Zucker: : — „Cons“als Infix-Operator [] — „Nil“ [] — Typ-Konstruktor, etwa in [Int] Spezielle Listen-Notationen Algebraic Datatypes Musik Beispiel: Listen Universität Bielefeld Programmieren in Haskell Example Giegerich [1..5] = [1,2,3,4,5] = 1:2:3:4:5:[] Algebraic Datatypes : Cons Musik 1 1 Cons 2 2 Cons 3 : Cons 4 Cons 5 Nil : 3 : 4 : 5 [] Elementare Funktionen auf Listen Universität Bielefeld Programmieren in Haskell Die meisten kennen wir bereits: Giegerich head, tail Algebraic Datatypes length Musik sum, product enumFromTo append reverse take, drop map filter concat, concatMap siehe Tafel Beispiel: Maybe 1 2 data Maybe a = Just a | Nothing Konstruktor Just ist ein-stellig Typvariable a als Parameter Eine Form der Fehlerbehandlung bzw. Vorbeugung, wenn eine Funktion ein Ergebnis liefert, das nicht in jedem Fall existiert 1 2 3 1 2 3 > divide a b = > if b == 0 then error " divide by zero " > else div a b Mit Maybe: > divide a b > | b == 0 = Nothing > | otherwise = Just ( div a b ) Universität Bielefeld Programmieren in Haskell Giegerich Algebraic Datatypes Musik Beispiel: Maybe Universität Bielefeld Programmieren in Haskell Giegerich 1 1 2 3 4 Typ von divide: divide :: ( Num a ) = > a -> a -> Maybe a Pattern matching: f a b = extract ( divide a b ) + ... where extract ( Just x ) = x extract Nothing = 0 Was ist der Typ von extract? Algebraic Datatypes Musik Typsynonyme (Nachtrag zum Haskell Typsystem) Universität Bielefeld Programmieren in Haskell 1 2 3 1 Neue Typnamen durch Typsynonyme: type Pair a b = (a , b ) type Triple a b c = (a ,b , c ) type OrdList a = [ a ] definiert neue Namen, genannt Typ-Synonyme, für bereits existieeremde Typen; hier im Beispiel für existierende Tupel-Typen und Listen. Dient ausschliesslich der Dokumentation. newtype MyList a = [ a ] führt ebenfalls einen NEUEN Typen analog zu [a] ein, der aber nicht als typgleich betrachtet wird. Verhindert gegenseitige Verwechslung von [a] und MyList a. Giegerich Algebraic Datatypes Musik Derived instance declarations Universität Bielefeld Programmieren in Haskell Optionale deriving Form: Giegerich data T a1 . . . am = C1 t11 . . . t1n1 ... | | Cr tr 1 . . . trnr deriving (k1 , . . . , ku ) kx Typklassen für bestimmte Klassen können Instanzen automatisch erzeugt werden das heißt, alle Operationen der Klassen werden auf dem neuen Typ T automatisch implementiert. → einfacher als explizite Definition, die auch möglich ist Algebraic Datatypes Musik ... deriving ... Universität Bielefeld Programmieren in Haskell Giegerich Algebraic Datatypes Example 1 2 3 Musik data Maybe a = Nothing | Just a deriving ( Eq , Ord , Read , Show ) Damit sind Operationen wie == oder < auf dem Typ Maybe implementiert. Modellierung von Musik Universität Bielefeld Programmieren in Haskell Giegerich cis dis fis gis ais cis dis fis gis ais des es ges as b des es ges as b Algebraic Datatypes Musik c d e f g a h c d e f Quelle: http://commons.wikimedia.org/wiki/File:Klaviatur.svg, Public Domain g a h Modellierung von Musik 1 2 Universität Bielefeld > module Musik where > import R a t i o Programmieren in Haskell Giegerich 3 4 5 > infixr 7 :∗: > i n f i x r 6 :+: Algebraic Datatypes 6 7 8 Musik > type G a n z e Z a h l > type Bruch = Int = Ratio Int > type Ton > type Dauer = GanzeZahl = Bruch 9 10 11 12 13 14 15 16 17 18 19 20 > data Musik = > Note Ton Dauer > Pause Dauer > Musik :∗: Musik > Musik :+: Musik > Instr I n s t r u m e n t Musik > Tempo G a n z e Z a h l Musik > deriving | | | | | −− h i n t e r e i n a n d e r −− g l e i c h z e i t i g −− S c h l a e g e p r o Minute Show Modellierung von Musik Universität Bielefeld Programmieren in Haskell Giegerich 22 23 24 147 148 149 150 151 > data Instrument = > A co usticGrand Pi an o | > B ri ghtAcousti cP i a no | ... > TelephoneRing | > Helicopter | > Applause | > Gunshot > deriving ( Show , Enum ) Algebraic Datatypes Musik Modellierung von Musik Universität Bielefeld Programmieren in Haskell Giegerich Sieben Ganztöne: c d e f g a h Halbtöne über den Tönen: cis dis eis (= f) fis gis ais his (=c) Halbtöne unter den Tönen: ces (=h) des es fes (=e) ges as b c cis dis fis gis ais cis dis fis gis ais des es ges as b des es ges as b d e f g a h c d e f g a h Algebraic Datatypes Musik Modellierung von Musik 19 Universität Bielefeld > module M u s i k H e l p e r where Programmieren in Haskell 20 21 Giegerich > import Musik 22 Algebraic Datatypes 23 24 25 > ce , c i s , des , de , d i s , es , eh , e i s , f e s > e f , f i s , ges , ge , g i s , as , ah , a i s , be , ha , h i s 26 27 28 29 30 31 32 33 > > > > > > > ce de eh ef ge ah ha = = = = = = = 0 2 4 5 7 9 11 ; ; ; ; ; ; ; cis dis eis fis gis ais his = = = = = = = 1 3 5 6 8 10 12 ; ; ; ; ; ; des es fes ges as be = = = = = = 1 3 4 6 8 10 : : TonMusik : : Ton Formeln, die Musik bedeuten 1 2 3 Note 0 (1/4) Note 24 (1/1) Pause (1/16) Universität Bielefeld -- Viertelnote tiefes C -- ganze Note c’ -- Sechzehntelpause 4 5 6 Programmieren in Haskell Giegerich Algebraic Datatypes Musik Note 24 (1/4) :*: Note 26 (1/4) :*: Note 28 (1/4) -- Anfang der C - Dur Tonleiter (c 7 8 9 Note 24 (1/4) :+: Note 28 (1/4) :+: Note 31 (1/4) -- C - Dur Akkord (c ,e , g ) 10 11 12 13 14 Tempo Tempo Instr Instr 70 m 180 m Oboe m VoiceAahs m ----- Musik Musik Musik Musik m m m m als Adagio als Presto von Oboe gespielt gesummt Abkürzungen 35 Universität Bielefeld > gP , hP , vP , aP , sP :: Musik Programmieren in Haskell Giegerich 36 41 43 > adagio , andante , allegro , presto :: GanzeZahl 38 39 40 gP hP vP aP sP = = = = = Pause Pause Pause Pause Pause (1/1) (1/2) (1/4) (1/8) (1/16) Algebraic Datatypes > > > > > 37 44 45 46 47 48 > > > > adagio = 70 andante = 90 allegro = 140 presto = 180 Musik Abkürzungen Universität Bielefeld Programmieren in Haskell Giegerich 50 > c’ , d’ , e’ , f ’ , g’ , a’ , h’ , c’ ’ 51 52 53 54 55 56 57 58 59 : : Dauer −> Musik Algebraic Datatypes Musik > > > > > > > > c’ d’ e’ f’ g’ a’ h’ c’’ u u u u u u u u = = = = = = = = Note Note Note Note Note Note Note Note ( c e +24) ( de +24) ( eh +24) ( e f +24) ( ge +24) ( ah +24) ( ha +24) ( c e +36) u u u u u u u u Zusammengesetzte Klänge Universität Bielefeld Programmieren in Haskell 61 > c DurTon i ka : : Musik 62 63 > c DurTon i ka = c ’ ( 1 / 1 ) : + : e ’ ( 1 / 1 ) : + : g ’ ( 1 / 1 ) 66 67 68 70 71 > cDurSkala > c ’ (3/8) > > = Tempo a l l e g r o ( : ∗ : d ’ (1/8) : ∗ : e ’ (3/8) : ∗ : f ’ (4/8) : ∗ : g ’ (1/8) : ∗ : a ’ (1/4) : ∗ : h ’ (1/8) : ∗ : c ’ ’ (1/2)) > durDreiklang t > = Note t ( 1 / 1 ) : + : Note ( t +4) ( 1 / 1 ) : + : Note ( t +7) ( 1 / 1 ) 72 73 74 Algebraic Datatypes Musik 64 65 Giegerich > m o l l D r e i k l a n g t = Note t ( 1 / 1 ) : + : Note ( t +3) ( 1 / 1 ) > : + : Note ( t +7) ( 1 / 1 ) Transponierung Universität Bielefeld Programmieren in Haskell Giegerich 79 > transponiere Algebraic Datatypes : : Ton −> Musik −> Musik Musik 80 81 82 83 84 85 86 > > > > > > t r a n s p o n i e r e i ( Pause d ) = t r a n s p o n i e r e i ( Note t d ) = t r a n s p o n i e r e i (m1 : ∗ : m2) = :∗: t r a n s p o n i e r e i (m1 : + : m2) = :+: Pause d Note ( t+i ) d ( transponiere ( transponiere ( transponiere ( transponiere i i i i m1) m2) m1) m2) Verschiedenes Universität Bielefeld Programmieren in Haskell Giegerich Algebraic Datatypes 92 93 > wdh : : Musik −> Musik > wdh m = m : ∗ : m 94 95 96 > ad_infinitum : : Musik −> Musik > ad_infinitum m = m : ∗ : ad_infinitum m 97 98 > einsatz d m = ( Pause d ) : ∗ : m Musik Bruder Jakob: Text Universität Bielefeld Programmieren in Haskell Bruder Jakob, Bruder Jakob Schläfst du noch? Schläfst du noch? ||: Hörst du nicht die Glocken? :|| Ding dang dong, ding dang dong. Quelle: http://de.wikipedia.org/w/index.php?title=Datei: FrereJacques1pt.png&filetimestamp=20070819210216, Public Domain Giegerich Algebraic Datatypes Musik