Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Lambda-Kalkül und Haskell Der Lambda-Kalkül ist als Kernsprache für Haskell eher ungeeignet: Keine echten Daten: Zahlen, Boolesche Werte, Listen und komplexe Datenstrukturen fehlen im Lambda-Kalkül. Ausweg mittels Church-Kodierung: Einführung in Funktionale Programmierung Funktionale Kernsprachen: Die KFP-Kernsprachen z.B. true = λx, y.x false = λx, y.y if-then-else = λb, x1 , x2 .b x1 x2 PD Dr. David Sabel if-then-else true e1 e2 = (λb, x1 , x2 .b x1 x2 ) (λx, y.x) e1 e2 no,β,3 no,β,2 −−−−→ (λx, y.x) e1 e2 −−−−→ e1 WS 2015/16 if-then-else false e1 e2 = (λb, x1 , x2 .b x1 x2 ) (λx, y.y) e1 e2 no,β,3 no,β,2 −−−−→ (λx, y.y) e1 e2 −−−−→ e2 Aber: Kompliziert; Daten und Funktionen sind nicht unterscheidbar; Typisierung passt nicht Stand der Folien: 22. Oktober 2015 1 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 2/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Lambda-Kalkül und Haskell (2) Kernsprachen für Haskell Rekursive Funktionen: Geht nur über Fixpunkt-Kombinatoren: Fakultät als Beispiel: Im folgenden führen wir verschiedene Kernsprachen ein. Alle sind Erweiterungen des Lambda-Kalküls f ak = (λf.(λx.f (x x)) (λx.f (x x))) (λf.λx.if x = 0 then 1 else x ∗ (f (x − 1))) Bezeichnungen: KFP. . . KFP = Kern einer Funktionalen Programmiersprache Aber: Kompliziert und schwer verständlich! Typisierung fehlt Haskell ist polymorph getypt. Kein seq: In Haskell ist seq verfügbar, im Lambda-Kalkül nicht kodierbar. D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 3/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 4/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Die Kernsprache KFPT Datentypen Annahmen: Es gibt eine (endliche) Menge von Typen (das sind nur Namen) Für jeden Typ gibt es eine endliche Menge von Datenkonstruktoren: Formale Notation: ci . Erweiterung des Lambda-Kalküls um Datentypen (Konstruktoren) und case. Datenkonstruktoren haben eine Stelligkeit ar(ci ) ∈ N0 (ar = arity“) ” Beispiele KFPT: T steht für getyptes case Beachte: KFPT ist nur ganz schwach getypt. Typ Bool, Datenkonstruktoren: True und False, ar(True) = 0 = ar(False). Typ List, Datenkonstruktoren: Nil und Cons, ar(Nil) = 0 und ar(Cons) = 2. Haskell-Schreibweise: [] für Nil und : (infix) für Cons Beachte [a1 , a2 , . . . , an ] ist Abkürzung für a1 : (a2 : (. . . : (an : []))) D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 5/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 6/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Syntax von KFPT Beispiele (1) Erstes Element einer Liste (head): Expr ::= V | λV.Expr | (Expr1 Expr2 ) | (ci Expr1 . . . Exprar(ci ) ) | (caseTypname Expr of {Pat1 → Expr1 ; . . . ; Patn → Exprn }) (Variable) λxs.caseList xs of {Nil → ⊥; (Cons y ys) → y} (Abstraktion) Restliste ohne erstes Element (tail): (Anwendung) (Konstruktoranwendung) λxs.caseList xs of {Nil → ⊥; (Cons y ys) → ys} (case-Ausdruck) ⊥ repräsentiert Fehler, z.B Ω Pati ::= (ci V1 . . . Var (ci ) ) (Pattern für Konstruktor i) wobei die Variablen Vi alle verschieden sind. λxs.caseList xs of {Nil → True; (Cons y ys) → False} Nebenbedingungen: case mit Typ gekennzeichnet, If-Then-Else: if e then s else t: Pati → Expri heißt case-Alternative case-Alternativen sind vollständig und disjunkt für den Typ: für jeden Konstruktor des Typs kommt genau eine Alternative vor. D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen Test, ob Liste leer ist (null): caseBool e of {True → s; False → t} 7/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 8/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiele (2) Haskell vs. KFPT: case-Ausdrücke (1) Vergleich mit Haskells case-Ausdrücken Syntax ähnlich: Paare: Typ Paar mit zweistelligem Konstruktor Paar Z.B. wird (True, False) durch (Paar True False) dargestellt. Statt → in Haskell: -> Keine Typmarkierung am case Projektionen: fst snd Beispiel: KFPT: caseList xs of {Nil → Nil; (Cons y ys) → y} Haskell: case xs of {[] -> []; (y:ys) -> y} := λx.casePaar x of {(Paar a b) → a} := λx.casePaar x of {(Paar a b) → b} Analog: mehrstellige Tupel In Haskell ist es nicht notwendig alle Konstruktoren abzudecken In Haskell sind Tupel bereits vorhanden (eingebaut), Schreibweise (a1 , . . . , an ) Kann Laufzeitfehler geben: (case True of False -> False) *** Exception: Non-exhaustive patterns in case In Haskell auch 0-stellige Tupel, keine 1-stelligen Tupel D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 9/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 10/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Haskell vs. KFPT: case-Ausdrücke (2) Haskell vs. KFPT: case-Ausdrücke (3) Übersetzung von geschachtelten in einfache Pattern (für KFPT) case [] of {[] -> []; (x:(y:ys)) -> [y]} Haskell erlaubt überlappende Pattern und geschachtelte Pattern. Z.B. ist wird übersetzt in: case [] of {[] -> []; (x:(y:ys)) -> [y]; x -> []} ein gültiger Haskell-Ausdruck caseList Nil of {Nil → Nil; (Cons x z) → caseList z of {Nil → ⊥; (Cons y ys) → (Cons y Nil) } } Semikolon und Klammern kann man bei Einrückung weglassen: case [] of [] -> [] (x:(y:ys)) -> [y] x -> [] Fehlende Alternativen werden durch P at → ⊥ ergänzt. ⊥ (gesprochen als bot“): Repräsentant eines geschlossenen ” nicht terminierenden Ausdrucks. Abkürzung: (caseT yp s of Alts) D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 11/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 12/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Freie und gebundene Variablen in KFPT Freie Variablen FV (x) FV (λx.s) FV (s t) FV (c s1 . . . sar(c) ) =x = FV (s) \ {x} = FV (s) ∪ FV (t) = FV (s1 ) ∪ . . . ∪ FV (sar(ci ) ) n S FV (caseT yp t of = FV (t) ∪ ( (FV (si ) \ {xi,1 , . . . , xi,ar(ci ) })) i=1 {(c1 x1,1 . . . x1,ar(c1 ) ) → s1 ; ... (cn xn,1 . . . xn,ar(cn ) ) → sn }) Zusätzlich zum Lambda-Kalkül: In case-Alternative (ci x1 . . . xar(ci ) ) → s sind die Variablen x1 , . . . , xar(ci ) in s gebunden. D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 13/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 14/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Gebundene Variablen Beispiel =∅ = BV (s) ∪ {x} = BV (s) ∪ BV (t) = BV (s1 ) ∪ . . . ∪ BV (sar(ci ) ) n S BV (caseT yp t of = BV (t) ∪ ( (BV (si ) ∪ {xi,1 , . . . , xi,ar(ci ) })) i=1 {(c1 x1,1 . . . x1,ar(c1 ) ) → s1 ; ... (cn xn,1 . . . xn,ar(cn ) ) → sn }) BV (x) BV (λx.s) BV (s t) BV (c s1 . . . sar(c) ) s := ((λx.caseList x of {Nil → x; Cons x xs → λu.(x λx.(x u))}) x) FV (s) = {x} und BV (s) = {x, xs, u} Alpha-äquivalenter Ausdruck: s0 := ((λx1 .caseList x1 of {Nil → x1 ; Cons x2 xs → λu.(x2 λx3 .(x3 u))}) x) FV (s0 ) = {x} und BV (s0 ) = {x1 , x2 , xs, x3 , u} D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 15/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 16/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Notationen Operationale Semantik Substitution s[t/x] ersetzt alle freien Vorkommen von x in s durch t (wenn BV (s) ∩ FV (t) = ∅) s[t1 /x1 , . . . , tn /xn ] parallele Ersetzung von x1 , . . . , xn durch t1 , . . . , tn (wenn für alle i:BV (s) ∩ FV (ti ) = ∅) Wie im Lambda-Kalkül (mit angepasster FV , BV Definition) Offene und geschlossene Ausdrücke Definition Die Reduktionsregeln (β) und (case) sind in KFPT definiert als: α-Umbenennung Distinct Variable Convention (β) (λx.s) t → s[t/x] (case) caseT yp (c s1 . . . sar(c) ) of {. . . ; (c x1 . . . xar(c) ) → t; . . .} → t[s1 /x1 , . . . , sar(c) /xar(c) ] Wenn s → t mit (β) oder (case) dann reduziert s unmittelbar zu t D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 17/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 18/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel KFPT-Kontexte Kontext = Ausdruck mit Loch [·] C ::= [·] | λV.C | (C Expr) | (Expr C) | (ci Expr1 . . . Expri−1 C Expri+1 Exprar(ci ) ) | (caseTyp C of {Pat1 → Expr1 ; . . . ; Patn → Exprn }) | (caseTyp Expr of {Pat1 → Expr1 ; . . . ; Pati → C; . . . , Patn → Exprn }) (λx.casePaar x of {(Paar a b) → a}) (Paar True False) β − → casePaar (Paar True False) of {(Paar a b) → a} case −−→ True β case Wenn C[s] → C[t] wobei s − → t oder s −−→ t, dann bezeichnet man s (mit seiner Position in C) als Redex von C[s]. Redex = Reducible expression D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 19/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 20/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Normalordnungsreduktion Normalordnungsreduktion (2) Definition Reduktionskontexte R in KFPT werden durch die folgende Grammatik erzeugt: Definition Wenn s unmittelbar zu t reduziert, dann ist R[s] → R[t] für jeden Reduktionskontext R eine Normalordnungsreduktion. R ::= [·] | (R Expr) | (caseT yp R of Alts) no no,β no,case Notation: −→, bzw. auch −−−→ und −−−−→. Redexsuche mit ∗ Neue Regel: • (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) no,+ no −−−→ transitive Hülle von −→ no,∗ no −−→ reflexiv-transitive Hülle von −→ Beispiel: ((caseBool s of {True → (λx, y.x); False → (λx, y.y)}) Nil)? D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 21/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 22/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiele Normalformen Ein KFPT-Ausdruck s ist eine Normalform (NF = normal form): s enthält keine (β)- oder (case)-Redexe und ist WHNF Kopfnormalform (HNF = head normal form): s ist Konstruktoranwendung oder Abstraktion λx1 , . . . xn .s0 , wobei s0 entweder Variable oder (c s1 . . . sar(c) ) oder (x s0 ) ist → x[(λy.y) (λz.z)/x] = (λy.y) (λz.z) ist eine Normalordnungsreduktion. (λx.x) ((λy.y) (λz.z)) schwache Kopfnormalform (WHNF = weak head normal form): s ist eine FWHNF oder eine CWHNF. → (λx.x) (y[(λz.z)/y]) = (λx.x) (λz.z) ist keine Normalordnungsreduktion (λx.x) ((λy.y) (λz.z)) funktionale schwache Kopfnormalform (FWHNF = functional whnf): s ist eine Abstraktion Konstruktor-schwache Kopfnormalform (CWHNF = constructor whnf): s ist eine Konstruktoranwendung (c s1 . . . sar(c) ) Wir verwenden nur WHNFs (keine NFs, keine HNFs). D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 23/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 24/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Terminierung bzw. Konvergenz Dynamische Typisierung Normalordnungsreduktion stoppt ohne WHNF: Folgende Fälle: eine freie Variable ist potentieller Redex (Ausdruck von der Form R[x]), oder Definition Ein KFPT-Ausdruck s konvergiert (oder terminiert, notiert als s⇓) genau dann, wenn: ein dynamischer Typfehler tritt auf. Definition (Dynamische Typregeln für KFPT) no,∗ s⇓ ⇐⇒ ∃ WHNF t : s −−→ t Ein KFPT-Ausdruck s direkt dynamisch ungetypt, falls: Falls s nicht konvergiert, so sagen wir s divergiert und notieren dies mit s⇑. s = R[caseT (c s1 . . . sn ) of Alts] und c ist nicht vom Typ T Sprechweisen: Wir sagen s hat eine WHNF (bzw. FWHNF, CWHNF), no,∗ wenn s zu einer WHNF (bzw. FWHNF, CWHNF) mit −−→ reduziert werden kann. s = R[(c s1 . . . sar(c) ) t] D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen s = R[caseT λx.t of Alts]. s ist dynamisch ungetypt ⇐⇒ no,∗ ∃t : s −−→ t ∧ t ist direkt dynamisch ungetypt 25/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 26/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiele Dynamische Typisierung (2) Satz Ein geschlossener KFPT-Ausdruck s ist irreduzibel (bzgl. der Normalordnung) genau dann, wenn eine der folgenden Bedingungen auf ihn zutrifft: caseList True of {Nil → Nil; (Cons x xs) → xs} ist direkt dynamisch ungetypt (λx.caseList x of {Nil → Nil; (Cons x xs) → xs}) True ist dynamisch ungetypt Entweder ist s eine WHNF, oder (Cons True Nil) (λx.x) ist direkt dynamisch ungetypt s ist direkt dynamisch ungetypt. (caseBool x of {True → True; False → False}) ist nicht (direkt) dynamisch ungetypt (λx.caseBool x of {True → True; False → False}) (λy.y) ist dynamisch ungetypt D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen Diese Eigenschaft wird auch Progress-Lemma genannt: Wenn t geschlossen, keine WHNF und getypt, dann kann man eine Normalordnungsreduktion durchführen. 27/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 28/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Markierungsalgorithmus zur NO-Redex-Suche Beispiel Für Ausdruck s starte mit s? , Verschieberegeln: (s t)? ⇒ (s? caseList y of { True)) (λu, v.v)) (Cons (λw.w) Nil))? (((λx.λy.( Nil → Nil; (Cons z zs) → (x z)} t) (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) Fälle danach: Markierung ist an einer Abstraktion; Fälle: caseList y of { True)) (Cons (λw.w) Nil))? ((λy.( Nil → Nil; (Cons z zs) → ((λu, v.v) z)} no,β −−−→ (λx.s0 )? , dann FWHNF C[((λx.s0 )? s00 )], dann reduziere die Applikation mit β C[caseT (λx.s0 )? . . .)], dann direkt dynamisch ungetypt caseList (Cons (λw.w) Nil) of { True)? ( Nil → Nil; (Cons z zs) → ((λu, v.v) z)} no,β −−−→ Markierung ist an einer Konstruktorapplikation (c . . .)? , dann CWHNF C[((c . . .)? s0 )], dann direkt dynamisch ungetypt C[(caseT (c . . .)? alts)], reduzieren, falls c zum Typ T gehört, sonst direkt dynamisch ungetypt no,case −−−−−→ (((λu, v.v) (λw.w)) True)? no,β Markierung ist an einer Variablen: Keine Reduktion möglich D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen ((λv.v) True)? −−−→ no,β −−−→ 29/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen True D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Darstellung von Ausdrücken als Termgraphen Darstellung von Ausdrücken als Termgraphen (2) Konstruktoranwendungen n-stellig: (c s1 . . . sn ) wobei si die Bäume für si c Knoten für je ein syntaktisches Konstrukt des Ausdrucks Variablen = ein Blatt Abstraktionen λx.s λ v s1 wobei s Baum für s . .~. ... ( ... sn case-Ausdrücke: n + 1 Kinder, caseT yp s of {Alt1 ; . . . ; Altn } caseT yp x s Applikationen (s t) @ s 30/54 wobei s , t Bäume für s und t s u z Alt1 .# . . ... case-Alternative P at → t Altn → t | P at D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen ) 31/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen t 32/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel Normalordnungsreduktion: Eigenschaften Die Normalordnungsreduktion ist deterministisch, d.h. für no jedes s gibt es höchstens ein t mit s −→ t. Eine WHNF ist irreduzibel bezüglich der Normalordnungsreduktion. λx.λy.caseList (Cons x Nil) of { (Cons z zs) → False; True (Cons True Nil) Nil → True} @ ) @t ' λt x # { Cons x } True Nil Cons z ∗ Wenn s → − t mit beliebigen (β)- und (case)-Reduktionen (in beliebigem Kontext angewendet), wobei t eine WHNF ist, dann no,∗ ∗ existiert eine WHNF t0 , so dass s −−→ t0 und t0 → − t (unter α-Gleichheit). s & z Satz (Standardisierung für KFPT) Nil caseList r # # True λ { y Cons z w → ' ' False Nil { ,→ $ True zs t o WHNF NO-Redex-Suche: immer links, bis Abstraktion, Konstruktoranwendung D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen no,∗ ∗ 33/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen ∗ t0 WHNF D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 34/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Rekursive Superkombinatoren: KFPTS KFPTS: Syntax Nächste Erweiterung: KFPT zu KFPTS S“ steht für Superkombinatoren ” Superkombinatoren sind Namen (Konstanten) für Funktionen Expr ::= | | | Superkombinatoren dürfen auch rekursive Funktionen sein Annahme: Es gibt eine Menge von Superkombinatornamen SK. Beispiel: Superkombinator length V | λV.Expr | (Expr1 Expr2 ) (ci Expr1 . . . Exprar(ci ) ) (caseTyp Expr of {Pat1 → Expr1 ; . . . ; Patn → Exprn }) SK wobei SK ∈ SK Pati ::= (ci V1 . . . Var (ci ) ) wobei die Variablen Vi alle verschieden sind. length xs =caseList xs of { Nil → 0; (Cons y ys) → (1 + length ys)} D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 35/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 36/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS:Syntax (2) KFPTS: Syntax (3) Zu jedem Superkombinator SK gibt es eine Superkombinatordefinition: Ein KFPTS-Programm besteht aus: Einer Menge von Typen und Konstruktoren, SK V1 . . . Vn = Expr einer Menge von Superkombinator-Definitionen, dabei und aus einem KFPTS-Ausdruck s. (Diesen könnte man auch als Superkombinator main mit Definition main = s definieren.) Vi paarweise verschiedene Variablen; Expr ein KFPTS-Ausdruck; Dabei müssen alle in s verwendeten Superkombinatoren auch definiert sein. FV (Expr) ⊆ {V1 , . . . , Vn }; ar(SK) = n ≥ 0: Stelligkeit des Superkombinators (n = 0 ist möglich). D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 37/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 38/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS:Syntax (2) Superkombinatoren KFPTS: Operationale Semantik Reduktionskontexte: R ::= [·] | (R Expr) | caseT yp R of Alts Reduktionsregeln (β), (case) und (SK-β): Haskell; Unterschiede bei Superkombinatordefinitionen: Mehrere Definitionen (für verschiedene Fälle) pro Superkombinator. Argumente können Pattern sein Guards sind möglich (β) (λx.s) t → s[t/x] (case) caseT yp (c s1 . . . sar(c) ) of {. . . ; (c x1 . . . xar(c) ) → t; . . .} → t[s1 /x1 , . . . , sar(c) /xar(c) ] (SK-β) (SK s1 . . . sn ) → e[s1 /x1 , . . . , sn /xn ], wenn SK x1 . . . xn = e die Definition von SK ist Normalordnungsreduktion: s → t mit (β)-, (case)- oder (SK-β) no R[s] −→ R[t] D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 39/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 40/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS: WHNFs und Dynamische Typisierung Markierungsalgorithmus WHNFs Markierung funktioniert genauso wie in KFPTS: WHNF = CWHNF oder FWHNF (s t)? ⇒ (s? t) CWHNF = Konstruktoranwendung (c s1 . . . sar(c) ) (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) FWHNF = Abstraktion oder SK s1 . . . sm mit ar(SK) > m Neue Fälle: Ein Superkombinator ist mit ? markiert: Direkt dynamisch ungetypt: Regeln wie vorher: R[(caseT λx.s of . . .)], R[(caseT (c s1 . . . sn )of . . .)], wenn c nicht von Typ T und R[((c s1 . . . sar(c) ) t)] Genügend Argumente vorhanden: Reduziere mit (SK-β) Zu wenig Argumente und kein Kontext außen: WHNF Zu wenig Argumente und im Kontext (case [.] . . .): direkt dynamisch ungetypt. Neue Regel: R[caseT (SK s1 . . . sm ) of Alts] ist direkt dynamisch ungetypt falls ar(SK) > m. D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 41/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 42/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel Erweiterung um seq und strict Die Superkombinatoren map und not seien definiert als: map f xs = caseList xs of {Nil → Nil; (Cons y ys) → Cons (f y) (map f ys)} not x = caseBool x of {True → False; False → True} In Haskell gibt es seq: (seq a b) = b falls a⇓ ⊥ falls a⇑ Operational: Werte erst a aus, dann b Beispiel zur Auswertung: Analog: strict (in Haskell infix als $! geschrieben) map not (Cons True (Cons False Nil)) strict f macht f strikt im ersten Argument, d.h. strict f wertet erst das Argument aus, dann erfolgt die Definitionseinsetzung. no,SK-β −−−−−→ caseList (Cons True (Cons False Nil)) of { Nil → Nil; (Cons y ys) → Cons (not y) (map not ys)} no,case −−−−→ Cons (not True) (map not (Cons False Nil)) seq und strict sind austauschbar: f $! x seq a b WHNF erreicht! = = seq x (f x) (\x -> b) $! a Beachte: Im GHCI-Interpreter wird nur aufgrund des Anzeigens weiter ausgewertet D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 43/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 44/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPXX+seq Sprachen Bemerkung: Die Sprache KFP KFP hat keine Typbeschränkungen! seq ist in KFPT, KFPTS nicht kodierbar! Expr ::= V | λV.Expr | (Expr1 Expr2 ) | (ci Expr1 . . . Exprar(ci ) ) | (case Expr of {Pat1 → Expr1 ; . . . ; Patn → Exprn ; lambda → Exprn+1 }) wobei P at1 , . . . , P atn alle Konstruktoren abdecken Wir bezeichnen mit KFPT+seq die Erweiterung von KFPT um seq KFPTS+seq die Erweiterung von KFPTS um seq Wir verzichten auf die formale Definition! Man benötigt u.a. die Reduktionsregel: Pati seq v t → t, wenn v WHNF ::= (ci V1 . . . Var (ci ) ) wobei die Variablen Vi alle verschieden sind. Unterschied zu KFP: Kein getyptes case, lambda-Pattern Neue Reduktionsregel case λx.s of {. . . , lambda → t} → t erweiterte Reduktionskontexte und die neue Verschieberegel: In KFP ist seq kodierbar: (seq s t)? → (seq s? t) seq a b := case a of {P at1 → b; . . . ; P atn → b; lambda → b} D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 45/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 46/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTSP Beispiele Mit KFPTSP bezeichnen wir polymorph getyptes KFPTS Definition Die Syntax von polymorphen Typen kann durch die folgende Grammatik beschrieben werden: True False not map (λx.x) T ::= T V | T C T1 . . . Tn | T1 → T2 wobei T V für eine Typvariable steht und T C ein Typkonstruktor mit Stelligkeit n ist. :: :: :: :: :: Bool Bool Bool → Bool (a → b) → [a] → [b] (a → a) polymorph: Typen haben Typvariablen z.B. fak :: Int → Int z.B. map :: (a → b) → (List a) → (List b) Haskell: -> statt → Haskell verwendet [a] statt (List a). D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 47/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 48/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einfache Typregeln Beispiel Für die Anwendung: s :: T1 → T2 , t :: T1 and := λx, y.caseBool x of {True → y; False → False} or := λx.y.caseBool x of {True → True; False → y} (s t) :: T2 Instantiierung Mit der Anwendungsregel: wenn T 0 = σ(T ), wobei σ eine Typsubstitution ist, s :: T 0 die Typen für Typvariablen ersetzt. s :: T and :: Bool → Bool → Bool, True :: Bool (and True) :: Bool → Bool Für case-Ausdrücke: s :: T1 , , False :: Bool (and True False) :: Bool ∀i : P ati :: T1 , ∀i : ti :: T2 (caseT s of {P at1 → t1 ; . . . ; P atn → tn ) :: T2 } D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 49/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 50/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel Beispiel Cons :: a → [a] → [a] Cons :: Bool → [Bool] → [Bool] True :: Bool, , False :: Bool , True :: Bool (Cons True) :: [Bool] → [Bool] (Cons True Nil) :: [Bool] , Nil :: [a] Nil :: [Bool] , Nil :: [a] Nil :: [Bool] map :: (Bool → Bool) → [Bool] → [Bool] , not :: Bool → Bool (map not) :: [Bool] → [Bool] caseBool True of {True → (Cons True Nil); False → Nil} :: [Bool] D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen map :: (a → b) → [a] → [b] 51/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 52/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Ausblick Übersicht Kernsprache KFP KFPT KFPTS KFPTSP KFPT+seq KFPTS+seq KFPTSP+seq Besonderheiten Erweiterung des call-by-name Lambda-Kalküls um ungetyptes case und Datenkonstruktoren, spezielles case-Pattern lambda ermöglicht Kodierung von seq. Erweiterung des call-by-name Lambda-Kalküls um (schwach) getyptes case und Datenkonstruktoren, seq ist nicht kodierbar. Erweiterung von KFPT um rekursive Superkombinatoren, seq nicht kodierbar. KFPTS, polymorph getypt; seq nicht kodierbar. Erweiterung von KFPT um den seq-Operator Erweiterung von KFPTS um den seq-Operator KFPTSP+seq mit polymorpher Typisierung, geeignete Kernsprache für Haskell D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen Erörterung der meisten Konstrukte von Haskell insbesondere auch: Modulsystem, Typklassen Informell: KFPTSP+seq ist die passende Kernsprache Genaue Analyse der Typisierung kommt erst danach! 53/54 D. Sabel · EFP · WS 2015/16 · Funktionale Kernsprachen: Die KFP-Kernsprachen 54/54