Unendliche Listen Unendliche Listen Gliederung Programmierparadigmen 1 Unendliche Listen Verknüpfen mit zipWith Filtern D. Rösner Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben 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 . . . Unendliche Listen Unendliche Listen Einführung Funktionen ... höherer Ordnung D. Rösner PGP 2011 . . . 1 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen 2 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen ‘lazy evaluation’ (auf Deutsch: verzögerte Auswertung): schrittweise Expansion der Definition von ones Werte werden nur bestimmt, wenn sie auch tatsächlich benötigt werden ones = 1:ones = 1:(1:ones) = 1:(1:(1:ones)) ... da in Haskell grundsätzlich ‘lazy’ evaluiert wird, werden für unendliche Listen in Haskell keine zusätzlichen Sprachmittel benötigt Beispiel: 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] ones = 1:ones Wie ist diese Definition zu lesen? s.a. [Tho99], 17.6 D. Rösner PGP 2011 . . . -- Def. -- Def. -- Def. 4 D. Rösner PGP 2011 . . . 5 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen 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? 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 . . . Unendliche Listen 7 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben D. Rösner PGP 2011 . . . Unendliche Listen Unendliche Listen 9 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 Erinnerung: paarweises Verknüpfen korrespondierender Elemente zweier Listen integers = 1: (zipWith (+) ones integers) zipWith :: (a->b->c) -> [a]->[b]->[c] zipWith z (a:as) (b:bs) = z a b : zipWith z as bs zipWith _ _ = [] _ 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 . . . 10 D. Rösner PGP 2011 . . . 11 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen schrittweise Expansion der Definition von integers Beispiel: unendliche Liste der Quadratzahlen integers = 1: (zipWith (+) ones integers) ones: 1 1 1 1 ... squares = map (\ x -> x*x) integers Zugriffe: integers: ones: 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 1 1 ... Main> take 20 squares [1,4,9,16,25,36,49,64,81,100,121,144, 169,196,225,256,289,324,361,400] -- zipWith: (+) 1 1 D. Rösner PGP 2011 . . . Unendliche Listen Main> head (filter (> 100000) squares) 100489 D. Rösner PGP 2011 . . . 12 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen 13 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Kubikzahlen Variante 1: 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] cubes = map (\ x -> x*x*x) integers Variante 2: Damit auch möglich: cubes’ = (zipWith (*) squares integers) fak n = faks!!(n-1) Zugriff: Anwendung: Main> take 10 cubes [1,8,27,64,125,216,343,512,729,1000] Main> fak 3 6 Main> fak 10 3628800 Main> head (filter (> 1000000) cubes) 1030301 D. Rösner PGP 2011 . . . 14 D. Rösner PGP 2011 . . . 15 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Fibonacci-Zahlen Filtern erzeugt unendliche Listen, deren Elemente eine gewünschte Eigenschaft haben Beispiel: unendliche Liste der nicht durch 7 teilbaren Zahlen fibgen a b = a:(fibgen b (a + b)) fibs = fibgen 0 1 Zugriffe: divisiblep x y = mod x y == 0 no_sevens = filter (\x -> not (divisiblep x 7)) [1 ..] 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 . . . Unendliche Listen 16 D. Rösner PGP 2011 . . . Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen 17 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen mögliche Verwendung: Kalender Beispiel: unendliche Liste der Wochentage Main> zipWith (showTag "Januar 2010") (drop 4 wochentage) [1 .. 31] data Wochentag = Mo | Di | Mi | Do | Fr | Sa | So deriving (Eq, Ord, Enum, Show, Read) 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"] 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 D. Rösner PGP 2011 . . . 20 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Hilfsfunktion: showTag unendliche Listen lassen sich oft auch als Listenkomprehension schreiben Beispiel: unendliche Liste aller pythagoräischen Tripel showTag monat = (\ d n -> shows d (showChar ’ ’ (shows n (showChar ’.’ (showChar ’ ’ monat))))) 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): Beispiel für Verwendung: pythagTriples = [(x,y,z)| z <- [2 .. ], y <- [2 .. z-1], x <- [2 .. y-1], x*x + y*y == z*z] Main> showTag "Februar 2009" Di 3 "Di 3. Februar 2009" D. Rösner PGP 2011 . . . Unendliche Listen 21 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 (64,120,136),(88,105,137),(84,112,140),(55,132,143),(100,105,145), (87,116,145),(24,143,145),(17,144,145),(96,110,146),(48,140,148), D. Rösner PGP 2011 . . . Unendliche Listen 23 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 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen aus Prelude.hs: die unendliche Liste der Potenzen einer natürlichen Zahl Variante 1: Listenkomprehension iterate :: (a -> a) -> a -> [a] powers n = [n^x| x <- [0 ..]] iterate f x Variante 2: mit iterate = x : iterate f (f x) Welche unendliche Liste wird durch iterate f x erzeugt? powers’ n = iterate (*n) 1 .................................................. D. Rösner PGP 2011 . . . Unendliche Listen 27 D. Rösner PGP 2011 . . . Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen 28 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): Variante 3: powers’’ n = 1:map (*n) (powers’’ n) Was ist der Vorteil von Variante 3? .................................................. D. Rösner PGP 2011 . . . 29 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 Unendliche Listen Zufallszahlen 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): in Haskell: seed multiplier increment modulus nextRand n = (multiplier*n + increment) ‘mod‘ modulus randomSequence = iterate nextRand Unendliche Listen 17489 25173 13849 65536 mögliche Nutzung: Konsequenz: die Werte der Pseudo-Zufallsfolge liegen zwischen 0 und modulus-1 D. Rösner PGP 2011 . . . = = = = Main> take 10 (randomSequence seed) [17489,59134,9327,52468,43805,8378,18395,59344, 52777,23478] 32 D. Rösner PGP 2011 . . . Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Zufallszahlen 33 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 von Lottozahlen: z.B. Simulation eines Würfels: 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] 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 D. Rösner PGP 2011 . . . 35 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Zufallszahlen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen in Haskell: 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 scaleSequence from to = map scale where scale n = from + n ‘div‘ denom range = to - from + 1 denom = modulus ‘div‘ range Zahlen aus dem jeweiligen Abschnitt wird dann der korrespondierende Wert aus dem Bereich von from bis to zugeordnet D. Rösner PGP 2011 . . . Unendliche Listen 36 D. Rösner PGP 2011 . . . Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Zufallszahlen 37 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Zufallszahlen Beispiel: Zufallsfolgen von Zeichen Bereich [’a’ ..’z’] gleichverteilte Zufallsfolgen für endliche Listen mit Werten anderer Datentypen lassen sich ebenfalls leicht gewinnen Skalierung für eine Liste von möglichen Werten: Main> take 30 (uniformFrom [’a’ ..’z’]) "gxdurdhxujihcljyfnqccxsfxgkbak" uniformFrom list = map (\n -> list!!(fromIntegral n)) (scaleSequence 0 (toInteger ((length list) - 1)) (randomSequence seed)) D. Rösner PGP 2011 . . . 38 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 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: Sieb des Eratosthenes Beispiel: Sieb des Eratosthenes Definition als Haskell-Funktion: 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. sieve [] = [] sieve (x:xs) = x:(sieve (filter (\y -> not (divisiblep y x)) xs)) Idee: Alternative Definition: 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 . . . Unendliche Listen sieve (x:xs) = x:(sieve (filter (\y -> mod y x /= 0) xs)) 41 D. Rösner PGP 2011 . . . Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen 42 Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Primzahlen die ersten 100 Beispiel: unendliche Liste der Primzahlen 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] primes = sieve [2 ..] D. Rösner PGP 2011 . . . 43 D. Rösner PGP 2011 . . . 44 Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Unendliche Listen Einführung Funktionen ... höherer Ordnung Datentypen Listenkomprehension Iterierte Funktionsanwendung Zufallszahlen Sieben Unendliche Listen Beispiel: unendliche Liste der Primzahlen naheliegende Abstraktion: das beim Sieben anzuwendende Prädikat wird zusätzliches Argument m.a.W.: die erste Primzahl grösser als eine Schranke sievep _ [] = [] Main> head (filter (> 1000) primes) 1009 Main> head (filter (> 10000) primes) 10007 Main> head (filter (> 5000) primes) 5003 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 . . . Unendliche Listen 45 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 D. Rösner PGP 2011 . . . 46