Programmieren in Haskell Stefan Janssen Programmieren in Haskell LambdaExpressions Funktionen höherer Ordnung Gestaffelte Funktionen Higher Order Functions Stefan Janssen Universität Bielefeld AG Praktische Informatik 3. Dezember 2014 Strictness Control More on fold Funktionen höherer Ordnung Programmieren in Haskell Worum geht es heute? Stefan Janssen LambdaExpressions In Haskell gibt es Funktionen, die Funktionen als Argument haben oder als Ergebnis liefern. Diese nennt man Funktionen höherer Ordnung. Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Davon kennen wir bisher Beispiele wie map oder (.) Was man insgesamt damit machen kann, ist damit noch lange nicht erschöpft ... “Funktionen als Bürger erster Klasse” Programmieren in Haskell Stefan Janssen Funktionen definieren kann man in jeder Programmiersprache. Eine funktionale Programmiersprache erlaubt auch LambdaExpressions Gestaffelte Funktionen Funktionen in Datenstrukturen, z.B. [(+), (-), (*)] Higher Order Functions Funktionen als Argmente, z.B. map square [1..100] Strictness Control Funktionen als Ergebnisse, z.B. f . g More on fold Wie entstehen Funktionen? Benannte Funktionen werden vom Programmierer definiert. Unbenannte Funktionen (engl. anonymous functions) entstehen durch teilweise Anwendung benannter Funktionen, z.B. (3+), (‘div‘ 2), ("niemals"++) map reverse Note ce (‘Note‘ (1/4)) map (1:) all_equal 3 4 (Natürlich kann man diesen anonymen Funktionen dann auch Namen geben: startnie = ("niemals"++)) durch Verknüpfung von Funktionen, z.B. reverse . concat oder durch ... Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Lambda-Abstraktion Programmieren in Haskell Abstraktion verwandelt einen Ausdruck in eine Funktion 3 ∗ a − b2 + 5 λa b → 3 ∗ a − b 2 + 5 ist ein Ausdruck ist eine Funktion von a und b b2 (λa b → 3 ∗ a − + 5)(2, 3) ist eine Funktionsanwendung und berechnet den Wert 2 Abstraktion: Vom konkreten zum Allgemeinen Dur3Klang cDur3kl = Note ce (1/4) :+: Note eh (1/4) :+: Note ge (1/4) versus dur3kl = \(t,d) -> Note t d :+: Note (t+4) d :+: Note (t+7) d Auf der rechten Seite der Gleichung steht eine anonyme Funktion (die links einen Namen bekommt) Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Lambda-Expressions in Haskell Programmieren in Haskell Man nennt sie ... Lambda-Abstractions Lambda-Ausdrücke Anonyme Funktionen Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Lambda-Expressions in Haskell Programmieren in Haskell Man nennt sie ... Lambda-Abstractions Lambda-Ausdrücke Anonyme Funktionen Example 1 2 3 4 (\ a b c - > b ^2 -4* a * c ) 1 5 4 map (\ x -> x ^2 + 1) [1..10] filter (\ x -> x ‘mod ‘ 5 == 0) [1..100] map (\( x , y ) -> x + y ) ( zip [1..10] [1..10]) Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Syntax Programmieren in Haskell Lambda-Ausdruck Einfache und allgemeine Form: Stefan Janssen λx1 . . . xn → expr (1) λpat1 . . . patn → expr (2) LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Syntax Programmieren in Haskell Lambda-Ausdruck Einfache und allgemeine Form: 1 2 Stefan Janssen λx1 . . . xn → expr (1) λpat1 . . . patn → expr (2) Bzw: in Haskell \ x1 ... xn -> expr \ pat1 ... patn -> expr definiert eine anonyme, n-stellige Funktion. LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Syntax Programmieren in Haskell Lambda-Ausdruck Einfache und allgemeine Form: 1 2 Stefan Janssen λx1 . . . xn → expr (1) λpat1 . . . patn → expr (2) Bzw: in Haskell \ x1 ... xn -> expr \ pat1 ... patn -> expr definiert eine anonyme, n-stellige Funktion. Wichtig: Lambda-Ausdruck ist ein Ausdruck, sein Wert eine Funktion. Er kann überall stehen, wo Ausdrücke erlaubt sind, z.B. als Argument einer Funktion/ eines Lambda-Ausdrucks LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Wiederholung: Pattern/Muster Programmieren in Haskell Stefan Janssen Pattern sind Ausdrücke bestehend aus natürlichen Zahlen Werten Variablen Datentyp-Konstruktoren Wildcard-Symbol: _ aber ohne Funktionen!! (– mit Ausnahme des Musters n + 1) LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Lambda-Patterns Programmieren in Haskell Stefan Janssen Lambda-Patterns erlauben pattern matching auf der “linken” Seite auch in anonymen Funktionen. Muster von mehrstelligen Konstruktoren müssen geklammert werden: Example 1 (\( x : xs ) -> x ) [4 ,3 ,2] LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Currying: 1-stellige versus n-stellige Funktionen n-stellige Funktionen lassen sich stets als 1-stellige Funktionen auffassen. Man nennt sie dann “curried” oder auf Deutsch curryfiziert (nach Haskell B. Curry) geschönfinkelt (nach Moses Schönfinkel) gestaffelt Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Currying: 1-stellige versus n-stellige Funktionen n-stellige Funktionen lassen sich stets als 1-stellige Funktionen auffassen. Man nennt sie dann “curried” oder auf Deutsch curryfiziert (nach Haskell B. Curry) geschönfinkelt (nach Moses Schönfinkel) gestaffelt Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Gestaffelte Sichtweise Strictness Control λpat1 pat2 . . . patn → expr (3) λpat1 → λpat2 → . . . λpatn → expr (4) More on fold Currying: 1-stellige versus n-stellige Funktionen n-stellige Funktionen lassen sich stets als 1-stellige Funktionen auffassen. Man nennt sie dann “curried” oder auf Deutsch curryfiziert (nach Haskell B. Curry) geschönfinkelt (nach Moses Schönfinkel) gestaffelt Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Gestaffelte Sichtweise Strictness Control λpat1 pat2 . . . patn → expr (3) λpat1 → λpat2 → . . . λpatn → expr (4) (λpat1 → (λpat2 → . . . (λpatn → expr))) (5) Bzw: More on fold Beispiel: sechsmal die gleiche Funktion Example 1 2 > add : : I n t −> I n t −> I n t > add x y = x + y 3 4 5 > add ’ : : I n t −> ( I n t −> I n t ) > add ’ x y = x + y 6 7 8 > add ’ ’ : : I n t −> ( I n t −> I n t ) > add ’ ’ x = \ y −> x + y 9 10 11 > add ’ ’ ’ : : I n t −> ( I n t −> I n t ) > add ’ ’ ’ = \ x y −> x + y 12 13 14 > add ’ ’ ’ ’ : : I n t −> ( I n t −> I n t ) > add ’ ’ ’ ’ = \ x −> \ y −> x + y 15 16 17 > add ’ ’ ’ ’ ’ : : I n t −> I n t −> I n t > add ’ ’ ’ ’ ’ = \ x −> \ y −> x + y Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Beispiele Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Typen: Was meint GHCi? Higher Order Functions Strictness Control More on fold Currying Programmieren in Haskell Stefan Janssen die verschiedenen Versionen von add haben den gleichen Typ → Denn -> (function type constructor) ist rechtsassoziativ in Haskell LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Currying Programmieren in Haskell Stefan Janssen die verschiedenen Versionen von add haben den gleichen Typ → Denn -> (function type constructor) ist rechtsassoziativ in Haskell Sichtweise: Das “zweistellige” add ist eine einstellige Funktion, die eine einstellige Funktion als Ergebnis hat LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Partielle Anwendung ohne Lambda Programmieren in Haskell Stefan Janssen LambdaExpressions Example 1 2 (1+) map (1+) [2 ,3 ,4] Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Kein Curry? Programmieren in Haskell Example 1 f (a , b ) = a + b Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Kein Curry? Programmieren in Haskell Stefan Janssen Example 1 f (a , b ) = a + b Gestaffelte Funktionen Ausweg: 1 2 curry curry f x y LambdaExpressions Higher Order Functions :: (( a , b ) -> c ) -> a -> b -> c = f (x , y ) Strictness Control More on fold Kein Curry? Programmieren in Haskell Stefan Janssen Example 1 f (a , b ) = a + b Gestaffelte Funktionen Ausweg: 1 2 curry curry f x y LambdaExpressions Higher Order Functions :: (( a , b ) -> c ) -> a -> b -> c = f (x , y ) Strictness Control More on fold Zuviel Curry? 1 2 uncurry uncurry f p :: ( a -> b -> c ) -> (( a , b ) -> c ) = f ( fst p ) ( snd p ) Fazit: Currying Programmieren in Haskell In Haskell: Stefan Janssen Nomen est omen LambdaExpressions Funktionen sind “per-default” gestaffelt Gestaffelte Funktionen Staffelung vermeidbar via Tupel Higher Order Functions Funktions-Typkonstruktor (->) ist rechtsassoziativ Functions-Anwendung ist linksassoziativ: f a b ist das gleiche wie (f a) b Strictness Control More on fold Fazit: Currying Programmieren in Haskell In Haskell: Stefan Janssen Nomen est omen LambdaExpressions Funktionen sind “per-default” gestaffelt Gestaffelte Funktionen Staffelung vermeidbar via Tupel Higher Order Functions Funktions-Typkonstruktor (->) ist rechtsassoziativ Functions-Anwendung ist linksassoziativ: f a b ist das gleiche wie (f a) b So gesehen ist jede mehrstellige Funktion in Haskell eine Higher-Order-Function. Strictness Control More on fold Higher Order Functions Programmieren in Haskell Funktionen höherer Ordnung Funktionen mit Funktionen als Parameter Funktionen mit Funktionen als Rückgabewert Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions In Haskell: Strictness Control More on fold Higher Order Functions Programmieren in Haskell Funktionen höherer Ordnung Funktionen mit Funktionen als Parameter Funktionen mit Funktionen als Rückgabewert Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions In Haskell: Funktionen als “1st class citizens” sind oft von höherer Ordnung Funktionen höherer Ordnung sind “Kontrollstrukturen”, die man (im Unterschied zu imperativen Sprachen) selbst definieren kann Strictness Control More on fold Wiederholung Programmieren in Haskell Stefan Janssen 1 2 3 Bekannte map :: map map Beispiele für Funktionen höherer Ordnung: (a - > b ) -> [ a ] -> [ b ] f [] = [] f ( x : xs ) = f x : map f xs 6 Gestaffelte Funktionen Higher Order Functions Strictness Control 4 5 LambdaExpressions filter :: ( a -> Bool ) -> [ a ] -> [ a ] filter p xs = [ x | x <- xs , p x ] More on fold Wiederholung A&D: Strukturelle Rekursion Programmieren in Haskell Stefan Janssen Srukturelle Rekursion auf Listen – Schema: f LambdaExpressions :: [σ] -> τ Gestaffelte Funktionen f [] = e1 Higher Order Functions f (a : as) = e2 Strictness Control where s = f as More on fold wobei e1 und e2 Ausdrücke vom Typ τ sind und e2 die Variablen a, as und s (nicht aber f ) enthalten darf. Beispiele Programmieren in Haskell length Stefan Janssen sum 1 2 prod LambdaExpressions and Gestaffelte Funktionen Alle folgen dem gleichen Schema wie z.B. and [] = True and ( x : xs ) = x && ( and xs ) Funktion Terminierungs- Anwendung wert (e1) auf x (e2) length 0 1 sum 0 x prod 1 x and True x Higher Order Functions Strictness Control Akkumulation des Ergebnisses (e2) + + * && More on fold Schema für diese Art der strukturellen Rekursion in Haskell Programmieren in Haskell foldr steht für “fold right” 1 2 3 4 foldr :: ( a -> b -> b ) -> b -> [ a ] -> b foldr _ e [] = e foldr f e ( x : xs ) = f x ( foldr f e xs ) 5 6 7 8 9 10 sum prod and or length = = = = = foldr foldr foldr foldr foldr (+) 0 (*) 1 (&&) True (||) False (\ a b -> 1 + b ) 0 Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Noch mehr Beispiele mit foldr ...? Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen 1 2 x ++ y = foldr (:) y x concat = foldr (++) [] Higher Order Functions Strictness Control More on fold foldr — sum aus der Vogelperspektive foldr f e ersetzt alle : durch f und [] durch e. Example [1..5] = [1,2,3,4,5] = 1:2:3:4:5:[] Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold foldr — sum aus der Vogelperspektive foldr f e ersetzt alle : durch f und [] durch e. Example Programmieren in Haskell Stefan Janssen [1..5] = [1,2,3,4,5] = 1:2:3:4:5:[] : LambdaExpressions Gestaffelte Funktionen 1 Higher Order Functions : 2 Strictness Control : More on fold 3 : 4 : 5 [] foldr — sum aus der Vogelperspektive foldr f e ersetzt alle : durch f und [] durch e. Programmieren in Haskell Example Stefan Janssen [1..5] = [1,2,3,4,5] = 1:2:3:4:5:[] : LambdaExpressions + Gestaffelte Funktionen 1 1 : 2 : 3 ⇒ foldr (+) 0 : 4 : 5 [] Higher Order Functions + 2 Strictness Control + 3 More on fold + 4 + 5 0 foldr — prod aus der Vogelperspektive Programmieren in Haskell : 1 Stefan Janssen : LambdaExpressions 2 : 3 Gestaffelte Funktionen Higher Order Functions : Strictness Control 4 : 5 [] More on fold foldr — prod aus der Vogelperspektive ∗ : 1 Stefan Janssen ∗ 1 : Programmieren in Haskell LambdaExpressions 2 ∗ 2 : Gestaffelte Funktionen ⇒ 3 Higher Order Functions ∗ 3 : Strictness Control 4 : 5 [] 4 ∗ 5 1 More on fold foldr — prod aus der Vogelperspektive ∗ : 1 Stefan Janssen ∗ 1 : Programmieren in Haskell LambdaExpressions 2 ∗ 2 : Gestaffelte Funktionen ⇒ 3 Higher Order Functions ∗ 3 : Strictness Control 4 : 5 [] 4 ∗ 5 1 → (1 ∗ (2 ∗ (3 ∗ (4 ∗ (5 ∗ 1))))) = 120 More on fold foldr — length Programmieren in Haskell : 1 Stefan Janssen : LambdaExpressions 2 : 3 Gestaffelte Funktionen Higher Order Functions : Strictness Control 4 : 5 [] More on fold foldr — length : 1 Programmieren in Haskell + : Stefan Janssen + 1 LambdaExpressions 2 : + 1 Gestaffelte Funktionen ⇒ 3 : Higher Order Functions + 1 Strictness Control 4 : 5 [] 1 + 1 0 More on fold foldr — length : 1 Programmieren in Haskell + : Stefan Janssen + 1 LambdaExpressions 2 : + 1 Gestaffelte Funktionen ⇒ 3 : Higher Order Functions + 1 Strictness Control 4 : 5 [] 1 + 1 0 → (1 + (1 + (1 + (1 + (1 + 0))))) = 5 More on fold “Rechenstrategie” Vogelperspektive Programmieren in Haskell Stefan Janssen Vogelperspektive bzgl. f bedeutet: Rechne so viel (und NUR so viel) bis alle Auftreten von f verschwunden sind. das ist i.A. werder inner- noch outermost aber auf jeden Fall mathematisch korrekt. Dient nicht dem wirklichen Rechnen, aber dem Programmverstehen. LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold foldr klammert von rechts ... Programmieren in Haskell Stefan Janssen 1 2 3 length " acbde " = > ( 1 + ( 1 + ( 1 + ( 1 + ( 1 + 0 ) ) ) ) ) and [ True , False , True ] = > True && ( False && ( True && False )) LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control ... geht’s auch von links her? More on fold foldl Programmieren in Haskell : f : 1 5 f Stefan Janssen f LambdaExpressions f 1 Gestaffelte Funktionen 4 f 3 f : 2 foldl ⇐ foldr ⇒ : 3 f 2 Higher Order Functions Strictness Control f 3 More on fold f e 1 2 4 : 5 [] 4 f 5 e foldl-Definition Programmieren in Haskell Stefan Janssen 1 2 3 foldl :: ( b -> a -> b ) -> b -> [ a ] -> b foldl _ e [] = e foldl f e ( x : xs ) = foldl f ( f e x ) xs LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control Der Endwert e ist jetzt ein Startwert. More on fold Unterschiede foldl, foldr Programmieren in Haskell Stefan Janssen Unterschiedliche Faltung foldr klammert rechtsassoziativ: ((a1 · (a2 · (a3 · . . . · (an · e))))) LambdaExpressions (6) Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Unterschiede foldl, foldr Programmieren in Haskell Stefan Janssen Unterschiedliche Faltung foldr klammert rechtsassoziativ: ((a1 · (a2 · (a3 · . . . · (an · e))))) LambdaExpressions (6) Gestaffelte Funktionen Higher Order Functions Strictness Control foldl klammert linksassoziativ: More on fold (((((e · a1 ) · a2 ) · a3 ) · . . .) · an ) (7) die Faltung von foldr entspricht der Datentypdefinition ggf. Platzbedarf besser bei foldl Unterschiede foldl, foldr Programmieren in Haskell Stefan Janssen LambdaExpressions 1 Eigenschaft Gestaffelte Funktionen foldr f e ( reverse x ) = foldl ( flip f ) e x Higher Order Functions Strictness Control More on fold Unterschiede foldl, foldr Programmieren in Haskell Stefan Janssen LambdaExpressions 1 Eigenschaft Gestaffelte Funktionen foldr f e ( reverse x ) = foldl ( flip f ) e x Higher Order Functions Beispiel siehe Tafel. Strictness Control More on fold foldl Beispiele Programmieren in Haskell Stefan Janssen LambdaExpressions sum = foldl (+) 0 Gestaffelte Funktionen or = foldl (||) False Higher Order Functions concat = foldl (++) [] ... Strictness Control More on fold Fold im Allgemeinen Programmieren in Haskell Stefan Janssen Fold-Operationen verarbeiten rekursive Datentypen nach deren Rekursionsschema, also mit struktureller Rekursion Kompakter Code Vermeidung von Redundanz Angabe des Wesentlichen Vermeidung von Fehlern bei hand-programmierter Rekursion LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Weitere Beispiele? Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Weitere Beispiele? Programmieren in Haskell Stefan Janssen 1 2 3 4 Die Funktion tabulate verwandelt Funktionen über einem Lambdagegebenen Intervall in tabellierende Funktionen Expressions Gestaffelte > tabulate :: ( Int , Int ) - >( Int - > a ) - >( Int - > a ) Funktionen > tabulate ( lo , up ) f = ( t !) where Higher Order Functions > t = array ( lo , up ) ( zip domain ( map f domain )) Strictness > domain = [ lo .. up ] Control 1 2 More on fold > g = tabulate f was sich beim mehrfachen Aufruf von g anstelle von f bezahlt macht. Combinator Languages, eDSLs Programmieren in Haskell Funktionen höherer Ordnung, deren Argumente nur Funktionen sind, nennt man “Kombinatoren”. In manchen Anwendungen gibt es eine Anzahl komplexer, spezifischer Operationen, die sich zu Kombinatoren abstrahieren lassen. Beispiele: Parsing, Prettyprinting, Dynamic Programming, Format-Transformationen Dies führt zur Definition von anwendungs-spezifischen Sprachen, “eingebettet” in Haskell (embedded domain specific languages, eDSLs) Dies ist der schnellste Weg zu einer DSL, aber nicht der Weg zur schnellsten DSL Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Zusammenfassung Programmieren in Haskell Stefan Janssen Wann definiert man selbst neue Funktionen höherer Ordnung? Wenn sich die gleiche Verknüpfung anderer Funktionen mehrfach wiederholt, ... LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Zusammenfassung Programmieren in Haskell Stefan Janssen Wann definiert man selbst neue Funktionen höherer Ordnung? Wenn sich die gleiche Verknüpfung anderer Funktionen mehrfach wiederholt, ... ... macht die Verwendung von Kombinatoren die Systematik transparent, hilft beim Vermeiden von Fehlern, und erhöht so die eigene Programmier-Produktivität LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Weitere Funktionen höherer Ordnung 1 Zum Beispiel die Funktions-Komposition: infixr 9 . Programmieren in Haskell Stefan Janssen 2 3 4 (.) f . g :: ( b -> c ) -> ( a -> b ) -> a -> c = \ x -> f ( g x ) LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Weitere Funktionen höherer Ordnung 1 Zum Beispiel die Funktions-Komposition: infixr 9 . Programmieren in Haskell Stefan Janssen 2 3 4 5 6 (.) f . g Oder: (.) (.) f g :: ( b -> c ) -> ( a -> b ) -> a -> c = \ x -> f ( g x ) :: ( b -> c ) -> ( a -> b ) -> a -> c x = f (g x) LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold Weitere Funktionen höherer Ordnung 1 Zum Beispiel die Funktions-Komposition: infixr 9 . Programmieren in Haskell Stefan Janssen 2 3 4 5 6 1 (.) :: ( b -> c ) -> ( a -> b ) -> a -> c f . g = \ x -> f ( g x ) Oder: (.) :: ( b -> c ) -> ( a -> b ) -> a -> c (.) f g x = f ( g x ) Übersichtlich für Algorithmen mit mehreren Phasen > treeSort = sortTree . build LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold 2 3 4 > compile = writeCode .m - opt . codegen . implmap . > transform . semCheck . parse . tokenize Das zweite Beispiel beschreibt die typischen Phasen eines Compilers $, $! und seq Programmieren in Haskell 1 Oder sogar die Funktionsanwendung als Funktion: infixr 0 $ LambdaExpressions 2 3 4 Stefan Janssen ($) f $ x :: ( a -> b ) -> a -> b = f x -- $ heisst " apply " Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold $, $! und seq Programmieren in Haskell 1 Oder sogar die Funktionsanwendung als Funktion: infixr 0 $ LambdaExpressions 2 3 4 Stefan Janssen ($) f $ x :: ( a -> b ) -> a -> b = f x -- $ heisst " apply " infix application operator spart Klammern Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold $, $! und seq Programmieren in Haskell 1 Oder sogar die Funktionsanwendung als Funktion: infixr 0 $ LambdaExpressions 2 3 4 Stefan Janssen ($) f $ x :: ( a -> b ) -> a -> b = f x -- $ heisst " apply " infix application operator spart Klammern Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold 1 2 Strikte Funktionsanwendung > infixr 0 $ ! > f $ ! x = x ‘seq ‘ f x -- = f x , aber strikt seq ist die sequentielle Auswertung und dient der Vermeidung unerwünschter Laziness. $, $! und seq seq ist eingebaute Funktion mit den Eigenschaften a ‘seq‘ b = ⊥, falls a = ⊥ a ‘seq‘ b = b, falls x 6= ⊥ Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen 1 2 Es ändert ggf. Laufzeit (schneller oder langsamer), Speicherplatz (i.A. weniger) und Terminierungsverhalten (falls überhaupt problematisch), nicht aber die Ergebnisse einer Funktion wenn sie definiert ist. Vergleiche: let { cond a b c = if a then b else c ; x = x } in ( cond True 1) $ x 3 4 5 let { cond a b c = if a then b else c ; x = x } in ( cond True 1) $ ! x Higher Order Functions Strictness Control More on fold foldr1 Programmieren in Haskell Stefan Janssen 1 2 3 4 Listerverarbeitung ohne Startwert, von rechts: foldr1 :: ( a -> a -> a ) -> [ a ] -> a foldr1 (*) = f where f [ a ] = a f ( a : b : xs ) = a * f ( b : xs ) Das letzte Listenelement dient als Startwert LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold foldl1 Programmieren in Haskell Stefan Janssen LambdaExpressions 1 2 ... und das Gleiche von links her: foldl1 :: ( a -> a -> a ) -> [ a ] -> a foldl1 (*) ( x : xs ) = foldl (*) x xs Das erste Listenelement dient als Startwert Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold foldl1-Beispiele Programmieren in Haskell Stefan Janssen LambdaExpressions Gestaffelte Funktionen Higher Order Functions Strictness Control More on fold foldl1-Beispiele Programmieren in Haskell Stefan Janssen LambdaExpressions 1 2 minimum = foldl1 min maximum = foldl1 max Gestaffelte Funktionen Higher Order Functions Strictness Control Geht’s kürzer? More on fold