Programmierparadigmen - Lambda

Werbung
Funktionales Programmieren
Funktionales Programmieren
Gliederung
Programmierparadigmen
1
Lambda-Kalkuel
Funktionales Programmieren
Lambda-Kalkül
Einführung
D. Rösner
Lambda-Ausdrücke
Rechenregeln
Institut für Wissens- und Sprachverarbeitung
Fakultät für Informatik
Otto-von-Guericke Universität Magdeburg
Arithmetik
Boolesche Operationen
Datenstrukturen
Kontrollstrukturen
c
Sommer 2011, 20. Juni 2011, 2011
D.Rösner
D. Rösner PGP 2011 . . .
Funktionales Programmieren
1
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
D. Rösner PGP 2011 . . .
Funktionales Programmieren
Mathematische Funktionen:
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Mathematische Funktionen:
totale Funktion: alle Elemente des Urbildbereiches
besitzen ein Bild
Beispiel:
Sei f die Funktion, die jeder natürlichen Zahl a die kleinste
natürliche Zahl b zuordnet, für die gilt, dass die Ziffern von
a in dezimaler Repräsentation in der dezimalen Expansion
von π zum ersten Mal nach b Ziffern rechts vom
Dezimalpunkt auftauchen
z.B. a = 59, π = 3,14159, f (59) = 4
andernfalls: partielle Funktion
Frage: Ist f total oder partiell?
vgl. [Sco00], Ch. 11.2.4
vgl. [Sco00], Ch. 11.2.4
math.: Funktion ist (eindeutige) Abbildung einer Menge
(Urbild, domain) in eine andere Menge (Bildbereich, range)
z.B. sqrt: R → R
plus: [R × R] → R
D. Rösner PGP 2011 . . .
2
4
D. Rösner PGP 2011 . . .
5
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Funktionen als Mengen:
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionen sind math. Objekte:
Funktionen sind Teilmengen des kartesischen Produkts
aus Urbild- und Bildbereich
Wenn f Funktion von A nach B, dann ist f Teilmenge von A
× B,
d.h. f ist Element der Potenzmenge von A × B, d.h. der
Menge aller Teilmengen von A × B,
kurz: 2A×B
z.B. sqrt ⊂ [R × R]
plus ⊂ [R × R × R]
in Mengennotation:
sqrt ≡ {(x, y ) ∈ R × R|y = x 2 }
plus ≡ {(x, y , z) ∈ R × R × R|z = x + y }
wegen der geforderten Eindeutigkeit sind nicht alle
Elemente von 2A×B Funktionen von A nach B
beachte: dies sind intensionale Darstellungen, aber keine
Berechnungsvorschriften
vgl. [Sco00], Ch. 11.2.4
D. Rösner PGP 2011 . . .
Funktionales Programmieren
D. Rösner PGP 2011 . . .
6
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Funktionen sind math. Objekte:
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Lambda-Kalkül
Lambda-Ausdruck: rekursive Definition
Lambda-Ausdruck ist entweder
Funktionsraum A → B:
diejenigen Elemente von 2A×B , bei denen in jedem Paar
die erste Komponente eindeutig
1
(A → B) ⊂ 2A×B
2
höhere Funktionen in Mengennotation,
z.B.
compose ≡ {(f , g, h)|∀x ∈ R : h(x) = f (g(x))}
compose ∈ [(R → R) × (R → R)] → (R → R)
D. Rösner PGP 2011 . . .
7
3
4
Name
Lambda-Abstraktion aus λ, Name, Punkt und
Lambda-Ausdruck
Funktionsanwendung aus zwei nebeneinander stehenden
Lambda-Ausdrücken
geklammerter Lambda-Ausdruck
vgl. [Sco00], Ch. 11.2.4
8
D. Rösner PGP 2011 . . .
10
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Lambda-Kalkül
meist zusätzliche Vorrangregeln:
kontextfreie Grammatik (CFG) für Lambda-Ausdrücke mit
minimaler Klammernzahl
Funktionsanwendung linksassoziativ,
d.h.
expr → name|number| λ name . expr | func arg
func → name|(λ name . expr) | func arg
arg → name|number| (λ name . expr) | (func arg)
f A B interpretiert als (f A) B
(und nicht f (A B))
Anwendung hat höhere Präzedenz als Abstraktion,
d.h.
Bemerkung: es wird unterschieden zwischen
Lambda-Ausdrücken, die als Funktionen (s. func) , und
solchen, die als Argumente verwendet werden (s. arg).
λ x.AB interpretiert als λ x.(A B)
(und nicht (λ x.A)B)
vgl. [Sco00], Ch. 11.2.4
vgl. [Sco00], Ch. 11.2.4
D. Rösner PGP 2011 . . .
Funktionales Programmieren
11
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
D. Rösner PGP 2011 . . .
Funktionales Programmieren
Lambda-Kalkül
12
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Lambda-Kalkül
mit λ werden formale Parameter eingeführt
Ein Name < name > ist frei in einem λ-Ausdruck, wenn
einer der drei Fälle zutrifft:
der mit λ eingeführte Name wird im nachfolgenden
Ausdruck als gebunden bezeichnet und der Ausdruck ist
der Gültigkeitsbereich (Skopus) für diesen Namen
< name > ist frei in < name >.
< name > ist frei in λ < name1 > . < exp >, wenn der
Identifikator < name >6=< name1 > und < name > ist frei
in < exp >
< name > ist frei in E1 E2 wenn < name > ist frei in E1 oder
< name > ist frei in E2
eine nicht gebundene Variable heißt frei
freie Variable müssen in einem umgebenden Skopus
gebunden sein
Beispiel:
s.a. [Roj98]
in λ x.λ y. times x y ist x gebunden,
in λ y. times x y ist x frei
D. Rösner PGP 2011 . . .
13
D. Rösner PGP 2011 . . .
14
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Lambda-Kalkül
Ein Name < name > ist gebunden in einem λ-Ausdruck,
wenn einer der zwei Fälle zutrifft:
zur vereinfachten Referenz können Ausdrücken Namen
(im Sinne von Synonymen oder Kurzschreibweisen)
gegeben werden
z.B.
< name > ist gebunden in λ < name1 > . < exp >, wenn
der Identifikator < name >=< name1 > oder < name > ist
gebunden in < exp >
< name > ist gebunden in E1 E2 wenn < name > ist
gebunden in E1 oder < name > ist gebunden in E2
square ≡ λx.times x x
identity ≡ λx.x
const7 ≡ λx.7
hypot ≡ λx.λy. sqrt (plus (square x) (square y))
ein Identifikator kann in einem Ausdruck sowohl frei als
auch gebunden vorkommen
lies: ≡ ‘ist Abkürzung für’
Beispiel: (λx.xy )(λy .y )
s.a. [Roj98]
D. Rösner PGP 2011 . . .
Funktionales Programmieren
D. Rösner PGP 2011 . . .
15
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
16
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
β-Reduktion:
Für jede λ-Abstraktion λx.E und jeden Ausdruck M:
Zum Rechnen mit dem Lambda-Kalkül genügen im
wesentlichen drei Rechenregeln:
(λx.E)M →β E[M \ x]
β-Reduktion
α-Konversion
η-Reduktion
Dabei bezeichnet E[M \ x] den Ausdruck E mit allen freien
Vorkommen von x ersetzt durch M.
Anwendungsbedingung:
β-Reduktion ist nicht erlaubt, wenn irgendwelche in M freien
Variablen in E[M \ x] gebunden würden.
D. Rösner PGP 2011 . . .
18
D. Rösner PGP 2011 . . .
19
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
α-Konversion:
Für jede λ-Abstraktion λx.E und jede Variable y, die keine
freien Vorkommen in E hat:
Anwendungsbedingung der β-Reduktion:
verhindert sog. Variablenergreifen (engl. variable capture)
Beispiel:
λx.E →α λy .E[y \ x]
würde der Ausdruck (λx.(λy .xy ))y ohne Beachtung der
Anwendungsbedingung β-reduziert, so ergäbe sich
(λy .yy )
das korrekte Resultat ergibt sich, wenn zunächst eine
Umbenennung vorgenommen wird
(λx.(λy .xy ))y → (λx.(λt.xt))y
→ (λt.yt)
η-Reduktion:
Für jede λ-Abstraktion λx.E, wobei E von der Form F x und
x hat keine freien Vorkommen in F:
λx.Fx →η F
s.a. [Roj98]
(überflüssige λ-Abstraktionen eliminieren)
vgl. [Sco00], Ch. 11.2.4
D. Rösner PGP 2011 . . .
Funktionales Programmieren
20
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
D. Rösner PGP 2011 . . .
Funktionales Programmieren
Bemerkungen zu den Rechenregeln:
21
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
β-Reduktion:
ähnelt Parameterübergabe durch call-by-name;
unbeabsichtigtes ‘Ergreifen’ (capture) einer Variable wird
durch die Anwendungsbedingung verhindert
zusätzlich für Arithmetik (falls nicht direkt innerhalb des
Kalküls behandelt) : δ-Reduktion
ein Ausdruck der Form op x y mit x, y numerische Literale
und op aus kleiner Menge von Standardfunktionen kann
durch arithmetischen Wert ersetzt werden
Beispiele:
plus 2 3 →δ 5
minus 5 2 →δ 3
times 2 3 →δ 6
α-Konversion: Umbenennungen, damit β-Reduktion
möglich
η-Reduktion:
von geringerer Bedeutung
wenn square wie oben definiert, dann mit η-Reduktion
erlaubt:
vgl. [Sco00], Ch. 11.2.4
λx.square x →η square
vgl. [Sco00], Ch. 11.2.4
D. Rösner PGP 2011 . . .
22
D. Rösner PGP 2011 . . .
23
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
β-Reduktion und α-Konversion (und ggf. η-Reduktion)
werden wiederholt angewendet, bis keine weitere
Reduktion möglich ist und der λ-Ausdruck sich in seiner
einfachsten Form befindet
Church-Rosser [1936]:
Reduktion in Normalordnung:
wenn mehr als eine β-Reduktion möglich, wird hierbei
diejenige gewählt, deren λ am weitesten links im gesamten
Ausdruck steht
einfachste Formen sind eindeutig
jede Folge von Reduktionen, die in einem nicht weiter
reduzierbaren Ausdruck endet, produziert das gleiche
Resultat
Beispiel:
(λf.λg.λh.fg(hh))(λx.λy.x)h(λx.xx)
→β . . .
beachte: Termination ist nicht garantiert
vgl. [Sco00], Ch. 11.2.4
Beispiel: (λx.xx)(λx.xx)
→β . . .
vgl. [Sco00], Ch. 11.2.4
D. Rösner PGP 2011 . . .
Funktionales Programmieren
D. Rösner PGP 2011 . . .
24
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
25
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
Arithmetik mit natürlichen Zahlen lässt sich wie folgt im
λ-Kalkül darstellen:
eine Darstellung für natürliche Zahlen im λ-Kalkül
0 ≡ λs.(λz.z)
auch geschrieben als: λsz.z
die Definitionen weiterer Zahlen:
benötigt wird eine Darstellung für Null sowie
eine Darstellung für Nachfolger-Funktion (engl. successor)
n-fache Anwendung der Nachfolger-Funktion auf Null
repräsentiert dann die jeweilige Zahl n
1 ≡ λsz.s(z)
2 ≡ λsz.s(s(z))
3 ≡ λsz.s(s(s(z)))
...
die so dargestellten Zahlen werden auch als
Church-Numerale bezeichnet
vgl. u.a. [Roj98]
vgl. u.a. [Roj98]
D. Rösner PGP 2011 . . .
26
D. Rösner PGP 2011 . . .
27
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
die Nachfolger-Funktion lässt sich durch folgenden
Kombinator darstellen:
die Addition zweier Zahlen m und n wird zurückgeführt auf
die m-fach wiederholte Anwendung der
Nachfolger-Funktion auf die Zahl n
S ≡ λwyx.y(wyx)
Bemerkung: als Kombinatoren werden λ-Ausdrücke ohne
freie Variable bezeichnet
Beispiel: 2 + 3 wird berechnet durch die Reduktion von
(λsz.s(s(z)))(λwyx.y(wyx))(λuv.u(u(u(v))))
................................
................................
................................
Frage: Was ergibt die Anwendung von S auf 0, 1, . . . ?
................................
................................
................................
vgl. u.a. [Roj98]
vgl. u.a. [Roj98]
D. Rösner PGP 2011 . . .
Funktionales Programmieren
D. Rösner PGP 2011 . . .
28
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
29
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
Beispiel: 2 ∗ 2 wird berechnet durch die Reduktion (hier in
Normalordnung) von
die Multiplikation zweier Zahlen m und n wird realisiert
durch die Anwendung der Funktion
λxyz.x(yz)
auf die Zahlen m und n
(λxyz.x(yz))2 2
→β λz.2 (2 z)
Beispiel: 2 ∗ 2 wird berechnet durch die Reduktion von
(λxyz.x(yz))2 2
................................
................................
................................
→Def .2 λz.(λst.s(s t))(2 z)
→β λz.λt.(2 z)(2 z t)
→Def .2 λz.λt.((λuv.u(u v))z)(2 z t)
→β λz.λt.(λv.z(z v))(2 z t)
vgl. u.a. [Roj98]
...
D. Rösner PGP 2011 . . .
30
D. Rösner PGP 2011 . . .
31
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
Beispiel: cont.
auch die booleschen Werte T und F werden durch
Funktionen repräsentiert
...
T ≡ λxy.x
F ≡ λxy.y
→β λz.λt.z(z (2 z t)))
→Def .2 λz.λt.z(z ((λuv.u(u v)) z t))
als Funktionen werden die beiden Wahrheitswerte auch als
select_first bzw. select_second bezeichnet
→β λz.λt.z(z ((λv.z (z v)) t))
→β λz.λt.z(z (z (z t)))
vgl. u.a. [Roj98], [Sco00]
→Def .4 4
D. Rösner PGP 2011 . . .
Funktionales Programmieren
D. Rösner PGP 2011 . . .
32
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
33
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
die logischen Verknüpfungen lassen sich dann wie folgt
definieren:
Negation angewendet auf T ergibt
¬T ≡ λx.x(λuv.v)(λab.a) (λcd.c)
reduzierbar zu:
................................
................................
................................
∧ ≡ λxy.xy(λuv.v) ≡ λxy.xyF
∨ ≡ λxy.x(λuv.u)y ≡ λxy.xTy
Negation eines Arguments ergibt sich mit
¬ ≡ λx.x(λuv.v)(λab.a) ≡ λx.xFT
vgl. u.a. [Roj98]
vgl. u.a. [Roj98]
D. Rösner PGP 2011 . . .
34
D. Rösner PGP 2011 . . .
35
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
mit Paaren lassen sich weitere nützliche Funktionen
definieren
Paare (a, b) lassen sich als Funktion wie folgt darstellen:
λz.zab
Beispiel: Vorgängerfunktion (engl. predecessor)
die Selektion des ersten bzw. zweiten Elements des
Paares erfolgt dann durch Anwendung dieser Funktion auf
T bzw. F
Grundidee: kreiere Paare der Form (n, n − 1) und
selektiere das zweite Element
Umsetzung:
(λz.zab)T = . . .
(λz.zab)F = . . .
die folgende Funktion ordnet einem Paar (n, n − 1) das
Paar (n + 1, n) zu:
Φ ≡ (λpz.z(S(pT))(pT))
vgl. u.a. [Roj98]
vgl. u.a. [Roj98]
D. Rösner PGP 2011 . . .
Funktionales Programmieren
36
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
D. Rösner PGP 2011 . . .
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
37
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Rechnen mit dem Lambda-Kalkül
die Vorgängerfunktion P gewinnen wir dann mit folgendem
Vorgehen:
eine bedingte Verzweigung lässt sich als Funktion wie folgt
darstellen:
wende Φ n-mal auf das Paar λz.z00 an und
selektiere dann das zweite Element des entstandenen
Paares
im λ-Kalkül:
if ≡ λc.λt.λe.cte
vgl. [Sco00], Ch. 11.2.4
P ≡ λn.nΦ(λz.z00)F
vgl. u.a. [Roj98]
D. Rösner PGP 2011 . . .
38
D. Rösner PGP 2011 . . .
39
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Rechnen mit dem Lambda-Kalkül
Literatur: I
Chris Barker.
Lambda Tutorial, interactive tutorial.
http://homepages.nyu.edu/ cb125/Lambda/.
das erstaunlichste Ergebnis über den λ-Kalkül ist die
Darstellbarkeit rekursiver Funktionen
eine zentrale Rolle dabei spielt der Operator Y, definiert
durch:
Henk Barendregt and Erik Barendsen.
Introduction to Lambda Calculus, 2000.
revised; ftp://ftp.cs.ru.nl/pub/CompMath.Found/lambda.pdf.
Y ≡ λh.(λx.h(xx))(λx.h(xx))
vgl. [Sco00], Ch. 11.2.4
Kostas Chatzikokolakis.
LCI - A lambda calculus interpreter, an open source
interpreter.
http://lci.sourceforge.net/.
eine besonders detaillierte Herleitung von Y liefert [Gab01]
D. Rösner PGP 2011 . . .
Funktionales Programmieren
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
40
D. Rösner PGP 2011 . . .
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Funktionales Programmieren
Literatur: II
41
Lambda-Kalkül
Lambda-Ausdrücke
Rechenregeln
Literatur: III
Richard P. Gabriel.
The Why of Y, 2001.
http://www.dreamsongs.com/NewFiles/WhyOfY.pdf.
Michael Lee Scott.
Programming Language Pragmatics.
Academic Press, San Diego, CA, USA, 2000.
ISBN 1-55860-578-9.
Achim Jung.
A short introduction to the Lambda Calculus, 2004.
http://www.cs.nyu.edu/rgrimm/teaching/sp10-pl/lambdacalculus.pdf.
Raul Rojas.
A Tutorial Introduction to the Lambda Calculus, 1997/1998.
tutorial notes;
http://www.inf.fu-berlin.de/lehre/WS03/alpi/lambda.pdf.
D. Rösner PGP 2011 . . .
42
D. Rösner PGP 2011 . . .
43
Herunterladen