Einführung in die funktionale Programmierung

Ähnliche Dokumente
Einführung in die funktionale Programmierung

Einführung in Haskell

Einführung in Haskell

Übersicht. Nebenläufige Programmierung: Praxis und Semantik. Semantische Modelle nebenläufiger Programmiersprachen. Einleitung

LR: Syntax. Semantik und Analyse von Funktionalen Programmen (SAFP): LR: Reduktions-Regeln. LR: Reduktions-Regeln

Semantik und Analyse von Funktionalen Programmen (SAFP):

Einführung in die funktionale Programmierung

Semantik und Analyse von Funktionalen Programmen (SAFP):

LR: Syntax. Semantik und Analyse von Funktionalen Programmen (SAFP): LR: Reduktions-Regeln. LR: Reduktions-Regeln

Einführung in Haskell

Grundlagen der Programmierung 2. Operationale Semantik

Einführung in die funktionale Programmierung

3 Exkurs: Der λ-kalkül

Haskell, Typen, und Objektorientierung

Grundlagen der Programmierung 3 A

Grundlagen der Programmierung 3 A

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Überladung und Konversion in Haskell. Typisierung in Haskell

Einführung in die Funktionale Programmierung:

1 Einleitung. 2 Normalordnungsreduktion. 3 Anwendungsordnung. 4 Verzögerte Auswertung. 5 Programmieren mit let in Haskell.

Theoretische Informatik II

Operationale Semantik: Haskell

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell

Der untypisierte Lambda-Kalkül als Programmiersprache

Der einfach getypter Lambda-Kalkül

Theoretische Informatik II

Funktionale Programmierung ALP I. λ Kalkül WS 2012/2013. Prof. Dr. Margarita Esponda. Prof. Dr. Margarita Esponda

Die Definition eines Typen kann rekursiv sein, d.h. Typ-Konstruktoren dürfen Elemente des zu definierenden Typ erhalten.

Workshop Einführung in die Sprache Haskell

Übersicht. Einführung in die Funktionale Programmierung: Übersicht: Expression und Typen. Ziele des Kapitels

Fortgeschrittene Funktionale Programmierung

Übersicht. Einführung in die Funktionale Programmierung: Ziele des Kapitels. Typisierung Prof Dr. Manfred Schmidt-Schauß WS 2012/13

Funktionale Programmierung ALP I. λ Kalkül. Teil 2 WS 2012/2013. Prof. Dr. Margarita Esponda. Prof. Dr. Margarita Esponda

Einführung in Funktionale Programmierung Typisierung

Grundlagen der Programmierung 2 (2.B)

Grundlagen der Programmierung 2 (2.A)

Funktionale Programmierung Einführung

Fortgeschrittene Funktionale Programmierung

Kontextuelle Gleichheit, Korrektheit, Programmtransformationen, Auswertungsänderung

Listen und Listenfunktionen. Grundlagen der Programmierung 2 A (Listen) Listen und Listenfunktionen. Listen? Haskell: Listen

Lösungen zum Aufgabenblatt 10 Logik und modelltheoretische Semantik

Interpreter (Hilfsfunktionen)

Grundlagen der Programmierung 2 (1.C)

Haskell, Typen und Typberechnung

Grundlagen der Programmierung 2 (1.A)

Einführung in das λ-kalkül

Adressen. Praktikum Funktionale Programmierung Organisation und Überblick. Termine WWW

Praktikum Funktionale Programmierung Organisation und Überblick

Haskell, Typen und Typberechnung

1 Geschichte. 2 Syntax und Konzepte. Lamdba-Kalkül

Grundlagen der Programmierung 2 A (Listen)

Der untypisierte Lambda-Kalkül

Semantics of a Call-by-Need Lambda Calculus with McCarthy s amb for Program Equivalence

Haskell, Typen und Typberechnung

Praktikum Funktionale Programmierung Teil 2: Typecheck und Transformation

Reduktionssysteme und Termersetzungssysteme

1. Typen 1.1 Typsicherheit 1.2 Typprüfung

Typen und Typcheck. Kapitel Typsysteme, Typüberprüfung

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Automatische Prüfung und Berechnung von Überlappungen zum Vollständigkeitsnachweis von Diagrammen in Programmiersprachen höherer Ordnung

Berechnungsschemata: Funktion als Parameter abstrahiert Operation im Schema, wird bei Aufruf des Schemas konkretisiert

Einführung in die Funktionale Programmierung

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen:

Funktionale Programmierung - Grundlagen -

Concurrent Haskell with Futures. Vorlesung SAFP, WS 2017/18

Funktionen und sprachliche Bedeutungen

Der untypisierte Lambda-Kalkül

Haskell. Grundlagen der Programmierung 2. Grundlagen der Programmierung 2: Geplanter Inhalt der ersten Hälfte. Prof. Dr. Manfred Schmidt-Schauß

Grundlagen der Programmierung 2 (1.A)

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

Grundlegende Datentypen

Abstrakte Maschinen und Kode-Erzeugung für Haskell

Inferenzmethoden. Einheit 18. Logik höherer Stufe

Semantics of a Call-by-Need Lambda Calculus with McCarthy s amb for Program Equivalence

Funktionale Programmierung. Das Funktionale Quiz. Das Funktionale Quiz. Das Funktionale Quiz

Grundlegende Datentypen

Grundlagen der Programmierung 2 (1.A)

Grundlagen der Programmierung 2 (1.B)

1 Vollständige partielle Ordnungen, stetige Funktionen

Inhaltsverzeichnis. 1 Polynomordungen [9 Punkte] 2. 2 System F [9 Punkte] 3. 3 Strukturelle Induktion und Folds [9 Punkte] 4

Beschreibung von Werten: Beschreibung von Werten: (2) Begriffsklärung: (Ausdruck, expression) (2) Begriffsklärung: (Ausdruck, expression)

Haskell. Grundlagen der Programmierung 2. Grundlagen der Programmierung 2 (1.A) Bücher, Literatur, URLs. Haskell. Einführung

Grundlagen der Programmierung 2 (1.B)

Programmierung und Modellierung

WS 2012/2013. Robert Giegerich. 21. November 2012

Kapitel 5: λ-kalkül und Laziness

Vortrag. Vortrag im Rahmen der Master-Vorlesung Semantik von Programmiersprachen an der FH München, Fachbereich Informatik

Funktionale Programmierung

Lambda-Kalkül. Philipp Meyer. 28. April 2009

Grundlagen der Programmierung 2

Funktionale Programmierung Grundlegende Datentypen

Logik und Künstliche Intelligenz

Transkript:

Einführung in die funktionale Programmierung Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 28. Oktober 2008

Einführung in Haskell: Syntax, Reduktionen, Kernsprachen Haskell, eine nicht-strikte funktionale Programmiersprache mit polymorphem Typsystem. Ziel dieses Kapitels ist: Darstellung der syntaktischen Grundlagen, Unterscheidung zwischen Kernbestandteilen der Programmiersprache und zusätzlichen Features, Progammierverständnis in Haskell, operationale Semantik: Auswertungen Einführung in die funktionale Programmierung; Folien Kap2-1 - 1 -

Die Kernsprache KFPT Die Kernsprache folgt der Lambda-Schreibweise im Lambda-Kalkül, der von Alonzo Church entwickelt wurde. Der Lambda-Kalkül ist Teil der betrachteten Kernsprache und auch von Haskell. Einführung der Syntax und Reduktionsregeln Einführung in die funktionale Programmierung; Folien Kap2-1 - 2 -

Syntax von KFPT Es gibt Konstantensymbole, die jeweils eine feste Stelligkeit haben. Diese nennen wir auch Konstruktoren. Konstruktoren mit Stelligkeit sind anzugeben (wir erfinden keine KFPT-Syntax dafür) Es gibt Typen Jeder Konstruktor gehört zu genau einem Typ. z.b. seien die Typen Bool und List; zu Bool gehören True und False, zu List gehören Cons und Nil. Es gibt pro Typ ein case-konstrukt: case T ypname. Einführung in die funktionale Programmierung; Folien Kap2-1 - 3 -

Syntax von KFPT Kontextfreie Grammatik für KFPT Exp ::= V (Variable) (\V -> Exp) wobei V eine Variable ist. (Exp 1 Exp 2 ) (c Exp 1... Exp n ) wobei c Konstruktor und n = ar(c) (case Typ Exp of {P at 1 -> Exp 1 ;... ; P at n -> Exp n }) Hierbei ist P at i Pattern zum Konstruktor i, Es kommen genau die Konstruktoren zu Typname vor P at i ->Exp i heißt auch case-alternative. Pat ::= (c V 1... V ar(c) ) Die Variablen V i müssen alle verschieden sein. Einführung in die funktionale Programmierung; Folien Kap2-1 - 4 -

Syntax von KFPT (c V 1... V ar(c) ) sind einfache Pattern bzw. Muster. λx.s im Lambda-Ausdrücke entspricht \x -> s in KFPT Zum Beispiel: λx.1 ist die Funktion, die konstant 1 liefert. Einführung in die funktionale Programmierung; Folien Kap2-1 - 5 -

Beispiele in KFPT Die Funktion, die leere Listen erkennt: \xs -> (case_list xs of {Nil -> True; Cons y ys -> False}) In Haskell: kein Typ-Index am case, sondern automatische Typerkennung Einführung in die funktionale Programmierung; Folien Kap2-1 - 6 -

Ausdrücke in KFPT (Haskell) \x -> s sind Abstraktionen oder Funktionsausdrücke. (s t) sind Anwendungen (Applikationen). (c t 1... t ar(c) ) sind Konstruktor-Anwendungen. (case T e of Alts) sind case-ausdrücke (Fallunterscheidungen). Einführung in die funktionale Programmierung; Folien Kap2-1 - 7 -

Beispiele und Kodierungen \x -> x ist die Identitätsfunktion. if A then B else C ist darstellbar durch: (case Bool A of {True -> B; False -> C}) Einführung in die funktionale Programmierung; Folien Kap2-1 - 8 -

Beispiele und Kodierungen Sei Paar zweistelliger Konstruktor. (Paar True 1) ist ein Objekt zu Paar. Die Selektoren zu Paar sind definierbar: \x -> (case_paar x of (Paar y1 y2) -> y1) \x -> (case_paar x of (Paar y1 y2) -> y2) Tupel sind vordefiniert in Haskell: Schreibweise ist (x, y, z). Einführung in die funktionale Programmierung; Folien Kap2-1 - 9 -

Programm zu Paaren Hat das Paar p als erstes Element ein False? wird implementiert durch: (case_paar p of {Paar x y -> (case_bool x of {True -> False; False -> True})}) Einführung in die funktionale Programmierung; Folien Kap2-1 - 10 -

Listen Konstruktoren: Cons mit Stelligkeit 2 Nil mit Stelligkeit 0 Die Liste [True, False] ist darstellbar in KFPT als Cons True (Cons False Nil) Einführung in die funktionale Programmierung; Folien Kap2-1 - 11 -

Zwei Abkürzungen Id K für die identische Abbildung für den konstanten Kombinator: Id ::= \x -> x (Lambda-Notation: λx.x) K x y ::= \x -> (\y-> x) (Lambda-Notation: λx.(λy.x)) Einführung in die funktionale Programmierung; Folien Kap2-1 - 12 -

Ein nichtterminierender Ausdruck bot := (λx.(x x)) (λy.(y y)) wir werden später sehen, dass die Auswertung dieses Ausdrucks nicht terminiert. Einführung in die funktionale Programmierung; Folien Kap2-1 - 13 -

Freie und gebundene Variablen Die Bindungsregeln in KFPT sind: In λx. e ist x eine gebundene Variable, der Gültigkeitsbereich (Skopus) ist e. In der case-alternative c x 1... x n -> e bindet das Pattern alle Variablen x i. Deren Gültigkeitsbereich (Skopus) ist e. Vorkommen von Variablen, die in keinem Gültigkeitsbereich einer Bindung stehen, sind frei. Bei Konflikten gilt die Regel: der innerste Bindungsbereich zählt Beispiel (λx. x (λx. (y x))) Einführung in die funktionale Programmierung; Folien Kap2-1 - 14 -

Freie und gebundene Variablen verschiedene Vorkommen können zu verschiedenen Bindungen gehören: Beispiel λx. (x (λx. x)) Sichtbar durch Indizes bzw. Umbenennung λx 1. (x 1 (λx 2. x 2 )) Ausdrücke die bis auf Umbenennung gleich sind, nennt man auch α-äquivalent Genauer: durch ein Folge von Umbenennungen ineinander überführt werden können, Einführung in die funktionale Programmierung; Folien Kap2-1 - 15 -

Freie und gebundene Variablen Ein Ausdruck ohne freie Variablen heißt geschlossener Ausdruck sonst offener Ausdruck. Ein KFPT-Programm ist definiert als ein geschlossener KFPT- Ausdruck Einführung in die funktionale Programmierung; Folien Kap2-1 - 16 -

Freie und gebundene Variablen. Beispiele \x -> (case_list x of {Cons y ys -> ys; Nil -> Nil}) ist ein geschlossener Ausdruck. Die Variable x ist frei im Unterausdruck case_list x of {Cons y ys -> ys; Nil -> Nil} Einführung in die funktionale Programmierung; Folien Kap2-1 - 17 -

Auswertungsregeln; operationale Semantik operationale Semantik: Transformationssystem auf den Ausdrücken deterministisch Bei erfolgreichem Terminieren: Der letzte Ausdruck ist der Wert Einführung in die funktionale Programmierung; Folien Kap2-1 - 18 -

Operationale Semantik: Wert Ein Wert in KFPT bzw. eine WHNF (weak head normal form, schwache Kopfnormalform) ist ein Ausdruck der Form (c t 1... t n ), wobei n = arity(c) und c ein Konstruktor ist, oder eine Abstraktion: λx. e. Eine WHNF kann sein: FWHNF, wenn die WHNF eine Abstraktion ist, oder CWHNF, wenn die WHNF eine Konstruktoranwendung der Form (c s 1... s n ) ist. Einführung in die funktionale Programmierung; Folien Kap2-1 - 19 -

Ersetzungen in Ausdrücken s[t/x] Im Ausdruck s werden die freien Vorkommen der Variablen x durch t ersetzt. Zu beachten: kein Einfangen von freien Variablen! Ausreichende Bedingung: In s gebundene Variablen sind von den freien Variablen in t verschieden Wenn nicht, dann gebundene Variablen in s umbenennen. Einführung in die funktionale Programmierung; Folien Kap2-1 - 20 -

Umbenennung Abstraktion : λx.e: λz.e[z/x]: z sei bisher nicht verwendete Variable. In e ersetze alle freien Vorkommen von x durch z. case-alternative: c x 1... x n -> e c z 1... z n -> e[z 1 /x 1,... z n /x n ] ersetze x i durch neue Variablen z i, i = 1,..., n In e ersetze alle freien Vorkommen von x i durch z i : Einführung in die funktionale Programmierung; Folien Kap2-1 - 21 -

Beispiel: Einfangen von Variablen Vorsicht: Auch beim Umbenennen muss man das Einfangen von Variablen vermeiden! Was ist die richtige Ersetzung in (λx.λy.(x z))[y/z]? falsch: richtig: (λx.λy.(x y)). (λx.λu.(x y)). mit Umbenennung: (λx.λy.(x z))[y/z] (λx.λu.(x z))[y/z] (λx.λu.(x y)) Einführung in die funktionale Programmierung; Folien Kap2-1 - 22 -

Auswertungsregeln Auswertungsregeln (Reduktionsregeln): Beta Case ((λx.t) s) t[s/x] (case T (c t 1... t n ) of {... ; c x 1... x n -> s;...}) s[t 1 /x 1,..., t n /x n ] Zunächst darf man diese überall verwenden: in allen Programmkontexten Redex (reducible expression) nennt man den Unterausdruck s, der unmittelbar reduziert wird. Einführung in die funktionale Programmierung; Folien Kap2-1 - 23 -

Beispiele (λx.(λy.x (y x))) (λz.z) (λy.(λz.z) (y (λz.z ))) (case List (Cons 1 (Cons 2 Nil)) {Cons y ys -> ys; Nil -> Nil}) mit Variablenbindung: (y 1; ys (Cons 2 Nil)) (Cons 2 Nil) Einführung in die funktionale Programmierung; Folien Kap2-1 - 24 -

Auswertungsregeln Die Anwendung der Auswertungsregeln ist noch nicht eindeutig: (λx.x)((λy.y)z) hat zwei Reduktionsmöglichkeiten. Ziel: die richtige deterministische Auswertung Einführung in die funktionale Programmierung; Folien Kap2-1 - 25 -

Kontexte Definition Ein Kontext ist ein Ausdruck der an einer Stelle ein Loch hat Das Loch wird geschrieben als [ ]. Man kann Ausdrücke einsetzen: Z.B. mit C[ ] := (\x -> ([ ] x)) ist C[x] = (\x -> (x x)) und C[y] = (\x -> (y x)) Einführung in die funktionale Programmierung; Folien Kap2-1 - 26 -

Reduktionskontexte Definition Reduktionskontexte: R ::= [] (R e) (case T R of {p 1 -> t 1 ;... ; p n -> t n }) Beobachtung: das Loch eines Reduktionskontextes ist: nicht in Abstraktionen nicht in einer Konstruktor-Anwendung nicht im Argument einer Anwendung. nicht in case-alternativen. Einführung in die funktionale Programmierung; Folien Kap2-1 - 27 -

Normalordnungs-Reduktion Normalordnungs-Reduktion (normal-order-reduktion): Der Ausdruck in einem Reduktionskontext wird reduziert: R[s] R[t] Ein-Schritt-Normalordnungsreduktion R ein Reduktionskontext, s keine WHNF und s reduziert unmittelbar zu t Der Unterterm s zusammen mit seiner Position ist der Normalordnungsredex Einführung in die funktionale Programmierung; Folien Kap2-1 - 28 -

Normalordnungs-Reduktion Bezeichnungen n n,+ bzw. n, n, eine Normalordnungsreduktion. die transitive und reflexiv-transitive Hülle von n ist die Normalordnungsrelation oder Auswertung eines Terms. Einführung in die funktionale Programmierung; Folien Kap2-1 - 29 -

Terminierung Definition: Sei t geschlossener Term. Wenn ein t existiert mit t n, t und t ist WHNF, dann: t terminiert (auch: konvergiert) Bezeichnung: t. Wenn nicht, dann: t divergiert Bezeichnung: t. Einführung in die funktionale Programmierung; Folien Kap2-1 - 30 -

Auswertungen Wenn t, sagen wir auch: t hat eine WHNF. Es gilt: Aber: Wenn t n, t und t ist WHNF, dann ist t eindeutig,keine n.o. t t und t ist WHNF, kann für viele verschiedene t gelten. Beispiel (cons ((λx.x) True)) Nil) ist WHNF, aber reduziert zu (cons True Nil) (das ist keine Normalordnung.) Einführung in die funktionale Programmierung; Folien Kap2-1 - 31 -

Beispiel zur Normalordnung (λx.x)((λy.y)z) hat zwei Reduktionsmöglichkeiten, aber nur eine Normalordnungsreduktion: (λx.x)((λy.y)z) n ((λy.y)z). Der Reduktionskontext R ist: ([ ] ein anderer Reduktionskontext: ([ ] ((λy.y)z)) Einführung in die funktionale Programmierung; Folien Kap2-1 - 32 -

Beispiele zur Auswertung ((λx.x) Nil) n Nil ((λx.λy.x) s t) n ((λy.s) t) n s. Umbenennung [y /y] nach dem ersten Reduktionsschritt; y kommt nicht in s vor Einführung in die funktionale Programmierung; Folien Kap2-1 - 33 -

Eigenschaften der Normalordnung Lemma Jede unmittelbare Reduktion in einem Reduktionskontext ist eine Normalordnungsreduktion. Der Normalordnungsredex und die Normalordnungsreduktion sind eindeutig. Eine WHNF hat keinen Normalordnungsredex und erlaubt keine Normalordnungsreduktion. Einführung in die funktionale Programmierung; Folien Kap2-1 - 34 -

Plotkins Sichtweise Gordon Plotkin: Eine Programmiersprache hat vier wichtige Komponenten: Ausdrücke Kontexte Werte eine Auswertungsrelation auf Ausdrücken. Das definiert dann u.a. t. Die Theorie der korrekten Programm-Transformationen kann man darauf aufbauen: s, t sind gleich, wenn für alle Kontexte C: C[s] C[t] (siehe zweite Semesterhälfte) Einführung in die funktionale Programmierung; Folien Kap2-1 - 35 -

Dynamische Typregeln für KFPT Für case: R[(case T e of {alt 1 ;... ; alt m })] ist direkt dynamisch ungetypt wenn R Reduktionskontext und e eine der folgenden Formen hat: (c a 1... a arc ) und c ist ein Konstruktor, der nicht zum Typ T gehört, λx. t. für Konstruktoren: R[((c a 1... a arc ) e)] ist direkt dynamisch ungetypt, wenn R Reduktionskontext ist. Einführung in die funktionale Programmierung; Folien Kap2-1 - 36 -

Dynamische Typregeln für KFPT Ein geschlossener Ausdruck e ist dynamisch ungetypt, wenn e : e n, e und e ist direkt dynamisch ungetypt. D.h. wenn die Normalordnungs-Reduktion eines geschlossenen Terms stoppt, aber keine WHNF erreicht ist. Bei offenen Termen von der Form R[x R ] spricht man nicht von Typfehler. Einführung in die funktionale Programmierung; Folien Kap2-1 - 37 -

Typisierung in KFPT e ist dynamisch wohlgetypt wenn e nicht dynamisch ungetypt ist. Haskells Typisierung ist restriktiver als es tritt kein dynamischer Typfehler auf Einführung in die funktionale Programmierung; Folien Kap2-1 - 38 -

Unwind Algorithmus zur Bestimmung des Normalordnungsredex geschrieben als eine Menge von Regeln, die ein Label (R) verschieben: Start mit t R, d.h. das Label ist ganz oben C[(s s ) R ] C[(s R s )] C[(case s alts) R ] C[(case s R alts)] Regel-Anwendung solange, bis nicht mehr möglich. Einführung in die funktionale Programmierung; Folien Kap2-1 - 39 -

Unwind Danach die Normalordnungs-Reduktion: (falls möglich) Beta C[((λx.t) R s)] C[t[s/x]] Case C[(case T (c t 1... t n ) R of {... ; c x 1... x n -> s;...})] C[s[t 1 /x 1,..., t n /x n ]] wenn keine möglich ist, dann gibt es zwei Möglichkeiten: (für geschlossenen Ausdrücke) WHNF oder dynamischer Typfehler. WHNF bei geschlossenen Ausdrücken): genau dann, wenn R-Label des Top-Terms sich durch die Regeln nicht verschieben lässt. Einführung in die funktionale Programmierung; Folien Kap2-1 - 40 -

Dynamisches Verhalten der Normalordnung Normalordnung: markiert Unterterme mit R reduziert R-markierte Unterterme, bis diese in WHNF sind. usw. Dies kann man als rekursiven Auswertungsalgorithmus formulieren. Ein effizienter Auswertungsalgorithmus benötigt noch Sharing! Einführung in die funktionale Programmierung; Folien Kap2-1 - 41 -

Beispiel: Auswertung bot := (λx.(x x)) (λy.(y y)) terminiert nicht: Die (beta)-reduktion ergibt: (λx.(x x)) R (λy.(y y)) n ((λy.(y y)) (λy.(y y))) n... Einführung in die funktionale Programmierung; Folien Kap2-1 - 42 -

Beispiel: Boolesche Funktionen aussagenlogische Verknüpfungen und, oder, nicht: und = λx. λy. case Bool x of {True-> y; False-> False} oder = λx. λy. case Bool x of {True-> True; False-> y} nicht = λx. case Bool x of {True-> False; False-> True} In Haskell sind die logischen Verknüpfungen bereits im Prelude definiert als &&,, not. Einführung in die funktionale Programmierung; Folien Kap2-1 - 43 -

Standardisierungs-Satz Satz (Standardisierung). Sei t ein (evtl. offener) Ausdruck und t t 1 mit (Beta) und (case)-reduktionen, wobei t 1 eine WHNF ist. Dann existiert eine WHNF t 2, so dass t no, t 2, und t 2 t1. t 1 t no, WHNF WHNF t 2 Folgerung: es ist korrekt, an beliebigen Positionen zu reduzieren, bis eine WHNF erreicht ist. Wenn die erreichte WHNF eine Konstruktorkonstante ist (z.b. True), dann ist sie sogar eindeutig. Einführung in die funktionale Programmierung; Folien Kap2-1 - 44 -

Syntax der funktionalen Kernsprache KFP Wir geben die Syntax von KFP hier zur Information schon mal an. Sie wird in der zweiten Semesterhälfte genauer besprochen KFP ist analog zu Kernsprachen von Compilern funktionaler Programmiersprachen. Einfache Syntax, möglichst wenig vordefiniert Einführung in die funktionale Programmierung; Folien Kap2-1 - 45 -

Syntax der funktionalen Kernsprache KFP Syntax: von KFP: Es gibt N Konstruktoren c i, i = 1,..., N mit jeweils Stelligkeit ar(c i ) CFG für KFP-Ausdrücke: EXP ::= V V sind Variablen λv. EXP (EXP EXP ) (c EXP 1... EXP n ) wobei c Konstruktor und n = ar(c) (case EXP {P at 1 Exp 1 ;... ; P at N+1 Exp N+1 }) P at i ist Pattern zum Konstruktor i, und P at N+1 das Pattern lambda. Pat ::= (c V 1... V ar(c) ) lambda Einführung in die funktionale Programmierung; Folien Kap2-1 - 46 -

Reduktionen der funktionalen Kernsprache KFP Normalordungs-Redex wie in KFPT Reduktionen wie in KFPT; einziges Extra: (case (\x.s) {... ; lambda e) e Einführung in die funktionale Programmierung; Folien Kap2-1 - 47 -

KFP und KFPT KFP: Unterschied zu KFPT: KFP hat ein ungetyptes case-konstrukt zu jedem Konstruktor ex im case eine Alternative extra Pattern: lambda : matcht Abstraktionen : Dadurch kann man z.b. seq in KFP definieren Einführung in die funktionale Programmierung; Folien Kap2-1 - 48 -

Rekursive Superkombinatoren: KFPTS Wir erweitern KFPT um Haskells rekursive Superkombinatoren. Die Erweiterung nennen wir KFPTS : Programmierung in KFPTS wie in einem vereinfachten Haskell Einführung in die funktionale Programmierung; Folien Kap2-1 - 49 -

KFPTS Syntax Ausdrücke wie in KFPT, nur um Superkombinatornamen erweitert. Es gibt Funktionsnamen (Superkombinatornamen) als neue Konstanten und eine Menge von Definitionen der Form Superkombinatorname V 1... V n = Exp Bedingungen: V 1... V n sind verschieden; In Exp kommen nur diese Variablen frei vor. Die Namensräume für Variablen, Konstruktoren, Kombinatornamen sind disjunkt. Jeder Superkombinator wird höchstens einmal definiert Das eröffnet die Möglichkeit, rekursive Funktionen zu definieren da Namen von Funktionen beliebig verwendet werden können. Einführung in die funktionale Programmierung; Folien Kap2-1 - 50 -

KFPTS-Programme Ein KFPTS-Programm besteht aus: 1. Einer Menge von Typen und Konstruktoren wie in KFPT, 2. einer Menge von Kombinator-Definitionen 3. und aus einem Ausdruck. definiert als main = Exp (main-konvention) Einführung in die funktionale Programmierung; Folien Kap2-1 - 51 -

KFPTS-Auswertung Reduktionsregeln: Beta SK-Beta ((λx.t) s) t[s/x] (f a 1... a n ) r[a 1 /x 1,..., a n /x n ] wenn f definiert ist als: f x 1... x n = r d.h. wenn ar(f) = n Case (case T (c t 1... t n ) of {... ; c x 1... x n -> s;...}) s[t 1 /x 1,..., t n /x n ] wobei n = ar(c)und c ist T -Konstruktor Unterschied zu Beta in KFPT: SK-Beta reduziert nur bei ausreichend vielen Argumenten. Einführung in die funktionale Programmierung; Folien Kap2-1 - 52 -

Beispiel map f xs = case List xs of {(Cons y ys) (Cons (f y) (map f ys)); Nil Nil} main = map not (Cons True Nil) Einführung in die funktionale Programmierung; Folien Kap2-1 - 53 -

KFPTS-Normal-Ordnung Reduktionskontexte in KFPTS wie in KFPT Der Wert des Programms ist der Wert des main-ausdrucks nach Auswertung. KFPTS-Normalordnungsreduktion: innerhalb eines KFPTS-Reduktionskontexts wird unmittelbar mit Case, Beta oder SK-Beta reduziert. Einführung in die funktionale Programmierung; Folien Kap2-1 - 54 -

KFPTS-Normal-Ordnung Normal-Ordnungs Reduktionen mit R-Label: Beta C[((λx.t) R s)] C[t[s/x]] Case C[(case T (c t 1... t n ) R of {... ; c x 1... x n -> s;...})] C[s[t 1 /x 1,..., t n /x n ]] Neu : SK-Beta C[(SK R s 1... s ar(sk ) )] C[r SK [s 1 /V 1,..., s n /V n ]] Einführung in die funktionale Programmierung; Folien Kap2-1 - 55 -

KFPTS-WHNF Eine KFPTS-WHNF ist entweder ein Ausdruck (c t 1... t n ) ; oder ein Ausdruck (f t 1... t n ), wobei f Kombinator und n < ar(f); oder ein Ausdruck λx.s Beispiel: map und (map not) sind WHNFs Einführung in die funktionale Programmierung; Folien Kap2-1 - 56 -

strict und seq (strict f t) macht f strikt im ersten Argument: Wert(f t) = a; t Wert(strict f t) = a und t (strict f t) (seq s t) wertet s und t aus und gibt den Wert von t zurück: Wert(t) = a; s Wert(seq s t) = a und s (seq s t) Einführung in die funktionale Programmierung; Folien Kap2-1 - 57 -

strict und seq Beide sind gleichwertig: strict f t = seq t (f t) seq s t = strict (\x->t) s In KFP sind strict und seq definierbar: strict f = \x. case x of {p_1 -> f x;... ;p_n -> f x;p_{n+1} -> f x} Beachte: In KFPT, KFPTS sind strict und seq nicht definierbar. Einführung in die funktionale Programmierung; Folien Kap2-1 - 58 -

Betrachtete Kernsprachen KFP KFPT KFPTS KFPT+ seq KFPTS+ seq KFPTSP Abstraktionen, Anwendungen,Konstruktoranwendungen jedes case hat alle Pattern und ein extra Pattern lambda Abstraktionen, Anwendungen,Konstruktoranwendungen jedes case hat nur Pattern eines Typs Wie KFPT; Superkombinatoren sind erlaubt. KFPT und seq wird als definiert angenommen KFPTS und seq wird als definiert angenommen KFPTS + seq und polymorphe Typisierung Einführung in die funktionale Programmierung; Folien Kap2-1 - 59 -