Praktische Informatik 3 (WS 2012/13) - informatik.uni

Werbung
Fahrplan
I
Praktische Informatik 3: Funktionale Programmierung
Vorlesung 5 vom 13.11.2012: Funktionen Höherer Ordnung I
Christoph Lüth
Universität Bremen
Wintersemester 2012/13
Rev. 1872
I
Einführung
I
Funktionen und Datentypen
I
Rekursive Datentypen
I
Typvariablen und Polymorphie
I
Funktionen höherer Ordnung I
I
Funktionen höherer Ordnung II
I
Typinferenz
I
Teil II: Funktionale Programmierung im Großen
I
Teil III: Funktionale Programmierung im richtigen Leben
1 [29]
Inhalt
2 [29]
Ähnliche Funktionen der letzten Vorlesung
I
Pfade:
c a t :: Path → Path → Path
c a t Mt p = p
c a t ( Cons p p s ) q s = Cons p ( c a t p s q s )
I
Funktionen höherer Ordnung
I
Funktionen als gleichberechtigte Objekte
I
Funktionen als Argumente
I
Teil I: Funktionale Programmierung im Kleinen
I
r e v :: Path → Path
r e v Mt = Mt
r e v ( Cons p p s ) = c a t ( r e v p s ) ( Cons p Mt)
Gelöst durch Polymorphie
Zeichenketten:
c a t :: M y S t r i n g → M y S t r i n g → M y S t r i n g
c a t Empty t
= t
c a t ( Cons c s ) t = Cons c ( c a t s t )
Spezielle Funktionen: map, filter, fold und Freunde
r e v :: M y S t r i n g → M y S t r i n g
r e v Empty
= Empty
r e v ( Cons c t ) = c a t ( r e v t ) ( Cons c Empty )
3 [29]
Ähnliche Funktionen der letzten Vorlesung
4 [29]
Muster der primitiven Rekursion
k a s s e :: E i n k a u f s w a g e n → I n t
k a s s e LeererWagen = 0
k a s s e ( E i n k a u f a m e ) = c e n t a m+ k a s s e e
i n v e n t u r :: L a g e r → I n t
inventur LeeresLager = 0
i n v e n t u r ( L a g e r a m l ) = c e n t a m+ i n v e n t u r l
l e n :: M y S t r i n g → I n t
l e n Empty
= 0
l e n ( Cons c s t r ) = 1+ l e n s t r
I
Anwenden einer Funktion auf jedes
Element der Liste
I
möglicherweise Filtern bestimmter
Elemente
I
Kombination der Ergebnisse zu einem
Gesamtergebnis E
x1
x3
x2
x4
Gemeinsamkeiten:
I
ein Fall pro Konstruktor
I
linearer rekursiver Aufruf
I
durch Polymorphie nicht gelöst (Instanz einer Definition)
E
5 [29]
Ein einheitlicher Rahmen
I
Funktionen Höherer Ordnung
Beispiele:
toL :: S t r i n g → S t r i n g
toL [ ]
= []
toL ( c : c s ) =
t o L o w e r c : toL c s
I
6 [29]
toU :: S t r i n g → S t r i n g
toU [ ]
= []
toU ( c : c s ) =
t o U p p e r c : toL c s
Slogan
“Functions are first-class citizens.”
Warum nicht . . .
map f [ ]
= []
map f ( c : c s ) = f c : map f c s
toL c s = map t o L o w e r c s
toU c s = map t o U p p e r c s
I
Funktion f als Argument
I
Was hätte map für einen Typ?
7 [29]
I
Funktionen sind gleichberechtigt: Ausdrücke wie alle anderen
I
Grundprinzip der funktionalen Programmierung
I
Modellierung allgemeiner Berechungsmuster
I
Kontrollabstraktion
8 [29]
Funktionen als Argumente: map
Funktionen als Argumente: filter
I
map wendet Funktion auf alle Elemente an
I
Elemente filtern: filter
I
Signatur:
I
Signatur:
map ::
I
(α→ β ) → [ α ] → [ β ]
filter
Definition wie oben
I
map f [ ]
= []
map f ( x : x s ) = f x : map f x s
I
(α→ Bool ) → [ α ] → [ α ]
Definition
filter p []
= []
f i l t e r p ( x : xs )
| p x
= x : f i l t e r p xs
| otherwise = f i l t e r p xs
Auswertung (wie vorher):
toL "ABC"
map toLower (’A’:’B ’:’ C’: [ ])
toLower ’A’ : map toLower (’B’:’C’: [ ])
...
’a ’:’ b ’:’ c’ : map toLower [ ]
’a ’:’ b ’:’ c ’: [ ] = "abc"
I
::
I
Beispiel:
l e t t e r s :: S t r i n g → S t r i n g
l e t t e r s = f i l t e r isAlpha
Funktionsausdrücke reduzieren durch Applikation
9 [29]
Beispiel filter: Primzahlen
I
10 [29]
Funktionen als Argumente: Funktionskomposition
Sieb des Erathostenes
I
I
I
Für jede gefundene Primzahl p alle Vielfachen heraussieben
Dazu: filtern mit \n→ mod n p /=0!
Namenlose (anonyme) Funktion
I
(◦) :: (β → γ ) → (α→ β ) → α→ γ
( f ◦ g) x = f (g x)
s i e v e :: [ I n t e g e r ] → [ I n t e g e r ]
sieve []
= []
s i e v e ( p : ps ) =
p : s i e v e ( f i l t e r ( \n → mod n p /= 0 ) p s )
I
Primzahlen im Intervall [1.. n]:
I
prim esTo :: I n t e g e r → [ I n t e g e r ]
prim esTo n = s i e v e [ 2 . . n ]
I
Funktionskomposition (mathematisch)
I
Vordefiniert
I
Lies: f nach g
Funktionskomposition vorwärts:
(>.>) :: (α→ β ) → (β → γ ) → α→ γ
( f >.> g ) x = g ( f x )
Die ersten n Primzahlen:
p r i m e s :: I n t → [ I n t e g e r ]
primes n = take n ( s i e v e [ 2 . . ] )
I
Nicht vordefiniert!
11 [29]
η-Kontraktion
I
12 [29]
Partielle Applikation
I
Vertauschen der Argumente (vordefiniert):
Funktionskonstruktor rechtsassoziativ:
f l i p :: (α→ β → γ ) → β → α→ γ
flip f b a = f a b
a → b→ c ≡ a→ (b→ c)
I
I
Damit Funktionskomposition vorwärts:
I
Inbesondere: (a → b)→ c 6= a→ (b→ c)
Funktionsanwendung ist linksassoziativ:
(>.>) :: (α→ β ) → (β → γ ) → α→ γ
(>.>) = f l i p (◦)
f a b ≡ ( f a) b
I
I
I
Da fehlt doch was?! Nein:
(>.>) = flip (◦) ≡
I
(>.>) f g a = flip (◦) f g a
I
I
Partielle Anwendung von Funktionen:
I
η-Kontraktion (η-Äquivalenz)
I
Bedingung: E :: α→β, x :: α, E darf x nicht enthalten
λx→ E x ≡ E
Syntaktischer Spezialfall Funktionsdefinition (punktfreie Notation)
f x =E x ≡ f =E
Inbesondere: f (a b) 6= ( f a) b
Für f :: a→ b→ c, x :: a ist f x :: b→ c (closure)
Beispiele:
I
I
I
map toLower :: String→ String
(3 ==) :: Int→ Bool
concat ◦ map ( replicate 2) :: String→ String
13 [29]
Einfache Rekursion
I
14 [29]
Einfache Rekursion
Einfache Rekursion: gegeben durch
I
I
I
eine Gleichung für die leere Liste
I
eine Gleichung für die nicht-leere Liste
(mit einem rekursiven Aufruf)
Beispiel: kasse, inventur, sum, concat, length,
(+
+), . . .
x1
x3
x2
f []
= A
f (x:xs) = x ⊗ f xs
x4
I
E
I
I
Parameter der Definition:
I
Startwert (für die leere Liste) A :: b
I
Rekursionsfunktion ⊗ :: a -> b-> b
Auswertung:
f [x1,..., xn] = x1 ⊗ x2 ⊗ . . . ⊗ xn ⊗ A
Auswertung:
sum [4,7,3]
concat [A, B, C]
length [4, 5, 6]
Allgemeines Muster:
4+7+3+0
A+
+B +
+ C+
+[]
1+ 1+ 1+ 0
15 [29]
I
Terminiert immer (wenn Liste endlich und ⊗, A terminieren)
I
Entspricht einfacher Iteration (while-Schleife)
16 [29]
Einfach Rekursion durch foldr
I
Beispiele: foldr
Einfache Rekursion
I
sum :: [ I n t ] → I n t
sum x s = f o l d r (+) 0 x s
I
Basisfall: leere Liste
I
Rekursionsfall: Kombination aus Listenkopf und Rekursionswert
I
I
Signatur
foldr
I
::
Summieren von Listenelementen.
Flachklopfen von Listen.
c o n c a t :: [ [ a ] ] → [ a ]
c o n c a t x s = f o l d r ( ++ )
(α→ β → β ) → β → [ α ] → β
Definition
I
foldr f e []
= e
f o l d r f e ( x : xs ) = f x ( f o l d r f e xs )
[ ] xs
Länge einer Liste
l e n g t h :: [ a ] → I n t
l e n g t h x s = f o l d r ( λx n → n+ 1 ) 0 x s
17 [29]
Beispiele: foldr
I
18 [29]
Noch ein Beispiel: rev
I
Kasse:
k a s s e :: E i n k a u f s w a g e n → I n t
k a s s e = f o l d r ( λ ( a , m) r → c e n t a m+ r ) 0
I
I
Listen umdrehen:
r e v :: [ a ] → [ a ]
rev [ ]
= []
r e v ( x : x s ) = r e v x s ++ [ x ]
type E i n k a u f s w a g e n = [ ( A r t i k e l , Menge ) ]
Inventur
Mit fold:
rev xs = f o l d r snoc
type L a g e r = [ ( A r t i k e l , Menge ) ]
[ ] xs
s n o c :: a → [ a ] → [ a ]
s n o c x x s = x s ++ [ x ]
i n v e n t u r :: L a g e r → I n t
i n v e n t u r = f o l d r ( λ ( a , m) r → c e n t a m+ r ) 0
I
Unbefriedigend: doppelte Rekursion
19 [29]
Einfache Rekursion durch foldl
I
foldr faltet von rechts:
foldr ⊗ [x1 , ..., xn ] A = x1 ⊗ (x2 ⊗ (. . . (xn ⊗ A)))
I
Warum nicht andersherum?
foldl ⊗ [x1 , ..., xn ] A = (((A ⊗ x1 ) ⊗ x2 ) . . .) ⊗ xn
I
Definition von foldl:
20 [29]
Beispiel: rev revisited
I
Listenumkehr ist falten von links:
rev ’ xs = f o l d l ( f l i p
I
f o l d l :: (α → β → α) → α → [ β ] → α
foldl f a [] = a
f o l d l f a ( x : xs ) = f o l d l f ( f a x ) xs
(:))
[ ] xs
Nur noch eine Rekursion
21 [29]
foldr vs. foldl
I
22 [29]
foldl = foldr
Definition (Monoid)
f = foldr ⊗ A entspricht
(⊗, A) ist ein Monoid wenn
f []
= A
f (x:xs) = x ⊗ f xs
I
I
Kann nicht-strikt in xs sein, z.B. and, or
(Neutrales Element links)
x⊗A=x
(Neutrales Element rechts)
(x ⊗ y) ⊗ z = x ⊗ (y ⊗ z)
f = foldl ⊗ A entspricht
(Assoziativät)
Theorem
Wenn (⊗, A) Monoid, dann für alle A, xs
f xs
= g A xs
g a []
= a
g a (x:xs) = g (a ⊗ x) xs
I
A⊗x=x
foldl ⊗ A xs = foldr ⊗ A xs
Endrekursiv (effizient), aber strikt in xs
23 [29]
I
Beispiele: length, concat, sum
I
Gegenbeispiel: rev
24 [29]
Funktionen Höherer Ordnung: Java
I
I
Funktionen Höherer Ordnung: C
Java: keine direkte Syntax für Funktionen höherer Ordnung
Folgendes ist nicht möglich:
I
typedef s t r u c t l i s t _ t {
void
∗ elem ;
struct l i s t _ t ∗ next ;
} ∗list ;
interface Collection {
Object f o l d ( Object f ( Object a , C o l l e c t i o n c ) ,
Object a ) }
I
Aber folgendes:
list
interface Foldable {
Object f ( Object a ) ; }
interface Collection {
Object f o l d ( Foldable f , Object a ) ; }
I
Implizit vorhanden: Funktionen = Zeiger auf Funktionen
Vergleiche Iterator aus Collections Framework (Java SE 6):
f i l t e r ( i n t f ( void ∗x ) , l i s t
l );
I
Keine direkte Syntax (e.g. namenlose Funktionen)
I
Typsystem zu schwach (keine Polymorphie)
I
Benutzung: signal (C-Standard 7.14.1)
#i n c l u d e <s i g n a l . h>
p u b l i c i n t e r f a c e I t e r a t o r<E>
boolean hasNext ( ) ;
E next ( ) ; }
void ( ∗ s i g n a l ( i n t sig , void ( ∗ func ) ( i n t ) ) ) ( i n t ) ;
25 [29]
Funktionen Höherer Ordnung: C
26 [29]
Übersicht: vordefinierte Funktionen auf Listen II
Implementierung von filter:
l i s t f i l t e r ( i n t f ( void ∗x ) , l i s t
{ i f ( l == NULL) {
r e t u r n NULL ;
}
else {
list r;
r= f i l t e r ( f , l → n e x t ) ;
i f ( f ( l → elem ) ) {
l → n e x t= r ;
return l ;
}
else {
free ( l );
return r ;
} }
}
l)
map
:: (α→ β ) → [ α ] → [ β ]
−− Auf alle anwenden
f i l t e r :: (α→ Bool ) → [ α ] → [ α ] −− Elemente filtern
foldr
:: (α→ β → β ) → β → [ α ] → β −− Falten v. rechts
foldl
:: (β → α→ β ) → β → [ α ] → β −− Falten v. links
t a k e W h i l e :: (α→ Bool ) → [ α ] → [ α ]
d r o p W h i l e :: (α→ Bool ) → [ α ] → [ α ]
−− takeWhile ist längster Prefix so dass p gilt, dropWhile der Rest
any
:: (α → Bool ) → [ α ] → Bool −− p gilt mind. einmal
all
:: (α → Bool ) → [ α ] → Bool −− p gilt für alle
elem :: ( Eq α) ⇒ α → [ α ] → Bool −− Ist enthalten?
z i p W i t h :: (α → β → γ ) → [ α ] → [ β ] → [ γ ]
−− verallgemeinertes zip
27 [29]
Zusammenfassung
I
I
Funktionen höherer Ordnung
I
Funktionen als gleichberechtigte Objekte und Argumente
I
Partielle Applikation, η-Kontraktion, namenlose Funktionen
I
Spezielle Funktionen höherer Ordnung: map, filter, fold und Freunde
Formen der Rekursion:
I
Einfache Rekursion entspricht foldr
29 [29]
28 [29]
Herunterladen