Funktionen in Haskell Funktionen in Haskell Gliederung Programmierparadigmen Funktionen in Haskell 1 D. Rösner Institut für Wissens- und Sprachverarbeitung Fakultät für Informatik Otto-von-Guericke Universität Magdeburg Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert c Sommer 2011, 4. April 2011, 2011 D.Rösner D. Rösner PGP 2011 . . . Funktionen in Haskell 1 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionen in Haskell: 2 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Operationen mit Funktionen Funktionen sind in funktionalen Programmiersprachen ‘Bürger erster Klasse’ (‘first class citizens’) Definition von Funktionen Anwendung von Funktionen auf Argumente (Funktionsapplikation) sie unterscheiden sich nicht von (anderen) Daten, Argumente können verschachtelt wieder Anwendungen von Funktionen auf Argumente sein sie können Argumente von Funktionen sein, sie können Werte von Funktionen sein, partielle Anwendung von Funktionen sie können Elemente in zusammengesetzten Datenstrukturen sein (z.B. Listen, Tupel, . . . ). D. Rösner PGP 2011 . . . D. Rösner PGP 2011 . . . Funktionskomposition 4 D. Rösner PGP 2011 . . . 5 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Definition von Funktionen Definition von Funktionen cont. Definition von Funktionen mit Gleichungen dabei bedingte Ausdrücke verwendbar Variante mit ‘Wächtern’ (engl. ‘guards’) boolesche Ausdrücke für Fälle in einer Definition Beispiel max :: Int -> Int -> Int max x y = if x >= y then x else y idealerweise disjunkt und vollständig abdeckend Beispiel gegebenenfalls verschachtelte bedingte Ausdrücke max :: Int -> Int -> Int Beispiel fib :: Int -> Int fib x = if x == 0 then 0 else if x == 1 then 1 else fib (x - 1) + fib (x - 2) D. Rösner PGP 2011 . . . Funktionen in Haskell max x y | x >= y | otherwise 6 = x = y D. Rösner PGP 2011 . . . Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Definition von Funktionen cont. 7 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Definition von Funktionen cont. Beispiele cont.: Variante mit ‘Pattern matching’ Beispiel Beispiel fib fib | | | fib :: Int -> Int :: Int -> Int x x == 0 = 0 x == 1 = 1 x > 1 = fib (x - 1) + fib (x - 2) fib 0 = 0 fib 1 = 1 fib x = fib (x - 1) + fib (x - 2) Variante: Beachte: Beispiel fib x | x == 0 || x == 1 | otherwise Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Fakt ‘guards’ bzw. Gleichungen werden sequentiell (von oben nach unten) ausgewertet = x = fib (x - 1) + fib (x - 2) D. Rösner PGP 2011 . . . 8 D. Rösner PGP 2011 . . . 9 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Definition von Funktionen cont. Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Definition von Funktionen cont. anonyme Variable (wildcards) beim ‘Pattern matching’ Beispiel mistery :: Int -> Int -> Int ‘wildcards’ immer dann sinnvoll, wenn beliebige Werte im Muster (auf der linken Seite) zugelassen werden sollen und auf diese auf der rechten Seite der Gleichung nicht verwiesen werden muss mistery 0 y = y mistery x y = x mit ‘wildcards’: Beispiel mistery :: Int -> Int -> Int mistery 0 y = y mistery x _ = x D. Rösner PGP 2011 . . . Funktionen in Haskell 10 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert D. Rösner PGP 2011 . . . Funktionen in Haskell Definition von Funktionen cont. 11 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Definition von Funktionen cont. Funktionsdefinitionen können wechselseitig aufeinander Bezug nehmen Problem (Warum reichen diese Definitionen nicht?) Beispiel isEven, isOdd :: Int -> Bool isEven, isOdd :: Int -> Bool isEven 0 = True isEven n = isOdd (n-1) isEven 0 = True isEven 1 = False isEven n = isOdd (n-1) isOdd 1 = True isOdd n = isEven (n-1) isOdd 0 = False isOdd 1 = True isOdd n = isEven (n-1) D. Rösner PGP 2011 . . . 12 D. Rösner PGP 2011 . . . 13 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionen höherer Ordnung: Funktionen höherer Ordnung: Definition Funktionen sind Funktionen höherer Ordnung, wenn sie Beispiele wiederkehrender Programmiermuster bei Listen Test, ob alle Elemente einer Liste eine Bedingung erfüllen eine Funktion als Argument nehmen und/oder eine Funktion als Wert zurückgeben. Test, ob mindestens ein Element einer Liste eine Bedingung erfüllt Auswählen der Elemente einer Liste, die einer Bedingung genügen (und verwerfen der anderen; sog. Filtern) Funktionen höherer Ordnung (auch Funktionale genannt) dienen der Abstraktion. Anwenden einer Funktion auf jedes Element einer Liste und Rückgabe der Liste mit den Resultaten Wiederkehrende Programmiermuster (pattern) lassen sich häufig als Funktionen höherer Ordnung darstellen. D. Rösner PGP 2011 . . . Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert u.v.a.m. 15 D. Rösner PGP 2011 . . . Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Programmiermuster ’Gilt Bedingung für alle?’: 16 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Programmiermuster ’Gilt Bedingung für alle?’: Realisierung als Funktion all mit erstes Argument: Bedingung als Prädikat pred, d.h. als Funktion vom Typ a -> Bool für bel. Typ a zweites Argument: zu testende Liste mit Elementen vom Typ a Programmiermuster: Test, ob alle Elemente einer Liste eine Bedingung erfüllen Fallunterscheidung: in Haskell (s.a. Prelude.hs): Liste ist leer, dann trifft Bedingung zu bei nichtleerer Liste muss der Kopf die Bedingung erfüllen und die Bedingung muss – rekursiv – für alle Elemente des Rests der Liste zutreffen Beispiel all :: (a -> Bool) -> [a] -> Bool all pred [] = True all pred (x:xs) = pred x && all pred xs D. Rösner PGP 2011 . . . 17 D. Rösner PGP 2011 . . . 18 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Programmiermuster ’Bedingung für mind. ein Element erfüllt?’: Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Programmiermuster ’Bedingung für mind. ein Element erfüllt?’: Realisierung als Funktion any mit erstes Argument: Bedingung als Prädikat pred, d.h. als Funktion vom Typ a -> Bool für bel. Typ a zweites Argument: zu testende Liste mit Elementen vom Typ a Programmiermuster: Test, ob mind. ein Element einer Liste eine Bedingung erfüllt Fallunterscheidung: Liste ist leer, dann gibt es kein Element, welches Bedingung erfüllt bei nichtleerer Liste muss entweder Kopf die Bedingung erfüllen oder die Bedingung muss – rekursiv – für mind. ein Element des Rests der Liste zutreffen in Haskell (s.a. Prelude.hs): Beispiel any :: (a -> Bool) -> [a] -> Bool any pred [] = False any pred (x:xs) = pred x || any pred xs D. Rösner PGP 2011 . . . Funktionen in Haskell 19 D. Rösner PGP 2011 . . . Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Programmiermuster Filtern: 20 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Programmiermuster Filtern: Wiederkehrende Frage und Aufgabe: welche Elemente einer Liste genügen einer gewünschten Eigenschaft? Wähle diese aus und verwerfe die anderen. mögliche Definition als Listenkomprehension: wiederum: Darstellung von Eigenschaften als Prädikate, d.h. als Funktionen vom Typ t -> Bool für bel. Typ t Funktion filter nimmt ein Prädikat und eine Liste als Argument und gibt die Liste derjenigen Elemente zurück, für die das Prädikat zutrifft mögliche Definition direkt: Beispiel filter p xs = [x | x <- xs, p x] Typ von filter?: filter :: ( a -> Bool) -> [a] -> [a] Beispiel filter p [] = [] filter p (x:xs) = if p x then x:(filter p xs) else filter p xs D. Rösner PGP 2011 . . . 21 D. Rösner PGP 2011 . . . 22 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Die Funktion map Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Die Funktion map cont. Programmiermuster: Anwendung einer Funktion auf jedes Element einer Liste; Ergebnis ist die Liste der Funktionswerte zu den Elementen mögliche Definitionen: Typ von map? map :: (a -> b) -> [a] -> [b] Beispiele für Anwendung: Beispiel direkt: doubleAll xs = map double xs Beispiel map f [] = [] map f (x:xs) = f x : (map f xs) double x = 2 * x Beispiel als Listenkomprehension: convertChrs :: [Char] -> [Int] Beispiel convertChrs xs = map ord xs map f xs = [ f x | x <- xs] D. Rösner PGP 2011 . . . Funktionen in Haskell 23 D. Rösner PGP 2011 . . . Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Elementweises Verbinden von Listen: zip 24 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Elementweises Verbinden von Listen: zipWith zip: aus zwei Listen (d.h. Paar von Listen) mache Liste mit Paaren korrespondierender Elemente; ignoriere „überschüssige“ Elemente ohne korrespondierenden Partner Verallgemeinerung zipWith: verknüpfe die korrespondierenden Elemente mit einer zweistelligen Funktion zipWith f (x:xs) (y:ys) = f x y : (zipWith f xs ys) zipWith f _ _ = [] Definition (direkt; s.a. Prelude.hs) zip :: [a] -> [b] -> [(a,b)] Beispiel: zip [1 .. 4] [2,4,6,8] ==> ... ? zip [] _ = [] zip _ [] = [] zip (x:xs) (y:ys) = (x,y):(zip xs ys) zipWith (+) [1 .. 4] [2,4,6,8] ==> ... ? Typ von zipWith? : Beispiel: zipWith :: zip [4,7,1,1] "Koeln" = [(4,’K’),(7,’o’),(1,’e’),(1,’l’)] D. Rösner PGP 2011 . . . 25 ................................... D. Rösner PGP 2011 . . . 26 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Anonyme Funktionen Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Anonyme Funktionen Beispiele anonymer Funktionen: Funktionen als Argumente von Funktionen höherer Ordnung können einerseits durch ihren Namen referenziert werden Beispiel wird eine Funktion nur als Argument bei einer Anwendung einer Funktion höherer Ordnung benötigt (und nirgends sonst), so reicht oft auch eine sog. anonyme Funktion aus Beispiel die Darstellung anonymer Funktionen erfolgt durch einen Lambda-Ausdruck mit der Syntax: (\<var(s)> -> <körper>) Beispiel (Variante) (\x -> x*x) (\x y -> x*x - 2*x*y + y*y) (\x -> (\y -> x*x - 2*x*y + y*y)) Syntax in Anlehnung an den sog. λ-Kalkül mit (λxy .x ∗ x + y ) D. Rösner PGP 2011 . . . Funktionen in Haskell Beachte: anonyme Funktionen sind wie benannte Funktionen verwendbar 27 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionale Abstraktion: 28 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Beispiele . . . cont. Beispiele rekursiv definierter Funktionen (vgl. [RL99], 1.2.2) das den obigen Beispielen zugrundeliegende Rekursionsprinzip kann wie folgt abstrahiert werden: es wird Funktionswert für die Basis (d.h. für n == 0) definiert der Funktionswert für n ergibt sich durch Kombination von n (bzw. eines aus n berechneten Werts) mit dem Funktionswert für (n-1) m.a.W.: der Rekursionsschritt wird als Anwendung einer zweistelligen Kombinationsfunktion auf n und Funktionswert für (n-1) realisiert Fakultätsfunktion fact n | n == 0 = 1 | n > 0 = n * fact(n-1) Summe der natürlichen Zahlen bis n sumInt n | n == 0 = 0 | n > 0 = n + sumInt(n-1) Summe der Quadrate der natürlichen Zahlen bis n sumSqr n | n == 0 = 0 | n > 0 = n*n + sumSqr(n-1) D. Rösner PGP 2011 . . . D. Rösner PGP 2011 . . . s.a. [RL99], 1.2.2 30 D. Rösner PGP 2011 . . . 31 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Darstellung dieser Abstraktion in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Abstraktion: induction mögliche Definition als Funktion höherer Ordnung Definition induction ist Funktion höherer Ordnung (nimmt eine Funktion als Argument; hier: comb) damit Darstellung von fact bzw. sumInt mit Hilfe von induction und der vordefinierten Funktionen (+) bzw. (*) induction base comb n | n == 0 = base | n > 0 = comb n (induction base comb (n-1)) Problem Was ist der Typ von induction ? > fact n = induction 1 (*) n > sumInt n = induction 0 (+) n Lösung induction :: . . . s.a. [RL99], 1.2.2 D. Rösner PGP 2011 . . . Funktionen in Haskell 32 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Abstraktion: induction 33 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Benannte vs. anonyme Funktionen die Kombinationsfunktion für sumSqr könnte benannt definiert werden, z.B. f x y = x*x + y dann: alternativ: Definition auf Funktionsebene möglich, d.h. > fact = induction 1 (*) > sumInt = induction 0 (+) die rechten Seiten dieser Gleichungen zeigen sog. partielle Anwendungen von mehrstelligen Funktionen D. Rösner PGP 2011 . . . D. Rösner PGP 2011 . . . > sumSqr n = induction 0 f n bzw. > sumSqr = induction 0 f 34 D. Rösner PGP 2011 . . . 35 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Benannte vs. anonyme Funktionen Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen als Werte: Beispiel: Funktionen zur Manipulation beliebiger reeller Funktionen (vgl. [PH06], 1.2, p. 24) alternativ: Kombinationsfunktion als sog. anonyme Funktion Sei f :: Float -> Float beliebig. Dann: sumSqr n = induction 0 (\x y -> x*x + y) n shift :: Float -> (Float -> Float) -> (Float -> Float) bzw. shift dx f x = f (x - dx) sumSqr = induction 0 (\x y -> x*x + y) mirror :: (Float -> Float) -> (Float -> Float) mirror f x = f (-x) ... D. Rösner PGP 2011 . . . Funktionen in Haskell D. Rösner PGP 2011 . . . 36 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionen als Werte: 38 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionskomposition Beispiel: Funktionen zur Manipulation beliebiger reeller Funktionen (vgl. [PH06], 1.2, p. 24) Verknüpfung von Funktionen als Kontrollstruktur: Ausgabe einer Funktion wird Eingabe der nachfolgenden Definition: ... stretch :: Float -> (Float -> Float) -> (Float -> Float) (f . g) x = f ( g x ) stretch r f x = f (x/r) f . g bedeutet: wende zuerst g, dann f an Frage: m.a.W. Verknüpfung muss von rechts nach links gelesen werden als ‘g, dann f’ Wie wirken sich shift, mirror und stretch aus? ................................ ................................ ................................ D. Rösner PGP 2011 . . . 39 D. Rösner PGP 2011 . . . 40 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionskomposition Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Beispiel Funktionskomposition: eine Funktion zweimal anwenden eine Funktion zweimal anwenden Typ von ‘.‘: (.) :: (b -> c) -> (a -> b) -> (a -> c) Beispiel Funktionskomposition ist assoziativ, d.h. für alle f, g und h twice :: (a -> a) -> (a -> a) f . (g . h) = (f . g) . h twice f = f . f in Haskell aus technischen Gründen als rechtsassoziativ behandelt; d.h. Sei f . g . h = f . (g . h) succ :: Int -> Int succ n = n + 1 Was ergibt dann (twice succ) 7 ==> ... ? D. Rösner PGP 2011 . . . Funktionen in Haskell D. Rösner PGP 2011 . . . 41 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionskomposition 42 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Partielle Anwendung Verallgemeinerung: n-fach wiederholte Funktionsanwendung Beispiel: Beispiel multiply :: Int -> Int -> Int iter :: Int -> (a -> a) -> (a -> a) multiply x y = x * y iter n f | n > 0 |otherwise = f . iter (n-1) f = id Frage: was ergibt multiply 2 ==> ... ? Frage: Was ergibt iter n double 1 ==> ... ? D. Rösner PGP 2011 . . . 43 D. Rösner PGP 2011 . . . 44 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Partielle Anwendung cont. Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Bestimmung des Typs einer partiellen Anwendung Beispiel Streichungsregel (cancellation rule) (s.a. [Tho99], 10.4): doubleAll :: [Int] -> [Int] doubleAll = map (multiply 2) Wenn der Typ einer Funktion f t1 -> t2 -> ... -> tn -> t ist hier zwei partielle Anwendungen: und diese wird angewendet auf e1 ::t1 , e2 ::t2 , ..., ek ::tk mit (k<=n), multiply 2 :: Int -> Int map (multiply 2) :: [Int] -> [Int] dann ergibt sich der Ergebnistyp durch „Streichen“ der Typen t1 bis tk , Variante ohne partielle Anwendung von map: Beispiel d.h. der Ergebnistyp von f e1 e2 ... ek ist tk +1 -> tk +2 -> ... tn -> t doubleAll xs = map (multiply 2) xs D. Rösner PGP 2011 . . . Funktionen in Haskell D. Rösner PGP 2011 . . . 45 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Assoziativität 46 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Beachte: Beachte: jede Funktion in Haskell nimmt exakt ein Argument Funktionsanwendung ist linksassoziativ, d.h. f x y = (f x) y So bedeutet multiply :: Int -> Int -> Int wegen der Rechtsassoziativität multiply :: Int -> (Int -> Int) -> ist rechtsassoziativ, d.h. a -> b -> c entspricht a -> (b -> c) Damit multiply 2 :: Int -> Int und (multiply 2) 5 :: Int -> ist nicht assoziativ; Beispiel: g :: (Int -> Int) -> Int g h = (h 0) + (h 1) D. Rösner PGP 2011 . . . 47 D. Rösner PGP 2011 . . . 48 Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Funktionen in Haskell Funktionen in Haskell Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Literatur: I Peter Pepper and Petra Hofstedt. Funktionale Programmierung – Sprachdesign und Programmiertechnik. Springer, Heidelberg, 2006. ISBN-10 3-540-20959-X; ISBN-13 978-3-540-20959-1. Allgemein (s.a. [Tho99], 10.4): f e1 e2 ... ek bzw. t1 -> t2 -> ... tn -> t sind Abkürzungen für (...((f e1 ) e2 ) ... ek ) bzw. t1 -> (t2 -> (...(tn -> t) ...)) D. Rösner PGP 2011 . . . Funktionen in Haskell Fethi Rabhi and Guy Lapalme. Algorithms – A Functional Programming Approach. Pearson Education Ltd., Essex, 1999. 2nd edition, ISBN 0-201-59604-0. 49 Funktionen . . . höherer Ordnung Abstraktion . . . als Wert Literatur: II 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 . . . 51 D. Rösner PGP 2011 . . . 50