Funktionen als Werte: Funktionen als Werte: cont. Beispiel: Manipulation beliebiger reeller Funktionen (vgl. [Pepper 1999, 8.2.2]) mirror :: (Float -> Float) -> (Float -> Float) mirror f x = f (-x) Sei f :: Float -> Float beliebig. stretch :: Float -> (Float -> Float) -> (Float -> Float) Dann: stretch r f x = f (x/r) shift :: Float -> (Float -> Float) -> (Float -> Float) Fragen: shift dx f x = f (x - dx) • Wie wirken sich shift, mirror und stretch aus? ... • Wie lassen sie sich als Funktionskomposition darstellen? c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 105 Funktionskomposition c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 106 Funktionskomposition: Variante Vorwärtskomposition Verknüpfung von Funktionen als Kontrollstruktur: f . g bedeutet: wende zuerst g, dann f an; m.a.W. Verknüpfung muss von rechts nach links gelesen werden als ‘g, dann f’ Ausgabe einer Funktion wird Eingabe der nachfolgenden Definition: Definition eines Operators >.>, der Funktionen in der Reihenfolge von links nach rechts verknüpft: (f . g) x = f ( g x ) Typ von ‘.‘: infixl 9 >.> (.) :: (b -> c) -> (a -> b) -> (a -> c) (>.>) :: (a -> b) -> (b -> c) -> (a -> c) Funktionskomposition ist assoziativ, d.h. für alle f, g und h g >.> f = f . g f . (g . h) = (f . g) . h z.B. bei Pictures.hs: rotate = flipH >.> flipV in Haskell aus technischen Gründen als rechtsassoziativ behandelt c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 107 c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 108 Funktionskomposition: eine Funktion zweimal anwenden Funktionskomposition Verallgemeinerung: n-fach wiederholte Funktionsanwendung twice :: (a -> a) -> (a -> a) twice f = f . f iter :: Int -> (a -> a) -> (a -> a) iter n f | n > 0 = f . iter (n-1) f |otherwise = id Sei succ :: Int -> Int succ n = n + 1 Frage: Was ergibt iter n double 1 ==> ... ? Was ergibt dann (twice succ) 7 ==> ... ? [Bem.: Variante: Mit Faltung definierbar als iter n f = foldr (.) id (replicate n f) ] c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 109 Partielle Anwendung c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 110 Partielle Anwendung cont. Beispiel: zwei partielle Anwendungen: multiply :: Int -> Int -> Int multiply x y = x * y • multiply 2 :: Int -> Int • map (multiply 2) :: [Int] -> [Int] Frage: was ergibt multiply 2 ==> ... ? Variante ohne partielle Anwendung von map: doubleAll xs = map (multiply 2) xs Beispiel: doubleAll :: [Int] -> [Int] doubleAll = map (multiply 2) c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 111 c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 112 Bestimmung des Typs einer partiellen Anwendung Assoziativität Beachte: Streichungsregel (cancellation rule): Wenn der Typ einer Funktion f t1 -> t2 -> ...tn -> t ist und diese wird angewendet auf e1::t1 , e2::t2 , ..., ek ::tk mit (k<=n), • Funktionsanwendung ist linksassoziativ, d.h. f x y = (f x) y f x y /= f (x y) • -> ist rechtsassoziativ, d.h. a -> b -> c entspricht a -> (b -> c) dann ergibt sich der Ergebnistyp durch „Streichen“ der Typen t1 bis tk , • -> ist nicht assoziativ; Beispiel: d.h. der Ergebnistyp von f e1 e2 ...ek ist g :: (Int -> Int) -> Int g h = (h 0) + (h 1) tk+1 -> tk+2 -> ...tn -> t c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 113 c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), Funktionen in Haskell Funktionen in Haskell Beachte: jede Funktion in Haskell nimmt exakt ein Argument Allgemein: f e1 e2 ...ek bzw. t1 -> t2 -> ...tn -> t So bedeutet multiply :: Int -> Int -> Int wegen der Rechtsassoziativität multiply :: Int -> (Int -> Int) Damit multiply 2 :: Int -> Int und (multiply 2) 5 :: Int c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 114 sind Abkürzungen für (...((f e1) e2 ) ...ek ) bzw. t1 -> (t2 -> (...(tn -> t) ...)) 115 c Prof. Dr. D. Rösner; erstellt: 14. Mai 2007 Sommer 2007, Programmierparadigmen (PGP), 116