3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 Beispiele � Der formale Parameter kann mehrfach im Funktionsrumpf auftreten: (λx. + x x) 5 � � β � δ 10 Der formale Parameter muss nicht im Funktionsrumpf auftreten: (λx. 3) 5 � +55 � β 3 In einem Funktionsrumpf kann eine weitere λ-Abstraktion enthalten sein (Currying cf. Seite 87): (λx. (λy . × y x)) 4 5 � β (λy . × y 4) 5 � β × 5 4 � δ 20 Notation Stefan Klinger · DBIS Schreiben abkürzend λx y . e statt Informatik 2 · Sommer 2016 λx. λy . e . 100 3 · Der λ-Kalkül Beispiel Funktionen können problemlos als Argumente übergeben werden: Operationale Semantik des λ-Kalküls · 3.4 � β � β � δ (λf . f 3) (λx. + x 1) (λx. + x 1) 3 +31 4 Wichtig Bei β-Reduktion werden genau die in der Kopie des Funktionsrumpfes freien Vorkommen des formalen Parameters ersetzt: � � (λx. λx. + (− x 1) x 3) 9 Das unterstrichene Vorkommen von � x ist durch die innere λ-Abstraktion β (λx.+ (− x 1)) 9 3 gebunden und wird daher bei der � β + (− 9 1) 3 ersten β-Reduktion nicht ersetzt. �∗ δ 11 Stefan Klinger · DBIS Informatik 2 · Sommer 2016 101 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 α-Konversion Erinnerung Generell hängt der Wert eines Ausdrucks nur von seinen freien Variablen ab. —cf. Seite 98 Im Umkehrschluss heißt das: Die Bedeutung eines λ-Ausdrucks ändert sich nicht, wenn wir gebundene Variablen konsistent umbenennen, d.h. wenn wir alle durch das gleiche λ gebundenen Vorkommen durch den gleichen neuen Namen ersetzen: (λx. × x 2) � α (λy . × y 2) � Man sagt auch: Diese Ausdrücke sind gleich bis auf Umbenennen, oder gleich modulo α-Konversion. � Manchmal ist diese α-Konversion unerläßlich, um Namenskollisionen und damit fehlerhafte Reduktionen (sog. “name capture”) zu vermeiden. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 102 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 Name Capture Beispiel Betrachten wir den λ-Ausdruck � � λy . (λx y . + x y ) y 3 5 und zwei verschiedene Reihenfolgen bei der Auswertung: � β � β � β � δ � � λy . (λx y . + x y ) y 3 5 � zuerst äußeren Redex β (λx y . + x y ) 5 3 � (λy . + 5 y ) 3 β � +53 β 8 Frage � δ Was ist schief gegangen? Stefan Klinger · DBIS � � λy . (λx y . + x y ) y 3 5 zuerst inneren Redex � � λy . (λy . + y y ) 3 5 (λy . + y y ) 3 +33 6 Informatik 2 · Sommer 2016 — Falsch! 103 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 � λy . (λx y . + x y ) y 3 5 � � � β λy . (λy . + y y ) 3 5 � Lösung � � � Das zunächst durch das äußere λ gebundene y ist nun falsch durch das innere λ gebunden (captured). Umbenennung durch α-Konversion hilft hier: � λy . (λx y . + x y ) y 3 5 Ersetze λy durch λz � λy . (λx z. + x z) y 3 5 � � � β λy . (λz. + y z) 3 5 α � Stefan Klinger · DBIS � Ersetzen die durch das innere λ gebundenen y konsistent durch neue Variable z. � Das y wird jetzt von λz nicht mehr eingefangen. Informatik 2 · Sommer 2016 104 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 Noch ein Beispiel definiert : Unter dem Namen twice sei folgende Funktion twice = λf x. f (f x) Wir verfolgen jetzt die Reduktion des Ausdrucks twice twice mittels β-Reduktion. = � β � β dann: twice twice (λf x. f (f x)) twice = λx. twice (twice x) � β λx. twice (twice � �� x�) � �� ○ 1 ○ 2 � 1 und ○ 2. Es entstehen die Redexe ○ 2 beliebig, Wir wählen ○ Stefan Klinger · DBIS ○ 2 � �� � λx. twice (twice x) λx. twice ((λf x. f (f x)) x) λx. twice (λx. x (x x)) Falsch! Die x sind nun durch die innere λ-Abstraktion gebunden (captured). Umbenennung mittels α-Konversion hilft hier... Informatik 2 · Sommer 2016 105 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 ○ 2 Es ist nötig die Variable der inneren Bindung umzubenennen, bevor die Ersetzung stattfindet. � Obacht = � α � β � �� � λx. twice (twice x) λx. twice ((λf x. f (f x)) x) λx. twice ((λf y . f (f y )) x) λx. twice (λy . x (x y )) An dieser Stelle erkennt man auch, dass es sich bei den x in λx. twice ((λf x. f (f x)) x) um verschiedene Variablen handelt, die den gleichen Namen tragen. � Sie unterscheiden sich durch das λ welches sie bindet. � Jede Variable ist entweder frei oder durch genau ein λ gebunden. � α-Konversion einer Variablen kann dies sichtbar machen. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 106 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 Die Einsetzung ist so zentral, dass wir ihr eine eigene Notation spendieren: Definition e[x � m] sprich: “m für x in e”, oder “e mit x ersetzt durch m” Seien x, v Variablen; c Konstante; m, e, e1 , e2 beliebige λ-Ausdrücke. c[x � m] = c � v [x � m] = m v wenn v = x sonst (e1 e2 )[x � m] = e1 [x � m] e2 [x � m] λv . e wenn v = x λv . e[x � m] wenn v �= x, und (λv . e)[x � m] = v nicht frei in m ist (λz. e[v � z])[x � m] sonst, z neuer Variablenname (das ist α-Konversion) Stefan Klinger · DBIS Informatik 2 · Sommer 2016 107 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 � Vorsicht Einsetzen ist eine Operation der Meta-Ebene. � � Die Notation e[x � m] beschreibt eine syntaktische Veränderung, die wir am λ-Ausdruck e vornehmen. Diese Operation ist nicht Bestandteil eines λ-Ausdrucks! • Es ist eine Operation auf einem λ-Ausdruck. • Die Grammatik des λ-Kalküls (cf. Seite 94) kennt den Ersetzungsoperator ·[· � ·] überhaupt nicht. Notation Der Ersetzungsoperator ·[· � ·] bezieht sich immer auf den kürzesten voranstehenden gültigen λ-Ausdruck: a (a b)[a � x] = a (x b) �= x (x b) Stefan Klinger · DBIS Informatik 2 · Sommer 2016 108 3 · Der λ-Kalkül Operationale Semantik des λ-Kalküls · 3.4 Zusammenfassung Damit sind alle Regeln zum Umgang mit dem λ-Kalkül vorhanden: Definition Operationale Semantik des λ-Kalküls Seien x, y Variablen; m, e beliebige λ-Ausdrücke; ∗ primitive Operation. α-Konversion λx. e β-Reduktion (λx. e) m δ-Reduktion ∗e � λy . e[x � y ] wenn y nicht frei in e � �e wenn e in Normalform20 α � e[x � m] β δ Dieses kompakte formale System ist ausreichend, um als Zielsprache für alle funktionalen Programmiersprachen zu dienen. � Tatsächlich ist Haskell ein syntaktisch stark angereicherter λ-Kalkül. � Manche Sprachelemente von Haskell werden wir auf den λ-Kalkül zurückführen. 20 d.h. e enthält keinen Redex; � implementiert ∗ auf der Zielmaschine. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 109 3 · Der λ-Kalkül 3.5 Anmerkungen · 3.5 Anmerkungen Namen als Abkürzungen für Terme Betrachten wir nochmal die Definition von Seite 105: twice = λf x. f (f x) � Diese Zeile ist nicht im λ-Kalkül geschrieben, denn der kennt keine Zuweisung, kein =-Zeichen. � twice ist eine Metavariable, die uns als Abkürzung für den Term λf x. f (f x) dient. � Obacht: Wenn man twice verwendet, dann tut man so als wären Klammern drum herum: twice x ≡ (λf x. f (f x)) x �≡ λf x. f (f x) x twice x meint also die Anwendung des ganzen Ausdrucks twice auf den Ausdruck x, nicht die syntaktische Konkatenation der beiden. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 110 3 · Der λ-Kalkül Anmerkungen · 3.5 Äquivalenz � Wann sind λ-Ausdrücke gleich? Man hätte auch schreiben (und denken) können: twice = λharry foo. harry (harry foo) � Diese Erkenntnis wird rigoros angewandt: λ-Ausdrücke die bis auf α-Konversion gleich sind, werden semantisch nicht unterschieden! • De Bruijn indices sind eine Syntax für λ-Ausdrücke, welche keine α-Konversion benötigt. • Der SK -Kalkül verwendet gar keine Variablen, ist aber gleich mächtig wie der λ-Kalkül. � Etwas weiter gefasst ist die Äquivalenz: Definition Äquivalenz von λ-Ausdrücken Zwei λ-Ausdrücke e1 , e2 heißen äquivalent, gdw. sie zur gleichen Normalform reduziert werden können, d.h.: e 1 ≡ e2 ⇔ ∃m. e1 �∗ m ∧ e2 �∗ m wobei �∗ hier durchaus für unterschiedlich viele Schritte stehen kann. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 111 3 · Der λ-Kalkül 3.6 � Exkurs: Variablenbindung anderswo · 3.6 Exkurs: Variablenbindung anderswo Das Konzept der Variablenbindung begegnet uns auch in der Mathematik und in anderen Programmiersprachen. ∀x. 2 · x > t n � i=1 1 2 3 2·i −1 for (int i = 0; i < k; i++) { print(i); } Frage Was sind hier die freien Variablen? Welche sind gebunden? Wo findet die Bindung statt? Stefan Klinger · DBIS Informatik 2 · Sommer 2016 112 3 · Der λ-Kalkül Exkurs: Variablenbindung anderswo · 3.6 α-Konversion? � Auch hier ist der gewählte Name eigentlich nicht relevant (cf. Seite 102). ∀x. 2 · x > t ≡ 2·i −1 ≡ n � i=1 1 2 3 for (int i = 0; i < k; i++) { print(i); } Stefan Klinger · DBIS ∀y . 2 · y > t n � j=1 1 ≡ 2 3 2·j −1 for (int j = 0; j < k; j++) { print(j); } Informatik 2 · Sommer 2016 113 3 · Der λ-Kalkül Exkurs: Variablenbindung anderswo · 3.6 Scoping � Bei vielen Programmiersprachen können wir die Verwendung verschiedener Variablen mit dem gleichen Namen beobachten: 1 2 3 4 5 int i = 42; for (int i = 0; i < 10; i++) { print(i); // gibt 0–9 aus } print(i); // gibt 42 aus Die innere Variable i überdeckt die äußere. Innerhalb der Schleife kann auf die 42 nicht zugegriffen werden. � Der Bereich in dem eine Variable syntaktisch verwendet werden kann, heißt Sichtbarkeitsbereich, oder Scope. � Ob, und wo eine Variable sichtbar ist, hängt von der jeweiligen Programmiersprache ab. • Obiger Code wäre in C erlaubt, hingegen • verbietet Java diese Überdeckung (aka. Shadowing). ⇒ Scoping-Regeln der Sprache lesen! Stefan Klinger · DBIS Informatik 2 · Sommer 2016 114 3 · Der λ-Kalkül � Exkurs: Variablenbindung anderswo · 3.6 Was in der Programmierung als zumindest fragwürdiger Stil gesehen werden kann, ist in der Mathematik unüblich, wenn nicht verpönt: � � 10 i � � 5· oder 3·i ∀x. ∃y . Px,y ∧ ∀x. Qx,y i=1 i=1 (Manche sagen: Das macht keinen Sinn! — Kann aber beim Einsetzen passieren) � Üblich ist aber die Wiederverwendung der Zählvariablen in nebeneinander stehenden Termen: n � i=1 (2 · i − 1) + n � i=0 5·i Tatsächlich sind das verschiedene Variablen die beide i heißen. Stefan Klinger · DBIS Informatik 2 · Sommer 2016 115