Unendliche Listen Programmierparadigmen Unendliche Listen D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg c Sommer 2011, 26. April 2011, 2011 D.Rösner D. Rösner PGP 2011 . . . 1 Unendliche Listen Gliederung 1 Unendliche Listen Einführung Funktionen ... höherer Ordnung Verknüpfen mit zipWith Filtern Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben D. Rösner PGP 2011 . . . 2 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen ‘lazy evaluation’ (auf Deutsch: verzögerte Auswertung): Werte werden nur bestimmt, wenn sie auch tatsächlich benötigt werden da in Haskell grundsätzlich ‘lazy’ evaluiert wird, werden für unendliche Listen in Haskell keine zusätzlichen Sprachmittel benötigt Beispiel: ones = 1:ones Wie ist diese Definition zu lesen? s.a. [Tho99], 17.6 D. Rösner PGP 2011 . . . 4 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen schrittweise Expansion der Definition von ones ones = 1:ones = 1:(1:ones) = 1:(1:(1:ones)) ... -- Def. -- Def. -- Def. damit zum Beispiel: Main> head ones 1 Main> head (tail ones) 1 Main> take 10 ones [1,1,1,1,1,1,1,1,1,1] D. Rösner PGP 2011 . . . 5 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Welche Listenfunktionen können bei unendlichen Listen angewendet werden? fast alle! ausgenommen sind nur solche Listenfunktionen, bei denen die Berechnung eines Werts das Durchlaufen der ganzen (endlichen) Liste erfordert dazu gehören: ........................................ ........................................ ..................................... ..................................... D. Rösner PGP 2011 . . . 7 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Welche Listenfunktionen können bei unendlichen Listen angewendet werden? alle Listenfunktionen, bei denen Werte in endlich vielen Auswertungsschritten gewonnen werden können, lassen sich wegen Haskells verzögerter Auswertung auf unendliche Listen anwenden dazu gehören auch die meisten Funktionen höherer Ordnung z.B. map, filter, zipWith, . . . Welche Funktionen höherer Ordnung gehören nicht dazu? ..................................... ...................................... D. Rösner PGP 2011 . . . 9 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Erinnerung: paarweises Verknüpfen korrespondierender Elemente zweier Listen zipWith :: (a->b->c) -> [a]->[b]->[c] zipWith z (a:as) (b:bs) = z a b : zipWith z as bs zipWith _ _ = [] _ D. Rösner PGP 2011 . . . 10 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen durch elementweises Verknüpfen lässt sich folgendes definieren Beispiel: unendliche Liste der natürlichen Zahlen integers = 1: (zipWith (+) ones integers) Wie ist diese Definition zu lesen? Zugriff auf einen endlichen Abschnitt: Main> take 10 integers [1,2,3,4,5,6,7,8,9,10] D. Rösner PGP 2011 . . . 11 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen schrittweise Expansion der Definition von integers integers = 1: (zipWith (+) ones integers) ones: 1 1 1 1 ... integers: ones: 1 1 1 1 1 ... integers: ones: 1 1 2 1 1 1 ... integers: ones: 1 1 2 1 3 1 1 -- zipWith: (+) 1 2 1 ... integers: ... 1 2 3 4 -- zipWith: (+) 1 3 -- zipWith: (+) 1 1 D. Rösner PGP 2011 . . . 12 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Quadratzahlen squares = map (\ x -> x*x) integers Zugriffe: Main> take 20 squares [1,4,9,16,25,36,49,64,81,100,121,144, 169,196,225,256,289,324,361,400] Main> head (filter (> 100000) squares) 100489 D. Rösner PGP 2011 . . . 13 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Kubikzahlen Variante 1: cubes = map (\ x -> x*x*x) integers Variante 2: cubes’ = (zipWith (*) squares integers) Zugriff: Main> take 10 cubes [1,8,27,64,125,216,343,512,729,1000] Main> head (filter (> 1000000) cubes) 1030301 D. Rösner PGP 2011 . . . 14 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Werte der Fakultätsfunktion faks = 1: (zipWith (*) faks (tail integers)) Main> take 10 faks [1,2,6,24,120,720,5040,40320,362880,3628800] Damit auch möglich: fak n = faks!!(n-1) Anwendung: Main> fak 3 6 Main> fak 10 3628800 D. Rösner PGP 2011 . . . 15 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Fibonacci-Zahlen fibgen a b = a:(fibgen b (a + b)) fibs = fibgen 0 1 Zugriffe: Main> take 10 fibs [0,1,1,2,3,5,8,13,21,34] Main> take 5 (filter (>10000) fibs) [10946,17711,28657,46368,75025] D. Rösner PGP 2011 . . . 16 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Filtern erzeugt unendliche Listen, deren Elemente eine gewünschte Eigenschaft haben Beispiel: unendliche Liste der nicht durch 7 teilbaren Zahlen divisiblep x y = mod x y == 0 no_sevens = filter (\x -> not (divisiblep x 7)) [1 ..] D. Rösner PGP 2011 . . . 17 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Wochentage data Wochentag = Mo | Di | Mi | Do | Fr | Sa | So deriving (Eq, Ord, Enum, Show, Read) wochentage = [Mo ..] ++ wochentage Main> take 30 wochentage [Mo,Di,Mi,Do,Fr,Sa,So,Mo,Di,Mi,Do,Fr,Sa, So,Mo,Di,Mi,Do,Fr,Sa,So,Mo,Di,Mi,Do,Fr,Sa, So,Mo,Di] D. Rösner PGP 2011 . . . 19 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen mögliche Verwendung: Kalender Main> zipWith (showTag "Januar 2010") (drop 4 wochentage) [1 .. 31] liefert ["Fr 1. Januar 2010","Sa 2. Januar 2010","So 3. Januar 2010", "Mo 4. Januar 2010","Di 5. Januar 2010","Mi 6. Januar 2010", "Do 7. Januar 2010","Fr 8. Januar 2010","Sa 9. Januar 2010", "So 10. Januar 2010","Mo 11. Januar 2010","Di 12. Januar 2010", "Mi 13. Januar 2010","Do 14. Januar 2010","Fr 15. Januar 2010", "Sa 16. Januar 2010","So 17. Januar 2010","Mo 18. Januar 2010", "Di 19. Januar 2010","Mi 20. Januar 2010","Do 21. Januar 2010", "Fr 22. Januar 2010","Sa 23. Januar 2010","So 24. Januar 2010", "Mo 25. Januar 2010","Di 26. Januar 2010","Mi 27. Januar 2010", "Do 28. Januar 2010","Fr 29. Januar 2010","Sa 30. Januar 2010", "So 31. Januar 2010"] D. Rösner PGP 2011 . . . 20 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Hilfsfunktion: showTag showTag monat = (\ d n -> shows d (showChar ’ ’ (shows n (showChar ’.’ (showChar ’ ’ monat))))) Beispiel für Verwendung: Main> showTag "Februar 2009" Di 3 "Di 3. Februar 2009" D. Rösner PGP 2011 . . . 21 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen unendliche Listen lassen sich oft auch als Listenkomprehension schreiben Beispiel: unendliche Liste aller pythagoräischen Tripel Erinnerung: pythagoräische Tripel sind Tripel (x, y , z) ganzer Zahlen, für die gilt: x 2 + y 2 = z2 in Haskell (s.a. [Tho99], 17.6): pythagTriples = [(x,y,z)| z <- [2 .. ], y <- [2 .. z-1], x <- [2 .. y-1], x*x + y*y == z*z] D. Rösner PGP 2011 . . . 23 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Ausgabe einer solchen unendlichen Liste muss abgebrochen werden: Main> pythagTriples [(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17),(12,16,20), (15,20,25),(7,24,25),(10,24,26),(20,21,29),(18,24,30), (16,30,34),(21,28,35),(12,35,37),(15,36,39),(24,32,40), (9,40,41),(27,36,45),(30,40,50),(14,48,50),(24,45,51), (20,48,52),(28,45,53),(33,44,55),(40,42,58),(36,48,60), (11,60,61),(39,52,65),(33,56,65),(25,60,65),(16,63,65), (32,60,68),(42,56,70),(48,55,73),(24,70,74),(45,60,75), (21,72,75),(30,72,78),(48,64,80),(18,80,82),(51,68,85), (40,75,85),(36,77,85),(13,84,85),(60,63,87),(39,80,89), (54,72,90),(35,84,91),(57,76,95),(65,72,97),(60,80,100), (28,96,100),(20,99,101),(48,90,102),(40,96,104),(63,84,105), (56,90,106),(60,91,109),(66,88,110),(36,105,111),(15,112,113), (69,92,115),(80,84,116),(45,108,117),(56,105,119),(72,96,120), (22,120,122),(27,120,123),(75,100,125),(44,117,125),(35,120,125), (78,104,130),(66,112,130),(50,120,130),(32,126,130),(81,108,135), D. Rösner PGP 2011 . . . 24 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Frage: kleinstes pythagoräisches Tripel, bei dem alle Zahlen grösser als 1000? Main> head (filter (\(x,_,_) -> x > 1000) pythagTriples ) liefert (Warnung: Zeitbedarf): (1020,1071,1479) D. Rösner PGP 2011 . . . 25 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen die unendliche Liste der Potenzen einer natürlichen Zahl Variante 1: Listenkomprehension powers n = [n^x| x <- [0 ..]] Variante 2: mit iterate powers’ n = iterate (*n) 1 D. Rösner PGP 2011 . . . 27 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen aus Prelude.hs: iterate iterate f x :: (a -> a) -> a -> [a] = x : iterate f (f x) Welche unendliche Liste wird durch iterate f x erzeugt? .................................................. D. Rösner PGP 2011 . . . 28 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Variante 3: powers’’ n = 1:map (*n) (powers’’ n) Was ist der Vorteil von Variante 3? .................................................. D. Rösner PGP 2011 . . . 29 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen für viele Anwendungen (z.B. Simulationen) werden Zufallszahlen benötigt ein gängiges Verfahren zur Erzegung von Pseudo-Zufallszahlen (engl. pseudo-random numbers) ist die sog. lineare Kongruenzmethode (s.a. [Tho99], 17.6): ausgehend von einem ganzzahligen Startwert (engl. seed) werden aufeinanderfolgende Werte der Folge von ganzzahligen Pseudo-Zufallszahlen dadurch berechnet, dass der jeweils aktuelle Wert mit einem Multiplikator multipliziert, dann zum Produkt ein Inkrement addiert und schliesslich der Folgewert durch Bestimmung des Rests modulo einer festen Zahl (dem sog. Modulus) gewonnen wird D. Rösner PGP 2011 . . . 31 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen in Haskell: nextRand n = (multiplier*n + increment) ‘mod‘ modulus randomSequence = iterate nextRand Konsequenz: die Werte der Pseudo-Zufallsfolge liegen zwischen 0 und modulus-1 D. Rösner PGP 2011 . . . 32 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen über ’günstige’ Werte für die Grössen Multiplikator, Inkrement und Modulus gibt es Erfahrungswissen eine mögliche Wertbelegung (s.a. [Tho99], 17.6): seed multiplier increment modulus = = = = 17489 25173 13849 65536 mögliche Nutzung: Main> take 10 (randomSequence seed) [17489,59134,9327,52468,43805,8378,18395,59344, 52777,23478] D. Rösner PGP 2011 . . . 33 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen aus gleichverteilten Zufallszahlen im Bereich zwischen 0 und modulus-1 lassen sich durch Skalierung solche in einem interessierenden Zahlenbereich gewinnen z.B. Simulation eines Würfels: Main> take 30 (scaleSequence 1 6 (randomSequence seed)) [2,6,1,5,5,1,2,6,5,3,3,2,1,3,3,6,2,4,4,1, 1,6,5,2,6,2,3,1,1,3] D. Rösner PGP 2011 . . . 34 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen z.B. Simulation von Lottozahlen: Main> take 30 (scaleSequence 1 49 (randomSequence seed)) [14,45,7,40,33,7,14,45,40,18,17,15,5,23,18, 46,11,26,31,4,5,46,35,10,44,14,19,3,2,21] D. Rösner PGP 2011 . . . 35 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen bei der Skalierung auf Werte zwischen from und to (je einschliesslich) wird der Bereich zwischen 0 und Modulus-1 in to - from + 1 gleichgrosse Abschnitte zerlegt Zahlen aus dem jeweiligen Abschnitt wird dann der korrespondierende Wert aus dem Bereich von from bis to zugeordnet D. Rösner PGP 2011 . . . 36 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen in Haskell: scaleSequence from to = map scale where scale n = from + n ‘div‘ denom range = to - from + 1 denom = modulus ‘div‘ range D. Rösner PGP 2011 . . . 37 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen gleichverteilte Zufallsfolgen für endliche Listen mit Werten anderer Datentypen lassen sich ebenfalls leicht gewinnen Skalierung für eine Liste von möglichen Werten: uniformFrom list = map (\n -> list!!(fromIntegral n)) (scaleSequence 0 (toInteger ((length list) - 1)) (randomSequence seed)) D. Rösner PGP 2011 . . . 38 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen Beispiel: Zufallsfolgen von Zeichen Bereich [’a’ ..’z’] Main> take 30 (uniformFrom [’a’ ..’z’]) "gxdurdhxujihcljyfnqccxsfxgkbak" Bereich [’a’ ..’e’] Main> take 30 (uniformFrom [’a’ ..’e’]) "beaedabeebbbacbebcdaaedbebbaac" D. Rösner PGP 2011 . . . 39 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: Sieb des Eratosthenes benannt nach Eratosthenes von Kyrene (ca. 276 v.Chr. – 194 v.Chr.), dem griechischen Mathematiker, Geograph, Geschichtsschreiber, Philologe und Dichter sowie Direktor der Bibliothek von Alexandria. Idee: a Streiche in der Liste aller natürlichen Zahlen alle Vielfachen der gerade als Primzahl erkannten Zahl. b Die erste der dann verbleibenden Zahlen ist wiederum prim. c Wiederhole a. D. Rösner PGP 2011 . . . 41 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: Sieb des Eratosthenes Definition als Haskell-Funktion: sieve [] = [] sieve (x:xs) = x:(sieve (filter (\y -> not (divisiblep y x)) xs)) Alternative Definition: sieve (x:xs) = x:(sieve (filter (\y -> mod y x /= 0) xs)) D. Rösner PGP 2011 . . . 42 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Primzahlen primes = sieve [2 ..] D. Rösner PGP 2011 . . . 43 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Primzahlen die ersten 100 Main> take 100 primes [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79, 83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163, 167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251, 257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349, 353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443, 449,457,461,463,467,479,487,491,499,503,509,521,523,541] D. Rösner PGP 2011 . . . 44 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Primzahlen die erste Primzahl grösser als eine Schranke Main> head (filter (> 1000) primes) 1009 Main> head (filter (> 10000) primes) 10007 Main> head (filter (> 5000) primes) 5003 D. Rösner PGP 2011 . . . 45 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen naheliegende Abstraktion: das beim Sieben anzuwendende Prädikat wird zusätzliches Argument m.a.W.: sievep _ [] = [] sievep p (x:xs) = x:(sievep p (filter (\y -> p y x) xs)) der Spezialfall des Sieb des Eratosthenes ergibt sich dann als primes’ = sievep (\a b -> mod a b /= 0) [2 ..] D. Rösner PGP 2011 . . . 46 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Literatur: I 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 PGP 2011 . . . 47