Listen in Haskell Algorithmen und Datenstrukturen I Listen in Haskell D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg c Winter 2009/10, 16. Oktober 2009, 2009/10 D.Rösner D. Rösner AuD I 2009/10 . . . 1 Listen in Haskell Gliederung 1 Listen in Haskell Datentyp Liste Strings Listenkomprehension D. Rösner AuD I 2009/10 . . . 2 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listen in Haskell: Listen . . . Zusammenfassung beliebig vieler Elemente vom selben Typ Darstellung des Listentyp: [<typ>], z.B. [Int] [Char] [[Int]] [(Name, Matrnr)] ... D. Rösner AuD I 2009/10 . . . 4 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listen in Haskell: Listen werden – sofern ungleich der leeren Liste [] - durch Anwendung des Konstruktors ‘:’ (sprich: cons) in eindeutiger Weise ausgehend von [] aufgebaut Beispiel: [4,2,3] == 4:2:3:[] == 4:(2:(3:[])) ‘:’ ist rechts-assoziativ, d.h. x:y:zs == x:(y:zs) D. Rösner AuD I 2009/10 . . . 5 Listen in Haskell Datentyp Liste Strings Listenkomprehension Primitive Rekursion über Listen auch ‘tail recursion’ genannt Definition durch Angabe des Ausgangswerts für [] und Angabe, wie von Wert für xs auf Wert von (x:xs) übergegangen wird Beispiel: Bestimmung der Länge einer Liste length [] = 0 length (x:xs) = 1 + length xs D. Rösner AuD I 2009/10 . . . 6 Listen in Haskell Datentyp Liste Strings Listenkomprehension Primitive Rekursion über Listen Beachte: length ist polymorph, d.h. auf Listen unterschiedlichen Typs anwendbar: length :: [a] -> Int ’wildcard’ in der zweiten Gleichung der Definition möglich, d.h. length (_:xs) = 1 + length xs length ist wie viele andere Funktionen auf Listen im sog. Standard-Prelude von Haskell bereits vordefiniert D. Rösner AuD I 2009/10 . . . 7 Listen in Haskell Datentyp Liste Strings Listenkomprehension Rekursion über Listen cont. Beispiel: Summe der Werte der Listenelemente sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs Frage: sum [2, 4 .. 11] ,→ . . . ? sum ist vordefiniert und polymorph Prelude> :t sum sum :: Num a => [a] -> a D. Rösner AuD I 2009/10 . . . 8 Listen in Haskell Datentyp Liste Strings Listenkomprehension Rekursion über Listen cont. Beispiel: Sortieren mit sog. Insertion-Sort iSort :: [Int] -> [Int] iSort [] iSort (x:xs) = [] = ins x (iSort xs) ins :: Int -> [Int] -> [Int] ins ins | | x [] = [x] x (y:ys) x<= y = x:(y:ys) otherwise = y: ins x ys D. Rösner AuD I 2009/10 . . . 9 Listen in Haskell Datentyp Liste Strings Listenkomprehension Der Typ String Spezialfall: Liste aus Zeichen, d.h. type String = [Char] alle polymorphen Listenfunktionen können für String benutzt werden Ausgabe mit putStr putStr :: String -> IO () Wechsel zwischen Strings und Werten: show (2 + 3) ==> "5" umgekehrt: (read "True") :: Bool ==> True D. Rösner AuD I 2009/10 . . . 11 Listen in Haskell Datentyp Liste Strings Listenkomprehension Der Typ String alle polymorphen Listenfunktionen können für String benutzt werden Prelude> "ein " ++ "konkatenierter String" ... Prelude> head "wort" ... Prelude> tail "wort" ... Prelude> length "wort" ... Prelude> init "wort" ... Prelude> last "wort" ... ... D. Rösner AuD I 2009/10 . . . 12 Listen in Haskell Datentyp Liste Strings Listenkomprehension Darstellung von Listen für Listen von Zahlen, Zeichen und anderen Aufzählungstypen gibt es Kurzschreibweisen [n .. m] Kurzform für [n,n+1,...,m] (falls m kleiner als n ist Liste leer) Beispiele: [3 .. 9] [1.2 .. 4.1] [’f’ .. ’q’] == [3,4,5,6,7,8,9] == [1.2,2.2,3.2] == "fghijklmnopq" D. Rösner AuD I 2009/10 . . . 13 Listen in Haskell Datentyp Liste Strings Listenkomprehension Darstellung von Listen Variante: die ‘Differenz’ zwischen dem zweiten und dem ersten Element ergibt die ‘Schrittweite’ Beispiele: [3,5 .. 14] [0.0,0.4 .. 2.0] [’f’,’h’ .. ’q’] = [3,5,7,9,11,13] = [0.0,0.4,0.8,1.2,1.6,2.0] = "fhjlnp" D. Rösner AuD I 2009/10 . . . 14 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension Vorbild: math. Notation für Mengen Beispiel: Teiler(n) = {i∈Nk i≤n, i Teiler von n} in Haskell: teiler :: Int -> [Int] teiler n = [ i | i<-[1..n], mod n i == 0] Liste [1..n] wirkt als Generator Test mod n i == 0 wählt Elemente aus mehrere Tests in Form boolescher Ausdrücke möglich D. Rösner AuD I 2009/10 . . . 16 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont.: Beispiele (vgl. [Tho99], pp.79) Sei ex die Liste [2,4,7] [ 2*n | n<-ex] ,→ [4,8,14] lies: ‘Nimm alle 2*n für n aus der Liste ex’ zur Veranschaulichung: Auswertung tabellarisch n 2*n = = 2 4 4 8 7 14 D. Rösner AuD I 2009/10 . . . 17 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont.: Beispiele (vgl. [Tho99], pp.79) Sei isEven definiert: isEven :: Int -> Bool isEven n = (n ‘mod‘ 2 == 0) [ isEven n | n<-ex] ,→ [True, True, False] mehrere Tests möglich [ 2*n | n<-ex, isEven n, n>3] D. Rösner AuD I 2009/10 . . . 18 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont.: Beispiele (vgl. [Tho99], pp.79) links von <- können nicht nur Variable, sondern auch Muster (pattern) stehen Beispiel: addPairs :: [(Int,Int)] -> [Int] addPairs pairList = [ n+m | (n,m) <- pairList] Veranschaulichung mit Tabelle: [ n+m n m n+m | (n,m) <- [(2,3),(2,1),(7,8)]] = 2 2 7 = 3 1 8 = 5 3 15 D. Rösner AuD I 2009/10 . . . 19 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont. (vgl. [Tho99], pp.79) zusätzlicher Test: nur geordnete Paare addieren addOrdPairs :: [(Int,Int)] -> [Int] addOrdPairs pairList = [ n+m | (n,m) <- pairList, n < m] Frage: addOrdPairs [(2,3),(2,1),(7,8)] ,→ . . . ? D. Rösner AuD I 2009/10 . . . 20 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont.: Syntax: allgemeine Form ist [ e | q1 , ... qk ] dabei ist jeder der Qualifikatoren qi entweder ein Generator der Form p <- lExp mit p Muster und lExp Ausdruck vom Listentyp oder ein Test, d.h. boolescher Ausdruck bExp wichtig: ein Ausdruck lExp bzw. bExp in qi kann auf die in q1 bis qi−1 benutzten Variablen verweisen D. Rösner AuD I 2009/10 . . . 21 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont. (vgl. [Tho99], 17.3) mit mehreren Generatoren können Elemente aus zwei oder mehr Listen kombiniert werden Beispiel: pairs :: [a] -> [b] -> [(a,b)] pairs xs ys = [ (x,y) | x<-xs , y<-ys ] pairs [1,2,3] [4,5] ,→ [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)] D. Rösner AuD I 2009/10 . . . 22 Listen in Haskell Datentyp Liste Strings Listenkomprehension Listenkomprehension cont.: pythagoräische Tripel: für welche Tripel (x, y , z) ganzer Zahlen gilt: x 2 + y 2 = z2 ? als Listenkomprehension: pyTriple n = [(x,y,z)| x<-[2 .. n], y<-[x+1 .. n], z<-[y+1 .. n], x*x+y*y==z*z] Frage: pyTriple 100 ,→ ... ? D. Rösner AuD I 2009/10 . . . 23 Listen in Haskell Datentyp Liste Strings Listenkomprehension Literatur: I Richard Bird. Introduction to functional programming using Haskell. Prentice Hall Europe, 2000. ISBN 0-13-484346-0; 2nd edition. Manual M. Chakravarty and Gabriele C. Keller. An Introduction to Computing with Haskell. Pearson Education Australia, 2002. ISBN 1 74009 404 2; also available in German translation. Simon Thompson. Haskell - The Craft of Functional Programming. Addison Wesley Longman Ltd., Essex, 1999. 2nd edition, ISBN 0-201-34275-8; Accompanying Web site: http://www.cs.ukc.ac.uk/people/staff/sjt/craft2e. D. Rösner AuD I 2009/10 . . . 24 Listen in Haskell Datentyp Liste Strings Listenkomprehension Literatur: II D. Rösner AuD I 2009/10 . . . 25