Funktionale Programmierung Funktionen höherer Ordnung Eine Funktion wird als Funktion höherer Ordnung bezeichnet, wenn Funktionen als Argumente verwendet werden, oder wenn eine Funktion als Ergebnis zurück gegeben wird. Beispiel: twoTimes :: ( a -> a ) -> a -> a twoTimes f x = f ( f x ) Anwendung: twoTimes quadrat 3 => quadrat (quadrat 3) => 81 Prof. Dr. Margarita Esponda Funktionale Programmierung Funktionen höherer Ordnung Typische Beispielsfunktion: map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs map f [2, 3, 6, 0] => [f(2), f(3), f(6), f(0)] Die Funktion f wird auf jedes Element der Liste angewendet map (^2) [2, 3, 6, 0] Prof. Dr. Margarita Esponda => [4, 9, 36, 0] Funktionale Programmierung Funktionen höherer Ordnung Die filter-Funktion Die filter-Funktion soll aus einer Liste nur die Elemente auswählen, die eine bestimmte Bedingung erfüllen. Beispiel: filter (<3) [2,5,0,1,7] Prof. Dr. Margarita Esponda => [2,0,1] Funktionale Programmierung Funktionen höherer Ordnung Die filter-Funktion 1. Definition: filter :: (a -> Bool) -> [a] -> [a] filter p [] = [] filter p (x:xs) Bedingung Prof. Dr. Margarita Esponda | p x = x : filter p xs | otherwise = filter p xs Funktionale Programmierung Funktionen höherer Ordnung takeWhile-Funktion So lange eine Bedingung erfüllt wird, werden Elemente aus einer Liste genommen. takeWhile :: (a → Bool) → [a] → [a] takeWhile p [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] Beispiel: takeWhile (<9) Prof. Dr. Margarita Esponda [2, 5, 7, 9, 11] => [2, 5, 7] Funktionale Programmierung Funktionen höherer Ordnung dropWhile-Funktion So lange eine Bedingung erfüllt wird, werden Elemente aus einer Liste gelöscht. dropWhile :: (a → Bool) → [a] → [a] dropWhile p [] = [] dropWhile p (x:xs) | p x = dropWhile p xs | otherwise = x:xs Beispiel: dropWhile Prof. Dr. Margarita Esponda isSpace " Hello" => "Hello" Funktionale Programmierung Funktionen höherer Ordnung zip-Funktion zip :: [a] → [b] → [(a,b)] zip (x:xs) (y:ys) = (x,y) : zip xs ys zip = [] _ _ Die zip-Funktion kombiniert die Elemente aus zwei Listen und liefert eine Liste von Tupeln zurück. Beispiel: zip [1..] ["abcd"] ⇒ [(1,'a'), (2,'b'), (3,'c'), (4,'d')] Prof. Dr. Margarita Esponda Funktionale Programmierung Funktionen höherer Ordnung zipWith-Funktion Die zipWith-Funktion bekommt zwei Listen und eine Funktion als Parameter und berechnet eine neue Liste, indem jeweils die Elemente der beiden Listen mit der angegebenen Funktion verknüpft werden. zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] zipWith f (x:xs) (y:ys) = (f x y):(zipWith f xs ys ) zipWith f _ _ = [] Beispiel: zipWith (^) [1, 2, 3] [0, 3, 2] Prof. Dr. Margarita Esponda ⇒ [1, 8, 9] Funktionale Programmierung Arithmetische Sequenzen Mit Hilfe des .. Operators lassen sich in Haskell sehr elegant Zahlensequenzen erzeugen. [ 1 .. 5 ] => [1,2,3,4,5] [ 0, 5 .. 21] => [ 0, 5, 10, 15, 20 ] [ 10, 8 .. 0 ] => [ 10, 8, 6, 4, 2, 0 ] [ 10 .. 1 ] => [] [ 1 .. ] => unendliche Liste take 5 [2, 0 .. ] => [ 2, 0, -2, -4, -6 ] … Prof. Dr. Margarita Esponda Funktionale Programmierung Funktionen höherer Ordnung Eine andere Definition der map-Funktion mit Listen-Generatoren ist: map :: (a -> b) -> [a] -> [b] map f xs = [ f x | x<-xs ] Anwendung: map length ["Eins", "Zwei", "Drei", "Vier"] => [4, 4, 4, 4] Prof. Dr. Margarita Esponda Funktionale Programmierung Listen-Generatoren Die Syntax von Listengeneratoren in Haskell ist sehr ähnlich zu dem, was wir für die Definition von Mengen in der Mathematik kennen. Mathematik: { x | x ∈ { 1 .. 20 }, (x mod 3) = 0 } { x x ∈Ν, x 3 ≤ 100 } Menge aller Zahlen, die genau durch 3 geteilt werden können Prof. Dr. Margarita Esponda Funktionale Programmierung Listen-Generatoren Haskell: [ x | x <- [1 .. 20], (mod x 3)==0 ] damit gibt man Haskell die Anweisung, eine Liste zu bilden aus allen Elementen, die genau durch 3 geteilt werden können: sollen dabei mehrere Bedingungen erfüllt werden, so müssen diese durch Komma getrennt sein. Im Unterschied zu der mathematischen Definition von Mengen können Haskell-Listen sich wiederholende Elemente beinhalten. Prof. Dr. Margarita Esponda Funktionale Programmierung Listen-Generatoren Allgemeine Form: [ body | qualifiers ] Beispiele: [ n*n | n <- [1..100] ] factors n = [ i | i <- [1..n], (n `mod` i) == 0 ] 2. Definition der filter-Funktion: filter :: (a -> Bool) -> [a] -> [a] filter p xs = [ x | x <- xs, p x ] Prof. Dr. Margarita Esponda Funktionale Programmierung Sieb des Eratosthenes 3. Jahrhundert v. Chr. Das Sieb des Eratosthenes ist ein sehr bekannter Algorithmus, der für ein vorgegebenes N alle Primzahlen findet, die kleiner gleich N sind. Der Algorithmus verwendet ein Feld p aus booleschen Werten, mit dem Ziel, dem Element p[i] den Wert 1 zuzuweisen, falls i eine Primzahl ist, und anderenfalls den Wert 0. Ziel: P P P Prof. Dr. Margarita Esponda P P P 1 2 3 4 5 6 7 8 9 0 1 1 0 1 0 1 0 0 10 11 0 1 Funktionale Programmierung Sieb des Eratosthenes Anfang: 1 1 1 1 1 1 1 1 1 1 2 3 4 5 6 7 8 9 0 1 1 0 1 1 0 1 1 0 1 1 1 0 2 1 3 1 Prof. Dr. Margarita Esponda 4 0 5 1 6 0 7 1 8 0 9 0 1 1 10 0 1 10 0 1 11 1 11 1 1 12 0 1 12 0 1 13 1 13 1 1 14 0 1 14 0 1 15 1 15 0 1 1 16 0 1 16 0 1 17 1 17 1 1 18 0 1 18 0 1 19 1 19 1 1 20 0 1 20 0 1 21 1 21 0 1 Funktionale Programmierung Sieb des Eratosthenes 1 0 1 0 2 3 1 2 1 3 1 1 4 0 4 0 5 1 5 1 6 0 6 0 7 1 7 1 8 0 8 0 9 10 0 0 9 10 0 0 11 1 11 1 12 0 12 0 13 1 13 1 14 15 0 14 0 15 0 0 16 0 16 0 17 1 17 1 18 0 18 0 19 1 19 1 20 0 20 0 0 2 3 1 1 4 0 5 1 6 0 7 1 8 0 nur bis N/2 noch besser ist nur bis Prof. Dr. Margarita Esponda 9 10 0 0 2 N 11 1 12 0 13 1 14 0 0 21 0 N nicht mehr! 1 21 15 0 16 0 17 1 18 0 19 1 20 0 21 0 Funktionale Programmierung Sieb des Eratosthenes 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 2 3 5 7 9 11 13 15 17 19 21 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 2 3 5 7 11 13 17 19 23 Prof. Dr. Margarita Esponda Funktionale Programmierung Listen-Generatoren primzahlen :: Integer → [Integer] primzahlen n = sieb [2..n] where sieb [] = [] sieb (p:xs) = p: sieb [k | k<-xs, k `mod` p>0] primzahlen :: Integer → [Integer] primzahlen = sieb [2..] where sieb (p:xs) = p:sieb[k | k<-xs, k `mod` p>0] Prof. Dr. Margarita Esponda Funktionale Programmierung Funktionen höherer Ordnung all-Funktion Entscheidet, ob alle Elemente einer Liste eine gegebene Bedingung erfüllen. all :: (a → Bool) → [a] → Bool all p xs = and [p x | x ← xs] Beispiel: all even [2 ,4 ,6 ,8] all (==3) Prof. Dr. Margarita Esponda => True [3,4,3,0,3] => False Funktionale Programmierung Funktionen höherer Ordnung any-Funktion Entscheidet, ob mindestens ein Element einer Liste eine gegebene Bedingung erfüllt. any :: (a → Bool) → [a] → Bool any p xs = or [p x | x ← xs] Beispiel: any even [2 ,3 ,6 ,8] => True any (==3) [3,4 ,3 ,0 ,3] => True Prof. Dr. Margarita Esponda