Lambda-Kalkuel - Otto-von-Guericke

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