Universität Bielefeld Programmieren in Haskell Giegerich Programmieren in Haskell WS 2011/2012 Administratives Musik Guards Arrays RobertGiegerich Universität Bielefeld AG Praktische Informatik November 14, 2012 Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Musik Universität Bielefeld Programmieren in Haskell Giegerich Administratives Der Nachfolger von Haskore ist Euterpea: http://haskell.cs.yale.edu/?page_id=103 Paul Hudak. The Haskell School of Music. 2.0 edition, 2011. http: //www.cs.yale.edu/homes/hudak/Papers/HSoM.pdf Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Fallunterscheidungen ... Universität Bielefeld Programmieren in Haskell ... in Ausdrücken: if condition then ausdruck else ausdruck 1 2 3 4 5 case expr of pat1 | guard1 -> expr1 pat2 | guard2 -> expr2 pat3 | guard3 -> expr3 ... ... in Definitionen auf der linken Seite Giegerich Administratives Musik Guards Arrays Algebraic Datatypes Listen Ranges Pattern matching: f [] (y:ys) = Ausdruck mit y und ys List Comprehensions Bewachte Gleichungen: ersetzen geschachtelte if-Anweisungen auf der rechten Seite Primzahlen Sortieren Wächter (Guards) in Funktionsdefinitionen Universität Bielefeld Programmieren in Haskell 1 2 3 4 > fn pat1 pat2 ... > | guard1 = expr1 > | guard2 = expr2 > ... Giegerich Administratives Musik Guards syntaktische Zucker für Funktionsdefinitionen Arrays guards (Wächter) sind Ausdrücke (vom Typ Bool) Algebraic Datatypes Listen Example 1 2 3 4 howManyEqual n m p | ( n == m ) && ( m == p ) = 3 | ( n == m ) || ( m == p ) || ( n == p ) = 2 | otherwise = 0 Ranges List Comprehensions Sortieren Primzahlen Datenstrukturen mit konstantem Zugriff Universität Bielefeld Programmieren in Haskell Giegerich Administratives “Konstanter Zugriff” heisst: Zugriff mit Aufwand unabhängig von der Größe der Datenstruktur. Beispiel Musik: Finden der n-ten Note erfordert Durchlauf der Datenstruktur in n oder mehr Schritten. Beispiel Listen: Element-Operator (!!) wird kaum verwendet Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Zugriff auf Listenelemente Universität Bielefeld Programmieren in Haskell Giegerich Listen beherbergen viele Elemente gleichen Typs. 1 2 1 2 Sequentielle Abarbeitung ist einfach und effizient, z.B. map f [] = [] map f ( x : xs ) = f x : map f xs Random Zugriff auf einzelne Elemente durch operator !! hängt von der Listenlänge ab: ( x : xs ) !! 0 = x ( x : xs ) !! n = xs !!( n -1) Abhilfe schafft der Datentyp Array a b Administratives Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Datentyp Array a b Universität Bielefeld Programmieren in Haskell Arrays – auf Deutsch “Felder” Modul Array stellt Datwntyp Array a b und Funktionen darauf bereit a ist der Datentyp des Index, b der Elementtyp Operator ! für element-Zugriff bietet effizienten Random-Access Indextyp erlaubt mehrere Dimensionen Giegerich Administratives Musik Guards Arrays Algebraic Datatypes Listen Ranges Funktion array liefert ein Array zurück 1 array : : ( I x a ) => ( a , a ) −> [ ( a , b ) ] −> Array a b List Comprehensions Sortieren 2 3 t = a r r a y ( low , h i g h ) l i s t _ o f _ e n t r i e s = . . . 1 (!) :: ( Ix a ) = > Array a b -> a -> b Primzahlen Beispiel: 2D Array 1 2 3 > module A r r > where > import Array 4 5 6 7 8 9 10 11 12 13 14 15 16 19 Programmieren in Haskell Giegerich Administratives > t a b l e : : Array ( Char , I n t ) I n t > t a b l e = array ( ( ’ a ’ , 0) , ( ’ c ’ , 2) ) > [ ( ( ’ a ’ , 0) , 0 ) , > ( ( ’ a ’ , 1) , 1 ) , > ( ( ’ a ’ , 2) , 2 ) , > ( ( ’b ’ , 0) , 3 ) , > ( ( ’b ’ , 1) , 4 ) , > ( ( ’ c ’ , 0) , 6 ) , > ( ( ’ c ’ , 1) , 7 ) , > ( ( ’b ’ , 2) , 5 ) , > ( ( ’ c ’ , 2) , 8 ) > ] 17 18 Universität Bielefeld > access a b = table ! (a , b) > access2 = ( table !) Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Alternative Universität Bielefeld Programmieren in Haskell Giegerich Pattern Matching als Alternative für read-only Felder Administratives vs. Feldgröße Musik Guards Arrays Example 1 2 3 4 5 access access access access ... ’a ’ ’a ’ ’a ’ ’b ’ 0 1 2 1 = = = = 0 1 2 3 Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Beispiel: Umwandlung String in Char Array Universität Bielefeld Programmieren in Haskell Giegerich Administratives Musik Guards 1 2 3 Arrays > s 2 a : : S t r i n g −> Array I n t Char > s2a xs = l i s t A r r a y (0 , length xs − 1) xs Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Beispiel: Tabellierung einer Funktion Universität Bielefeld Programmieren in Haskell Giegerich Verwandung einer Funktion in eine Tabelle 2 3 4 5 > tabulate > tabulate > t > domain : : ( I n t , I n t ) −> ( I n t −> a ) −> ( I n t −> a ) ( l o , up ) f = ( t ! ) where = a r r a y ( l o , up ) ( z i p domain (map f domain ) ) = [ l o . . up ] 6 Arrays Algebraic Datatypes Ranges 8 10 Guards Listen 7 9 Administratives Musik 1 > sq1 x = x ∗ x+1 > f a s t s q 1 = t a b u l a t e ( 1 , 1 0 ) sq1 List Comprehensions Sortieren Primzahlen Algebraische Datentypen – Fortsetzung Universität Bielefeld Programmieren in Haskell Allgemeine Form der Deklaration: data T a1 . . . am = C1 t11 . . . t1n1 ... | | Cr tr 1 . . . trnr Giegerich Administratives Musik Guards Arrays T Typkonstruktor Algebraic Datatypes Ci (Daten-)Konstruktoren Listen ai Typvariablen tij Typen oder Typvariablen Ranges List Comprehensions Sortieren Warum heißen Algebraische Datentypen „algebraisch“? deriving Typ-Kontexte Primzahlen Beispiel: Listen Universität Bielefeld Programmieren in Haskell Example Giegerich [1..5] = [1,2,3,4,5] = 1:2:3:4:5:[] Administratives : Cons Musik Guards 1 1 Cons Arrays : Algebraic Datatypes 2 2 Cons : Listen Ranges 3 Cons 3 List Comprehensions : Sortieren 4 Cons 5 Nil 4 : 5 [] Primzahlen Listendefinition Universität Bielefeld Programmieren in Haskell Giegerich Administratives 1 2 Wenn man sie nicht schon hätte: data List a = Cons a ( List a ) | Nil Pseudo-Code für vordefinierte Listen 1 2 data [ a ] = a : [ a ] | [] Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Primzahlen Elementare Funktionen auf Listen Universität Bielefeld Programmieren in Haskell Die meisten kennen wir bereits: Giegerich head, tail Administratives length Musik sum, product Guards Arrays enumFromTo append reverse take, drop Algebraic Datatypes siehe Tafel Listen Ranges List Comprehensions map Sortieren filter Primzahlen concat, concatMap Arithmetic Sequences Universität Bielefeld Syntaktischer Zucker für Listen [expr1..] [expr1..expr2] [expr1,expr2..] [expr1,expr2..expr3] Programmieren in Haskell Example Arrays Giegerich Administratives Musik Guards Algebraic Datatypes Hugs> [1..5] [1,2,3,4,5] Hugs> [1,3..10] [1,3,5,7,9] Hugs> [2,4..10] [2,4,6,8,10] Hugs> [1..] [1,2,3,... Listen Ranges List Comprehensions Sortieren Primzahlen Arithmetic Sequences Universität Bielefeld Programmieren in Haskell Giegerich Übersetzung: Administratives [expr1..] = enumFrom expr1 Musik [expr1..expr2] = enumFromTo expr1 expr2 Guards [expr1,expr2..] = enumFromThen expr1 expr2 Arrays Algebraic Datatypes [expr1,expr2..expr3] = enumFromThenTo expr1 expr2 Listen expr3 Ranges Voraussetzung: expri haben den Gleichen Typ T Typ T gehört der Typklasse Enum an List Comprehensions Sortieren Primzahlen List Comprehensions (Übersetzt auch: Listenbeschreibung) List Comprehension 1 [ expr | qual1 , ... , qualn ] (wobei n >= 1) Universität Bielefeld Programmieren in Haskell Giegerich Administratives Musik Guards Qualifier ist: Generator: pat <- expr Guard (oder Filter): boolexpr lokale Deklaration: let decls Example Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren 1 [ x * x | x <- [1..20] , odd x ] [1,9,25,49,81,121,169,225,289,361] Primzahlen Auflösung von List Comprehensions Universität Bielefeld Programmieren in Haskell Übersetzungsschema: [ expr | True ] = [ expr ] Giegerich Administratives [ expr | qual, True ] = [ expr | qual ] Musik [ expr | guard, qual1, ..., qualn ] = if guard then [ e | qual1 , ... , qualn ] else [] Guards [ expr | pat <- list, qual1, ..., qualn] = let f pat = [ expr | qual1 , ... , qualn ] f _ = [] in concatMap f list Listen [ expr | let decls, qual1, ..., qualn ] = let decls in [ expr | qual1 , ... , qualn ] Primzahlen Arrays Algebraic Datatypes Ranges List Comprehensions Sortieren Sortieren Universität Bielefeld Programmieren in Haskell Spezifikation des Sortierproblems: genauer: Sortieren per Vergleich Eingabe: Liste l Giegerich Administratives Musik Guards Elemente vom Typ T Arrays T ist eine Instanz der Typklasse Ord Algebraic Datatypes Ausgabe: sortierte Liste r Listen length l = length r für alle x ∈ l: length [ a | a <- l, a == x] = length [ b | b <- r, b == x] Ranges List Comprehensions Sortieren Insertion Sort is_ordered l Quicksort Primzahlen Insertion Sort Universität Bielefeld Programmieren in Haskell Giegerich Administratives 1 2 3 > isort :: Ord a = > [ a ] -> [ a ] > isort [] = [] > isort ( x : xs ) = insert x ( isort xs ) where 4 5 6 7 8 > > > > insert x insert x | x <= | x > [] = [ x ] ( y : ys ) y = x : y : ys y = y :( insert x ys ) Musik Guards Arrays Algebraic Datatypes Listen Ranges List Comprehensions Sortieren Insertion Sort Quicksort Primzahlen Quicksort Universität Bielefeld Programmieren in Haskell Giegerich Quicksort – noch bekannt aus der ersten Vorlesung ...? Administratives Musik Guards Arrays 1 2 3 4 5 > qsort :: Ord a = > [ a ] -> [ a ] Algebraic Datatypes > qsort [] = [] Listen > qsort ( a : xs ) = qsort [ b | b <- xs , b < a ] ++ Ranges > [ a ] ++ List Compre> qsort [ b | b <- xs , b >= a ] hensions Sortieren Insertion Sort Quicksort Primzahlen Primzahlen Universität Bielefeld Programmieren in Haskell Primzahl natürliche Zahl > 1 nur teilbar durch 1 und sich selbst Giegerich Administratives Musik Guards Arrays Erster Versuch: Hier ist direkt die Definition progammiert: Algebraic Datatypes Listen Ranges 1 2 3 4 5 > primesSlow :: Integral a = > [ a ] List Compre> primesSlow = [ n | n <- [2..] , divisors n ==hensions [1 , n ] Sortieren > where Primzahlen > divisors :: Integral a = > a -> [ a ] > divisors n = [ d | d <- [1.. n ] , n ‘mod ‘ d == 0] Sieb des Eratosthenes Sieb des Eratosthenes Universität Bielefeld Programmieren in Haskell Giegerich Aus der Liste aller Zahlen werden sukzessive die Vielfachen der bereits gefundenen Primzahlen herausgesiebt ... Administratives Musik Guards Arrays 1 2 > primes :: Integral a = > [ a ] > primes = sieve [2..] where 5 Listen Ranges 3 4 Algebraic Datatypes > > List Compresieve :: Integral a = > [ a ] -> [ a ] hensions sieve ( a : xs ) = a : sieve [ n |n < - xs , n ‘ mod ‘ a /=Sortieren 0] Primzahlen Sieb des Eratosthenes