Der λ-kalkül. Frank Huch. Sommersemester 2015



Ähnliche Dokumente
Einfache Ausdrücke Datentypen Rekursive funktionale Sprache Franz Wotawa Institut für Softwaretechnologie

Primzahlen und RSA-Verschlüsselung

Lineargleichungssysteme: Additions-/ Subtraktionsverfahren

Informationsblatt Induktionsbeweis

7 Rechnen mit Polynomen

Grundlagen der Theoretischen Informatik, SoSe 2008

Skript und Aufgabensammlung Terme und Gleichungen Mathefritz Verlag Jörg Christmann Nur zum Privaten Gebrauch! Alle Rechte vorbehalten!

13. Lineare DGL höherer Ordnung. Eine DGL heißt von n-ter Ordnung, wenn Ableitungen y, y, y,... bis zur n-ten Ableitung y (n) darin vorkommen.

Theoretische Grundlagen des Software Engineering

Die Gleichung A x = a hat für A 0 die eindeutig bestimmte Lösung. Für A=0 und a 0 existiert keine Lösung.

Terme stehen für Namen von Objekten des Diskursbereichs (Subjekte, Objekte des natürlichsprachlichen Satzes)

Rundung und Casting von Zahlen

6.2 Scan-Konvertierung (Scan Conversion)

Beweisbar sichere Verschlüsselung

Approximation durch Taylorpolynome

50. Mathematik-Olympiade 2. Stufe (Regionalrunde) Klasse Lösung 10 Punkte

Musterlösungen zur Linearen Algebra II Blatt 5

Einführung in. Logische Schaltungen

Die reellen Lösungen der kubischen Gleichung

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Erwin Grüner

1 topologisches Sortieren

Grundlagen der höheren Mathematik Einige Hinweise zum Lösen von Gleichungen

Semantik von Formeln und Sequenzen

Grundbegriffe der Informatik

Einführung in die Programmierung

Repetitionsaufgaben Wurzelgleichungen

Formale Systeme, WS 2012/2013 Lösungen zu Übungsblatt 4

Würfelt man dabei je genau 10 - mal eine 1, 2, 3, 4, 5 und 6, so beträgt die Anzahl. der verschiedenen Reihenfolgen, in denen man dies tun kann, 60!.

Einführung in das Programmieren Prolog Sommersemester Teil 2: Arithmetik. Version 1.0

Professionelle Seminare im Bereich MS-Office

Lineare Gleichungssysteme

Java Kurs für Anfänger Einheit 5 Methoden

4. AUSSAGENLOGIK: SYNTAX. Der Unterschied zwischen Objektsprache und Metasprache lässt sich folgendermaßen charakterisieren:

Übung Theoretische Grundlagen

Mathematischer Vorbereitungskurs für Ökonomen

2.1 Präsentieren wozu eigentlich?

Stackelberg Scheduling Strategien

Grundbegriffe der Informatik

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

1 Mathematische Grundlagen

Logische Folgerung. Definition 2.11

Wie Sie mit Mastern arbeiten

2. Vorlesung. Slide 40

Mathematik: Mag. Schmid Wolfgang Arbeitsblatt 3 1. Semester ARBEITSBLATT 3 RECHNEN MIT GANZEN ZAHLEN

Programmiersprachen und Übersetzer

1. Man schreibe die folgenden Aussagen jeweils in einen normalen Satz um. Zum Beispiel kann man die Aussage:

Software- und Druckerzuweisung Selbstlernmaterialien

der Eingabe! Haben Sie das Ergebnis? Auf diesen schwarzen Punkt kommen wir noch zu sprechen.

Lineare Gleichungssysteme

Zwischenablage (Bilder, Texte,...)

Güte von Tests. die Wahrscheinlichkeit für den Fehler 2. Art bei der Testentscheidung, nämlich. falsch ist. Darauf haben wir bereits im Kapitel über

Um Ihre Ziele durchzusetzen! Um Beziehungen zu knüpfen und zu pflegen! Um in Begegnungen mit anderen Ihre Selbstachtung zu wahren!

Mediator 9 - Lernprogramm

Inhalt. 1 Einleitung AUTOMATISCHE DATENSICHERUNG AUF EINEN CLOUDSPEICHER

8.2 Thermodynamische Gleichgewichte, insbesondere Gleichgewichte in Mehrkomponentensystemen Mechanisches und thermisches Gleichgewicht

Objektorientierte Programmierung

Zeichen bei Zahlen entschlüsseln

Arbeitshilfe "Tipps für Gespräche mit Vorgesetzten und KollegInnen" Was gilt für mich?

Konzepte der Informatik

Funktionale Programmierung

Mehr Geld verdienen! Lesen Sie... Peter von Karst. Ihre Leseprobe. der schlüssel zum leben. So gehen Sie konkret vor!

Plotten von Linien ( nach Jack Bresenham, 1962 )

Das Briefträgerproblem

ONLINE-AKADEMIE. "Diplomierter NLP Anwender für Schule und Unterricht" Ziele

Einführung in die Algebra

Prozentrechnung. Wir können nun eine Formel für die Berechnung des Prozentwertes aufstellen:

Gutes Leben was ist das?

Gleichungen Lösen. Ein graphischer Blick auf Gleichungen

Lineare Funktionen. 1 Proportionale Funktionen Definition Eigenschaften Steigungsdreieck 3

Fachschaft Mathematik und Informatik (FIM) LA I VORKURS. Herbstsemester gehalten von Harald Baum

Lernerfolge sichern - Ein wichtiger Beitrag zu mehr Motivation

IINFO Storyboard

Alle Schlüssel-Karten (blaue Rückseite) werden den Schlüssel-Farben nach sortiert und in vier getrennte Stapel mit der Bildseite nach oben gelegt.

Grundlagen der Programmierung (Vorlesung 14)

Festigkeit von FDM-3D-Druckteilen

Autoformat während der Eingabe

Kapitel 4 Die Datenbank Kuchenbestellung Seite 1

Korrelation (II) Korrelation und Kausalität

Gruppenrichtlinien und Softwareverteilung

4 Aufzählungen und Listen erstellen

Die Komplexitätsklassen P und NP

Zusammenfassung. Satz. 1 Seien F, G Boolesche Ausdrücke (in den Variablen x 1,..., x n ) 2 Seien f : B n B, g : B n B ihre Booleschen Funktionen

Lineare Gleichungssysteme

C++ Tutorial: Timer 1

SCHRITT 1: Öffnen des Bildes und Auswahl der Option»Drucken«im Menü»Datei«...2. SCHRITT 2: Angeben des Papierformat im Dialog»Drucklayout«...

Gemeinsamer Bibliotheksverbund: Übertragung von Datenexporten für den Verbundkatalog Öffentlicher Bibliotheken

13 OOP MIT DELPHI. Records und Klassen Ein Vergleich

1 Vom Problem zum Programm

Internationales Altkatholisches Laienforum

Lösungen zu Kapitel 7

Handbuch ECDL 2003 Modul 2: Computermanagement und Dateiverwaltung Der Task-Manager

Deterministische Turing-Maschinen (DTM) F3 03/04 p.46/395

Modellbildungssysteme: Pädagogische und didaktische Ziele

Abituraufgabe zur Stochastik, Hessen 2009, Grundkurs (TR)

Eigenwerte und Eigenvektoren von Matrizen

Formeln. Signatur. aussagenlogische Formeln: Aussagenlogische Signatur

AGROPLUS Buchhaltung. Daten-Server und Sicherheitskopie. Version vom b

Frohe Weihnachten und ein gutes neues Jahr!

WinWerk. Prozess 6a Rabatt gemäss Vorjahresverbrauch. KMU Ratgeber AG. Inhaltsverzeichnis. Im Ifang Effretikon

Transkript:

Der λ-kalkül Frank Huch Sommersemester 2015 In diesem Skript werden die Grundlagen der Funktionalen Programmierung, insbesondere der λ-kalkül eingeführt. Der hier präsentierte Stoff stellt einen teil der Vorlesung Funktionale Programmierung im Sommersemester 2015 dar. Weitere, praktische Inhalte werden in weiteren Dokumenten zur Verfügung gestellt. Inhaltsverzeichnis 1 Theoretische Grundlagen: Der Lambda-Kalkül 1 1.1 Syntax des Lambda-Kalküls.......................... 1 1.2 Substitution................................... 1 1.3 Reduktionsregeln................................ 2 1.4 Datenobjekte im reinen Lambda-Kalkül................... 5 1.5 Mächtigkeit des Kalküls............................ 6 1.6 Angereicherter Lambda-Kalkül........................ 7

1 Theoretische Grundlagen: Der λ-kalkül Grundlage funktionaler Sprachen ist der λ-kalkül, der 1941 von Church entwickelt wurde. Motivation war, eine Grundlage der Mathematik und mathematischen Logik zu schaffen; in diesem Zusammenhang entstand der Begriff der Berechenbarkeit. Es zeigte sich eine Äquivalenz zur Turing-Maschine, aus der die Church sche These hervorging. Wichtige Aspekte: Funktionen als Objekte Gebundene und freie Variablen Auswertungsstrategien 1.1 Syntax des λ-kalküls Var sei eine abzählbare Menge von Variablen, Exp die Menge der Ausdrücke des reinen λ-kalküls, die definiert werden durch (e Exp): e ::= v (mit v Var) Variable (e e ) (mit e, e Exp) Applikation λv.e (mit v Var, e Exp) Abstraktion Wir verwenden folgende Konvention zur Klammervermeidung: Applikation ist linksassoziativ, d.h. wir schreiben xyz statt ((xy)z) Wirkungsbereich von λ reicht so weit wie möglich, d.h. λx.xy steht für λx.(xy) und nicht für ((λx.x)y) Listen von Parametern: λxy.e statt λx.λy.e Beachte: Es gibt keine Konstanten (vordefinierte Funktionen) oder If-Then-Else-Strukturen, diese sind später im reinen λ-kalkül definierbar. Der reine λ-kalkül ist damit minimal, aber universell, wie wir noch sehen werden. 1.2 Substitution Die Semantik des reinen λ-kalküls erfolgt wie in funktionalen Sprachen üblich: λx.e entspricht den anonymen Funktion \x -> e. Somit ergibt sich in der Semantik: (λx.x)z z, wobei im Rumpf (x) der Funktion die Variable x durch z substituiert wurde. Ganz so einfach läßt sich diese Regel aber nicht realisieren, wie das folgende Beispiel zeigt. Durch die Anwendung der Regel können Namenskonflikte auftreten: (λf.λx.fx)x λx.xx Konflikt (λf.λx.fx)x λy.xy kein Konflikt 1

Ein zunächst freie Variable kann durch Anwendung der Reduktionsregel in den Bindungsbereich einer anderen λ-abstraktion kommen und so fälschlicher Weise gebunden werden. Um dies formal fassen zu können, ist es zunächst sinnvoll freie bzw. gebundene Variablen zu definieren: free(v) = {v} bound(v) = free((e e )) = free(e) free(e ) bound((e e )) = bound(e) bound(e ) free(λv.e) = free(e) \ {v} bound(λv.e) = bound(e) {v} Ein Ausdruck e heißt geschlossen (Kombinator), wenn free(e) = ist. Wichtig: Bei der Applikation dürfen wir Variablen nur Erseten, wenn freie Variablen im aktuellen Parameter nicht gebunden werden. Präzisiert wird dies durch die Definition der Substitution: Seien e, f Exp, v Var. Dann ist die Substitution e[v/f] ( ersetze v durch f in e ) definiert durch: v[v/f] = f x[v/f] = x für x v (e e )[v/f] = (e[v/f] e [v/f]) λv.e[v/f] = λv.e λx.e[v/f] = λx.(e[v/f]) für x v, x / free(f) λx.e[v/f] = λy.(e[x/y][v/f]) für x v, x free(f), y / free(e) free(f) Die letzte Regel sorgt insbesondere dafür, dass keine freien Variablen durch ein anderes λ gebunden werden. Stattdessen, benennen wir die gebundene Variable um und machen die Substitution dennoch möglich. Beachte, dass diese Definition nicht wirklich eine Funktion darstellt, vielmehr eine Relation, da wir nicht vorschreiben, in welche Variable, wir eine gebundene Variable bei einem Namenskonflikt umbenennen. Kommt eine zu substituierende Variable in einem Ausdruck nicht vor, bleibt der Ausdruck aber unverändert: Falls v / free(e), so ist e[v/f] = e. Mit Hilfe der Substitution können wir nun auch das Ausrechnen der Applikation als Reduktionsrelation formalisieren. 1.3 Reduktionsregeln Definiere die Beta-Reduktion (β-reduktion) durch folgende Relation: β Exp Exp mit (λv.e)f β e[v/f] Beispiel: Nun gilt (λf.λx.fx)x β λy.xy 2

aber auch Somit ist β nicht konfluent 1! (λf.λx.fx)x β λz.xz Aber: Die Namen der formalen Parameter spielen keine Rolle bezüglich der Bedeutung einer Funktion, d.h. die syntaktisch verschiedenen Terme λx.x und λy.y sind semantisch gleich (die Identitätsfunktion). Um dennoch ein konfluentes Ersetzungssystem zu definieren, fürgt man die Umbenennung gebundeneer Variablen als zusätzliche Reduktionsrelation ein: Die Alpha-Reduktion (α-reduktion) ist eine Relation Beispiele: α Exp Exp mit λx.e α λy.(e[x/y]) (falls y / free(e)) λx.x α λy.y, λy.xy α λz.xz, λy.xy α λx.xx Somit gilt e α e ( e und e sind α-äquivalent ) genau dann, wenn sich e und e nur durch Namen der Parameter unterscheiden. Konvention im Folgenden: Betrachte α-äquivalente Ausdrücke als gleich, d.h. rechne auf α-äquivalenzklassen statt auf Ausdrücken. Die β-reduktion kann bisher Ausdrücke ausrechnen, allerdings nur außen deswegen setzen wir die β-reduktion auf beliebige Stellen in Ausdrücken fort (analog für α- Reduktion): Falls e β e so auch ef β e f und fe β fe und λx.e β λx.e Die letzte Fortsetzung der β-reduktion im Rumpf einer λ-abstraktion lässt man, wenn es um Berechnungen geht, häufig weg. Für Konfluenzbetrachtungen und eine Theorie zur Äquivalenz von λ-ausdrücken ist sie aber dennoch wichtig. Eigenschaften der β-reduktion: Die Relation β ist konfluent. Jeder Ausdruck besitzt höchstens eine Normalform bezüglich β (bis auf α- Äquivalenzklassen). Es gibt allerdings auch Ausdrücke ohne Normalform, dies ist wichtig für die Äquivalenz zu Turing-Maschinen! Ein BEispiel stellt der folgende Ausdruck dar: (λx.xx)(λx.xx) β (λx.xx)(λx.xx) 1 Eine Relation ist konfluent, falls für alle u, v, w mit u v und u w auch ein z existiert mit v z und w z. 3

Die darin enthaltene Selbstapplikation (λx.xx) würde in Programmiersprachen wie Haskell zu einem Typfehler führen. Frage: Wie findet man die Normalform, falls sie existiert? Ein β-redex sei ein Teilausdruck der Form (λx.e)f. Dann ist eine Reduktionsstrategie eine Funktion von der Menge der Ausdrücke in die Menge der Redexe: Sie gibt an, welcher Redex als nächster reduziert wird. Wichtige Reduktionsstrategien sind: Outermost-Strategie (LO, nicht strikt, normal-order-reduction): Wähle äußersten Redex Innermost-Strategie (LI, strikt, applicative-order-reduction): Wähle innersten Redex (λx.z)((λx.xx)(λx.xx)) (λx.z)((λx.xx)(λx.xx)) LI (λx.z)((λx.xx)(λx.xx)) LO z Da eigentlich alle Funktionensabstraktionen einstellig sind, können die Redexe nicht nach links/rechts unterschieden werden. Dennoch verwendet man den Begriff der LI/LO- Strategie. Satz: Ist e eine Normalform von e, d.h. e β e β e, dann existiert eine LO-Ableitung von e nach e. Damit berechnet LO jede Normalform, LI manche nicht! LO ist somit berechnungsstärker als LI. Ein wichtiger Aspekt (für Optimierungen, Transformation, Verifikation) ist die Äquivalenz von Ausdrücken 2. Intuitiv sind e und e genau dann äquivalent, wenn e überall für e eingesetzt werden kann, ohne das Ergebnis zu verändern. Beispiele: λx.x ist äquivalent zu λy.y λf.λx.((λy.y)f)((λz.z)x) ist äquivalent zu λf.λx.f x Wünschenswert wäre es, die Äquivalenz durch syntaktische Transformationen nachweisen zu können. α- und β-äquivalenz sind dafür aber nicht ausreichend, betrachte folgendes Beispiel (in Haskell-Notation): (+1) ist äquivalent zu λx.(+) 1 x, denn bei der Anwendung auf ein Argument z gilt: (+1) z (+) 1 z und (λx.(+) 1 x)z β (+) 1 z Doch beide Terme sind weder α- noch β-äquivalent. Daher definieren wir noch die Eta-Reduktion (η-reduktion) als Relation: η Exp Exp mit λx.ex η e (falls x / free(e)) Weitere Sichtweisen der η-reduktion: 2 Wobei wir im Folgenden nur Äquivalenz auf terminierenden Ausdrücken betrachten, sonst ist nicht klar, was man unter Ergebnis versteht. 4

Die η-reduktion ist eine vorweggenommene β-reduktion: (λx.ex)f β ef, falls x / free(e) ist. Extensionalität: Funktionen sind äquivalent, falls sie gleiche Funktionsgraphen (Menge der Argument-Wert-Paare) haben. Beachte: Falls fx β gx3 gilt, dann ist f β,η g (mit x free(f) free(g)), da gilt: f η λx.fx β λx.gx η g Es gibt auch noch eine weitere Reduktion, die Delta-Reduktion (δ-reduktion), die das Rechnen mit vordefinierten Funktionen ermöglicht, wie zum Beispiel (+) 1 2 δ 3. Diese vordefinierten Funktionen sind nicht notwendig, da sie im reinen λ-kalkül darstellbar sind. Zusammenfassung der Reduktionen im λ-kalkül: α-reduktion: Umbenennung von Parametern β-reduktion: Funktionsanwendung η-reduktion: Elimination redundanter λ-abstraktionen δ-reduktion: Rechnen mit vordefinierten Funktionen Um zu zeigen, dass wir keine fordefinierten Werte zum Rechnen im λ-kalkül benötigen, schauen wir uns eine gängige Codierung von Basisdatentypen an. 1.4 Datenobjekte im reinen λ-kalkül Datentypen sind Objekte mit Operationen darauf, Idee hier: Stelle die Objekte durch geschlossene λ-ausdrücke dar und definiere passende Operationen. Betrachte den Datentyp der Wahrheitswerte: Objekte sind True und False, die wichtigste Operation ist die If-Then-Else-Funktion: { e1, falls b = True if_then_else(b, e 1, e 2 ) = e 2, falls b = False Daher sind Wahrheitswerte nur Projektionsfunktionen: True λx.λy.x erstes Argument nehmen False λx.λy.y zweites Argument nehmen Nun lässt sich eine If-Then-Else-Funktion definieren durch Cond λb.λx.λy.bxy 3 Unter u β v verstehen wir: es gibt ein w, so dass u β w und v β w. 5

Beispiel: Cond True e 1 e 2 (λbxy.bxy)(λxy.x)e 1 e 2 3 β (λxy.xe 1e 2 ) 2 β e 1 Cond False e 1 e 2 (λbxy.bxy)(λxy.y)e 1 e 2 3 β (λxy.ye 1e 2 ) 2 β e 2 Nun kodieren wir die natürlichen Zahlen: Betrachte die Church-Numerals, die jede Zahl n N als Funktional darstellen, das eine Funktion f genau n mal auf ein Argument anwendet: Nun definieren wir Operationen: 0 λf.λx.x 1 λf.λx.fx 2 λf.λx.f(fx) 3 λf.λx.f(f(fx)) n λf.λx.f n x Die wichtigste Operation ist die Nachfolgefunktion succ: Beispiel: Nachfolger von Eins: succ λn.λf.λx.nf(fx) succ 1 (λn.λf.λx.nf(f x))(λf.λx.f x) β λf.λx.(λf.λx.fx)f(fx) β λf.λx.(λx.fx)(fx) β λf.λx.f(fx) 2 Test auf Null: is_null λn.n(λx.false)true Beispiel: Teste Null auf Null: 1.5 Mächtigkeit des Kalküls is_null 0 = (λn.n(λx.false)true)(λf.λx.x) β (λf.λx.x)(λx.false)true β (λx.x)true β True Ist der reine λ-kalkül also berechnungsuniversell? Ja, denn auch Rekursion ist darstellbar, beachte den Fixpunktsatz: Satz: Zu jedem F Exp gibt es einen Ausdruck X mit F X β X. 6

Beweis: Wähle zum Beispiel X = Y F mit Fixpunktkombinator Y : Y λf.(λx.f(xx))(λx.f(xx)) Es bleibt zu zeigen, dass Y F β F (Y F ) gilt, siehe Übung. Der reine λ-kalkül ist minimal, aber berechnungsuniversell er besitzt aber eher theoretische Relevanz (Barendregt 1984). Dies wollen wir hier nicht formal zeigen. Die vorgestellten Datenrepräsentationen sollten aber verdeutlichen, dass eine universelle Programmierung möglich ist. Auch wenn Selbstapplikation in Haskell eigentlich auf Grund des Typsystems nicht möglich ist, können wir den Y-Kombinator mit Hilfe einer Recorddefinition programmieren: newtype Fix a = Fix { app : : Fix a > a } f i x = \ f > (\ x > f ( app x x ) ) ( Fix (\ x > f ( app x x ) ) ) Da die Definition der Subtraktion bzw. des Dekrementierens für Churchzahlen etwas komplizierter ist, verwenden wir den definierten Fixpunktkombinator zur Definition der Fakultätsfunktion auf Haskell-Zahlen: f a c = f i x (\ f > \ x > i f x==0 then 1 else x f ( x 1)) Wir definieren ein Funktional für die Fakultätsfunktionen, dessen kleinesten Fixpunkt wir mittels des Y-Kombinators an jeder beliebigen Stelle berechnen können. 1.6 Angereicherter λ-kalkül Für funktionale Programmiung ist aber eher ein angereicherter λ-kalkül relevant, bei dem Konstanten (vordefinierte Objekte und Funktionen), let, if-then-else und ein Fixpunktkombinator hinzugenommen werden. Die Syntax des angereicherten λ-kalküls: e ::= v Variable k Konstantensymbol (e e ) Applikation let v = e in e lokale Definitionen if e then e 1 else e 2 Alternative (manchmal auch case) µv.e Fixpunktkombinator Als operationale Semantik benutzen wir zusätzlich zur α-, β- und η-reduktion noch folgende Regeln: δ-reduktion für Konstanten, z.b. (+) 21 21 δ 42 let v = e in e e [v/e] 7

if True then e 1 else e 2 e 1 if False then e 1 else e 2 e 2 µv.e e[v/µv.e] Beispiel: Fakultätsfunktion: fac µf.λx. if ((==) x 0) then 1 else (( ) x (f (( ) x 1))) Der angereicherte λ-kalkül bildet die Basis der Implementierung funktionaler Sprachen (Peyton, Jones 1987): 1. Übersetze Programme in diesen Kalkül (Core-Haskell im ghc): Pattern-Matching wird in if-then-else (oder case) übersetzt, f x 1... x n = e wird übersetzt zu f = λx 1... x n.e, für rekursive Funktionen führt man Fixpunktkombinatoren ein, ein Programm entspricht einer Folge von let-deklarationen und einem auszuwertenden Ausdruck. 2. Implementiere den Kalkül durch eine spezielle abstrakte Maschine, z.b. durch die SECD-Maschine von Landin im ghc oder durch eine Graphreduktionsmaschine. Weitere Anwendungen des erweiterten λ-kalküls sind die denotationelle Semantik und die Typisierung (getypte λ-kalküle). 8