Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Übersicht Einführung in die Funktionale Programmierung: 1 Einleitung 2 KFPT 3 KFPTS 4 Erweiterung um seq 5 Polymorphe Typen Funktionale Kernsprachen: Die KFP-Kernsprachen Prof. Dr. Manfred Schmidt-Schauß WS 2011/12 Stand der Folien: 31. Oktober 2011 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 1 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 2/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Lambda-Kalkül und Haskell Lambda-Kalkül und Haskell (2) 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. Rekursive Funktionen: Geht nur über Fixpunkt-Kombinatoren: Fakultät als Beispiel: Ausweg Church-Kodierung: f ak = (λf.(λx.f (x x)) (λx.f (x x))) (λf.λx.if x = 0 then 1 else x ∗ (f (x − 1))) z.B. true = λx, y.x false = λx, y.y if-then-else = λb, x1 , x2 .b x1 x2 Aber: Kompliziert und schwer verständlich! if then-else true e1 e2 = (λb, x1 , x2 .b x1 x2 ) (λx, y.x) e1 e2 no,β,3 Typisierung fehlt Haskell ist polymorph getypt. no,β,2 −−−−→ (λx, y.x) e1 e2 −−−−→ e1 Kein seq: In Haskell ist seq verfügbar, im Lambda-Kalkül nicht kodierbar. 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 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 3/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 4/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Kernsprachen für Haskell Die Kernsprache KFPT Im folgenden führen wir verschiedene Kernsprachen ein. Alle sind Erweiterungen des Lambda-Kalküls Erweiterung des Lambda-Kalküls um Datentypen (Konstruktoren) und case. Bezeichnungen: KFP. . . KFPT: T steht für getyptes case KFP = Kern einer Funktionalen Programmiersprache Beachte: KFPT ist nur ganz schwach getypt. EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 5/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 6/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Datentypen Syntax von KFPT Annahmen: Expr ::= V | λV.Expr | (Expr1 Expr2 ) | (ci Expr1 . . . Exprar(ci ) ) | (caseTypname Expr of {Pat1 → Expr1 ; . . . ; Patn → Exprn }) 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 . Datenkonstruktoren haben eine Stelligkeit ar(ci ) ∈ N0 (ar = arity“) ” Beispiele (Variable) (Abstraktion) (Anwendung) (Konstruktoranwendung) (case-Ausdruck) Pati ::= (ci V1 . . . Var (ci ) ) (Pattern für Konstruktor i) wobei die Variablen Vi alle verschieden sind. Typ Bool, Datenkonstruktoren: True und False, ar(True) = 0 = ar(False). Nebenbedingungen: Typ List, Datenkonstruktoren: Nil und Cons, ar(Nil) = 0 und ar(Cons) = 2. case mit Typ gekennzeichnet, Pati → Expri heißt case-Alternative Haskell-Schreibweise: [] für Nil und : (infix) für Cons case-Alternativen sind vollständig und disjunkt für den Typ: für jeden Konstruktor des Typs kommt genau eine Alternative vor. Beachte [a1 , a2 , . . . , an ] ist Abkürzung für a1 : (a2 : (. . . : (an : []))) EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 7/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 8/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiele (1) Beispiele (2) Erstes Element einer Liste (head): Paare: Typ Paar mit zweistelligem Konstruktor Paar Z.B. wird (True, False) durch (Paar True False) dargestellt. λxs.caseList xs of {Nil → ⊥; (Cons y ys) → y} Restliste ohne erstes Element (tail): Projektionen: λxs.caseList xs of {Nil → ⊥; (Cons y ys) → ys} fst snd Test, ob Liste leer ist (null): λxs.caseList xs of {Nil → True; (Cons y ys) → False} Analog: mehrstellige Tupel In Haskell sind Tupel bereits vorhanden (eingebaut), Schreibweise (a1 , . . . , an ) if e then s else t: In Haskell auch 0-stellige Tupel, keine 1-stelligen Tupel caseBool e of {True → s; False → t} EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß := λx.casePaar x of {(Paar a b) → a} := λx.casePaar x of {(Paar a b) → b} 9/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 10/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Haskell vs. KFPT: case-Ausdrücke (1) Haskell vs. KFPT: case-Ausdrücke (2) Vergleich mit Haskells case-Ausdrücken Syntax ähnlich: Haskell erlaubt überlappende Pattern. Z.B. ist Statt → in Haskell: -> Keine Typmarkierung am case case [] of {[] -> []; (x:(y:ys)) -> [y]} ein gültiger Haskell-Ausdruck Beispiel: Semikolon und Klammern kann man bei Einrückung weglassen: case [] of [] -> [] (x:(y:ys)) -> [y] KFPT: caseList xs of {(Nil → Nil; (y : ys) → y} Haskell: case xs of {[] -> []; (y:ys) -> y} In Haskell nicht notwendig alle Konstruktoren abzudecken Kann Laufzeitfehler geben: (case True of False -> False) *** Exception: Non-exhaustive patterns in case EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 11/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 12/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Haskell vs. KFPT: case-Ausdrücke (3) Freie und gebundene Variablen in KFPT Übersetzung von geschachtelten in einfache Pattern (für KFPT) case [] of {[] -> []; (x:(y:ys)) -> [y]} wird übersetzt in: Zusätzlich zum Lambda-Kalkül: In case-Alternative caseList Nil of {Nil → Nil; (Cons x z) → caseList z of {Nil → ⊥; (Cons y ys) → (Cons y Nil) } } (ci x1 . . . xar(ci ) ) → s sind die Variablen x1 , . . . , xar(ci ) in s gebunden. 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) EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 13/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 14/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Freie Variablen Gebundene 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 }) EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 15/54 =∅ = 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) ) EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 16/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel Notationen s := ((λx.caseList x of {Nil → x; Cons x xs → λu.(x λx.(x u))) x)} FV (s) = {x} und BV (s) = {x, u} Wie im Lambda-Kalkül (mit angepasster FV , BV Definition) Offene und geschlossene Ausdrücke Alpha-äquivalenter Ausdruck: α-Umbenennung Distinct Variable Convention 0 s := ((λx1 .caseList x1 of {Nil → x1 ; Cons x2 xs → λu.(x2 λx3 .(x3 u))) x)} FV (s0 ) = {x} und BV (s0 ) = {x1 , x2 , x3 , u} EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 17/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 18/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Operationale Semantik Beispiel 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 ) = ∅) (λx.casePaar x of {(Paar a b) → a}) (Paar True False) β − → Definition Die Reduktionsregeln (β) und (case) sind in KFPT definiert als: (β) casePaar (Paar True False) of {(Paar a b) → a} case −−→ True (λ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 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 19/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 20/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Kontexte Normalordnungsreduktion Definition Reduktionskontexte R in KFPT werden durch die folgende Grammatik erzeugt: 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 }) β 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]. EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 21/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 22/54 Beispiele Definition Wenn s unmittelbar zu t reduziert, dann ist R[s] → R[t] für jeden Reduktionskontext R eine Normalordnungsreduktion. no,β (λx.x) ((λy.y) (λz.z)) → (λy.y) (λz.z) ist eine Normalordnungsreduktion. (λx.x) ((λy.y) (λz.z)) → (λx.x) (λz.z) ist keine Normalordnungsreduktion no,case Notation: −→, bzw. auch −−−→ und −−−−→. no −−−→ transitive Hülle von −→ no,∗ EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Normalordnungsreduktion (2) no,+ Redexsuche mit ∗ Neue Regel: • (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) Beispiel: ((caseBool s of {True → (λx, y.x); False → (λx, y.y)}) Nil)? Redex = Reducible expression no R ::= [·] | (R Expr) | (caseT yp R of Alts) no −−→ reflexiv-transitive Hülle von −→ EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 23/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 24/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Normalformen Terminierung bzw. Konvergenz Ein KFPT-Ausdruck s ist eine Normalform (NF = normal form): s enthält keine (β)- oder (case)-Redexe 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 schwache Kopfnormalform (WHNF = weak head normal form): s ist eine FWHNF oder eine CWHNF. 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). EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 25/54 Definition Ein KFPT-Ausdruck s konvergiert (oder terminiert, notiert als s ⇓) genau dann, wenn: no,∗ s ⇓ ⇐⇒ ∃ WHNF t : s −−→ t Falls s nicht konvergiert, so sagen wir s divergiert und notieren dies mit s ⇑. Sprechweisen: Wir sagen s hat eine WHNF (bzw. FWHNF, CWHNF), no,∗ wenn s zu einer WHNF (bzw. FWHNF, CWHNF) mit −−→ reduziert werden kann. EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 26/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Dynamische Typisierung Beispiele Normalordnungsreduktion stoppt ohne WHNF: Folgende Fälle Eine freie Variable wurde gefunden (Ausdruck von der Form R[x]), oder Ein dynamischer Typfehler tritt auf. caseList True of {Nil → Nil; (Cons x xs) → xs} ist direkt dynamisch ungetypt Definition (Dynamische Typregeln für KFPT) (λx.caseList x of {Nil → Nil; (Cons x xs) → xs}) True ist dynamisch ungetypt Ein KFPT-Ausdruck s direkt dynamisch ungetypt, falls: (Cons True Nil) (λx.x) ist direkt dynamisch ungetypt s = R[caseT (c s1 . . . sn ) of Alts] und c ist nicht vom Typ T (caseBool x of {True → True; False → False}) ist nicht (direkt) dynamisch ungetypt s = R[caseT λx.t of Alts]. (λx.caseBool x of {True → True; False → False}) (λy.y) ist dynamisch ungetypt s = R[(c s1 . . . sar(c) ) t] s ist dynamisch ungetypt ⇐⇒ no,∗ ∃t : s −−→ t ∧ t ist direkt dynamisch ungetypt EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 27/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 28/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Dynamische Typisierung (2) Markierungsalgorithmus zur NO-Redex-Suche Für Ausdruck s starte mit s? , Verschieberegeln: (s t)? ⇒ (s? t) (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) Satz Ein geschlossener KFPT-Ausdruck s ist irreduzibel (bzgl. der Normalordnung) genau dann, wenn eine der folgenden Bedingungen auf ihn zutrifft: Fälle danach: Markierung ist an einer Abstraktion; Fälle: (λx.s0 )? , dann FWHNF C[((λx.s0 )? s00 )], dann reduziere die Applikation mit β C[caseT (λx.s0 )? . . .)], dann direkt dynamisch ungetypt Entweder ist s eine WHNF, oder Markierung ist an einer Konstruktorapplikation s ist direkt dynamisch ungetypt. (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 Markierung ist an einer Variablen: Keine Reduktion möglich EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 29/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Darstellung von Ausdrücken als Termgraphen 0 1 caseList y of { A True)) (λu, v.v)) (Cons (λw.w) Nil))? (((λx.λy.(@ Nil → Nil; (Cons z zs) → (x z)} −−−→ no,β −−−→ Knoten für je ein syntaktisches Konstrukt des Ausdrucks Variablen = ein Blatt 0 1 caseList y of { A True)) (Cons (λw.w) Nil))? ((λy.(@ Nil → Nil; (Cons z zs) → ((λu, v.v) z)} Abstraktionen λx.s 0 1 caseList (Cons (λw.w) Nil) of { A True)? (@ Nil → Nil; (Cons z zs) → ((λu, v.v) z)} no,case x Applikationen (s t) no,β no,β −−−→ s ((λv.v) True)? λ? wobei s Baum für s ?? ?? ?? s @> ? −−−−−→ (((λu, v.v) (λw.w)) True) −−−→ 30/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiel no,β EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß wobei s , t Bäume für s und t >> >> >> t True EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 31/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 32/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Darstellung von Ausdrücken als Termgraphen (2) Beispiel Konstruktoranwendungen n-stellig: (c s1 . . . sn ) wobei si die Bäume für si mm c QBBQQ m | BBQQQQ mmm || BB QQQQ mmm ||| m BB QQQ m m | m BB QQ( || m v mm | ~ ... ... ... s1 sn λx.λy.caseList (Cons x Nil) of { (Cons z zs) → False; True (Cons True Nil) Nil → True} hhhh @ SSSS case-Ausdrücke: n + 1 Kinder, caseT yp s of {Alt1 ; . . . ; Altn } caseT yp GGRRR kt GG RRRR kkktkttt k GG k k k t k GG RRRRRR k t t kk GG RRR k t z k k ) G# u kk k ... ... s Alt1 Altn →@ case-Alternative P at → t yy yy y y y| y @@ @@ @@ @ x t P at EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 33/54 False Nil True EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 34/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Normalordnungsreduktion: Eigenschaften Rekursive Superkombinatoren: KFPTS 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. Nächste Erweiterung: KFPT zu KFPTS S“ steht für Superkombinatoren ” Superkombinatoren sind Namen (Konstanten) für Funktionen Theorem (Standardisierung für KFPT) Superkombinatoren dürfen auch rekursive Funktionen sein ∗ 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. Annahme: Es gibt eine Menge von Superkombinatornamen SK. Beispiel: Superkombinator length s@ @ no,∗ ~~ ~ @ ~ ~ @ ~ ~ _ o _ _ _ _ _ t t0 ∗ length xs =caseList xs of { Nil → 0; (Cons y ys) → (1 + length ys)} ∗ EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß Nil Cons OO u OOO ' u z uu z zs NO-Redex-Suche: immer links, bis Abstraktion, Konstruktoranwendung Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen WHNF h SSS hhhh S) thhhh ConsGG O i @ i O i O i u OOO GG iiii ' zuuu # tiiii True True Nil λ G G GGG ww # {www x w λ NNNNN w w N& {ww y caseList XXX f f XXXXXX f f ffff XXXXXX rfffff ,→ → ConsH O OOO v JJJJ pp HH | v p v O | p v # wp ' { $ }| WHNF 35/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 36/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS: Syntax KFPTS:Syntax (2) Zu jedem Superkombinator gibt es eine Superkombinatordefinition: Expr ::= | | | V | λV.Expr | (Expr1 Expr2 ) (ci Expr1 . . . Exprar(ci ) ) (caseTyp Expr of {Pat1 → Expr1 ; . . . ; Patn → Exprn }) SK wobei SK ∈ SK SK V1 . . . Vn = Expr dabei Vi paarweise verschiedene Variablen; Expr ein KFPTS-Ausdruck; Pati ::= (ci V1 . . . Var (ci ) ) wobei die Variablen Vi alle verschieden sind. FV (Expr) ⊆ {V1 , . . . , Vn }; ar(SK) = n ≥ 0: Stelligkeit des Superkombinators (n = 0 ist möglich). EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 37/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 38/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS: Syntax (3) KFPTS: Operationale Semantik Reduktionskontexte: R ::= [·] | (R Expr) | caseT yp R of Alts Ein KFPTS-Programm besteht aus: Reduktionsregeln (β), (case) und (SK-β): Einer Menge von Typen und Konstruktoren, einer Menge von Superkombinator-Definitionen, und aus einem KFPTS-Ausdruck s. (Diesen könnte man auch als Superkombinator main mit Definition main = s definieren.) (β) (λ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 , . . . , s2 /xn ], wenn SK x1 . . . xn = e die Definition von SK ist Dabei müssen alle in s verwendeten Superkombinatoren auch definiert sein. Normalordnungsreduktion: s → t mit (β)-, (case)- oder (SK-β) no R[s] −→ R[t] EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 39/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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. EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 41/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 43/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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} EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 45/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 46/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen 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). EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 47/54 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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 die Typen für Typvariablen ersetzt. s :: T and :: Bool → Bool → Bool, True :: Bool 0 (and True) :: Bool → Bool (and True False) :: Bool Für case-Ausdrücke: s :: T1 , , False :: Bool ∀i : P ati :: T1 , ∀i : ti :: T2 (caseT s of {P at1 → t1 ; . . . ; P atn → tn ) :: T2 } EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 49/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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] , map :: (a → b) → [a] → [b] Nil :: [a] Nil :: [Bool] , Nil :: [a] Nil :: [Bool] caseBool True of {True → (Cons True Nil); False → Nil} :: [Bool] EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 51/54 map :: (Bool → Bool) → [Bool] → [Bool] , not :: Bool → Bool (map not) :: [Bool] → [Bool] EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 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 EFP – (04) Die KFP-Kernsprachen – WS 2011/12 – M. Schmidt-Schauß 54/54