Funktionale Programmierung

Werbung
Funktionale Programmierung
Jörg Kreiker
Uni Kassel und SMA Solar Technology AG
Wintersemester 2011/2012
1
Teil III
Muster und Fälle raten
2
Muster
• bekannte Muster: Variablen, Wildcards, leere/nicht-leere Listen
• Muster erlauben gleichzeitiges Testen und Zerlegen
strukturierter Werte
• Muster müssen linear sein, keine Variable mehr als einmal
• Vorkommen von Mustern:
• Musterbindungen
• λ Abstraktionen
• Funktionsbindungen
• Listencomprehensions
3
Haskell Muster
pat
F
|
|
|
|
|
c
x
K pat1 . . . patk
x@pat
˜pat
Wildcard
Literal
Variable
k -stelliger Konstruktor
’as’ Muster
irrefutable
4
Musterabgleich
• Muster werden mit Werten verglichen (matched)
• Mögliche Resultate
• Erfolg: Menge von Bindngen, [x1 7→ v1 , . . . , xn 7→ vn ] ∈ E
• Fehler, ↓
• Divergenz, ⊥
• Achtung: Werte können beliebig (un)reduziert sein
• Musterabgleich erzwingt Reduktion (forcing)
• Reduktion nur soweit wie nötig
5
Musterabgleich formal
Muster p gegen Wert v: p ]v ∈ Id → Val ∪ {⊥, ↓}
Muster p
x
c
Wert v
v
v
c0
⊥
K p1 . . . pk
K v1 . . . vk
K 0 v1 . . . vk
⊥
x@p
˜p
v
v
p ]v
[]
[x 7→ v ]
if c == c 0 then [] else ↓
⊥
p1 ]v1 ] . . . ] pk ]vk
↓
⊥
[x 7→ v ] ] p ]v
lazy pattern, nächste Folie
] ist linksassoziativ, vereinigt Umgebungen und ergibt ↓ /⊥ beim
ersten Vorkommen.
6
Lazy Patterns
• ∼ p ]v, wobei x1 , . . . , xk frei sind in p
• falls p ]v =↓ oder p ]v = ⊥ dann [x1 7→ ⊥, . . . , xk 7→ ⊥]
• Auswertung genau dann wenn eines der xi verwendet wird
• Bindung impliziert nicht Auswertung!
• Beispiel
case v of ∼ p → e
(λx1 x2 . . . xk → e ) (case v of p → x1 ) . . . (case v of p → xk )
7
Dynamische Semantik mit Mustern
• Lambda
λp1 . . . pk → e
case (x1 , . . . , xk ) of (p1 , . . . , pk ) → e
xi sind unverbrauchte Variablen.
• Let
let {p1 = e1 ; . . . ; pk = ek } in e
let (∼ p1 , . . . , ∼ pk ) = (e1 , . . . , ek ) in e
let p = e1 in e
case e1 of ∼ p → e
let p = e1 in e
let p = fix (λ∼ p → e1 ) in e
• Bindung in let Ausdrücken ist implizit lazy
• fix ist ein Fixpunkt Operator
• Listencomprehensions und Funktionsdefinitionen werden
analog zu case und λ Ausrücken reduziert
8
Beispiele
• let x = ⊥ in 0 =⇒ 0
• let (x,y) = ⊥ in 0 =⇒ 0 lazy let, irrefutable
• (\(x,y) -> 0) ⊥ =⇒ ⊥ refutable pattern
• (\˜(x,y) -> 0) ⊥ =⇒ 0 irrefutable pattern
• (\(x,y) -> 0) (⊥, ⊥) =⇒ 0
• (\(x:xs) -> (x:x:xs)) ⊥ =⇒ ⊥
• (\˜(x:xs) -> (x:x:xs)) ⊥ =⇒ ⊥ : ⊥ : ⊥
• irrefutable: lazy patterns, Variablen, Wildcards, as-Muster mit
irrefutable Teilmustern
• refutable: Konstruktoren, Literale
9
STOP
10
Case Ausdrücke
exp F case exp of { pat1 match1 ; . . . ; patn matchn }
Jedes matchi hat die Form
| gi1 → ei1 | gi2 → ei2 | . . . | gik → eiki where declsi
•
•
•
•
•
g ist ein Guard vom Typ Bool
k , n ≥ 1, jedes ki ≥ 1
Layout nach of
pat → exp
pat | True → exp
Beispiel:
map f x = case x of
[] -> [z] where z = f 0
(y:ys) | y < 0 -> (f (-y)) : z
| y > 0 -> (f y) : z
| otherwise -> z
where z = map f ys
11
Dynamische Semantik von case
case e of {p1 m1 ; . . . ; pn mn }
in Umgebung E, wobei jedes mi die Form
| gi1 → ei1 | gi2 → ei2 | . . . | gik → eiki where declsi
hat.
1. Gleiche e gegen p1 , p2 , . . . bis zum ersten Erfolg, pi , ab;
andernfalls 3.
2. Werte gi1 zu giki aus in E0 = E ⊕ pi ]e ⊕ [[declsi ]]
2.1 Falls alle gij zu False auswerten: 1.
2.2 Das erste j, für das gij zu True auswertet: Werte eij in E0 aus
3. gebe ⊥ zurück
12
Musterbindungen
p
| g1
=
e1
...
| gm
=
em
where {decls}
• Einfache Musterbindung p = e erzeugt Bindungen p ]e
• allgemeiner Fall zurückführen auf den einfachen:
p
=
let decls in
if g1 then e1 else
if g2 then e2 else
...
if gm then em else ⊥
13
Funktionsbindungen
x
...
x
p11
. . . p1k
m1
pn1
. . . pnk
mk
mi
= |
gi1
= ei1
| gimi = eimi
where {declsi }
• aufeinanderfolgend, gleiche Anzahl an Mustern, linear
• bindet x an einen funktionalen Wert
λx1 . . . xk → case (x1 , . . . xk ) of
(p11 , . . . , p1k ) m1
...
• funktionale Werte können an Infixoperatoren gebunden werden
f
f
‘map‘
‘map‘
[]
(x:xs)
=
=
[]
f x : f ‘map‘ xs
14
STOP
15
Zugehörige Unterlagen
Herunterladen