Programmieren in Haskell - Funktionen höherer Ordnung

Werbung
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
Herunterladen