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 Dr. David Sabel WS 2010/11 Stand der Folien: 8. November 2010 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 und Daten und Funktionen nicht unterscheidbar EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 3/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 a la Schmidt-Schauß: 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 2010/11 – D. Sabel 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 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 2010/11 – D. Sabel EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 7/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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): := λx.casePaar x of {(Paar a b) → a} := λx.casePaar x of {(Paar a b) → b} Analog: mehrstellige Tupel λxs.caseList xs of {Nil → True; (Cons y ys) → False} 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 2010/11 – D. Sabel 9/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 2010/11 – D. Sabel 11/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 2010/11 – D. Sabel 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 2010/11 – D. Sabel EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 2010/11 – D. Sabel 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 2010/11 – D. Sabel 17/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 s[t1 /x1 , . . . , tn /xn ] parallele Ersetzung von x1 , . . . , xn durch t1 , . . . , tn (λ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 2010/11 – D. Sabel 19/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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]. R ::= [·] | (R Expr) | caseT yp R of Alts Definition Wenn s unmittelbar zu t reduziert, dann ist R[s] → R[t] für jeden Reduktionskontext R eine Normalordnungsreduktion. no no,β no,case Notation: −→, bzw. auch −−−→ und −−−−→. Redex = Reducible expression no,+ no −−−→ transitive Hülle von −→ no,∗ no −−→ reflexiv-transitive Hülle von −→ EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 21/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 ist WHNF (λx.x) ((λy.y) (λz.z)) → (λy.y) (λz.z) ist eine Normalordnungsreduktion. Kopfnormalform (HNF = head normal form): s ist Konstruktoranwendung oder Abstraktion λx1 , . . . xn .s0 ist, wobei s0 entweder Variable oder (c s1 . . . sar(c) ) oder (x s0 ) ist (λx.x) ((λy.y) (λz.z)) → (λx.x) (λz.z) ist keine Normalordnungsreduktion 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 2010/11 – D. Sabel 23/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 wurde gefunden (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] EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 26/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Beispiele Dynamische Typisierung (2) caseList True of {Nil → Nil; (Cons x xs) → xs} ist direkt dynamisch ungetypt Satz Ein geschlossener KFPT-Ausdruck s ist irreduzibel (bzgl. der Normalordnung) genau dann, wenn eine der folgenden Bedingungen auf ihn zutrifft: (λx.caseList x of {Nil → Nil; (Cons x xs) → xs}) True ist dynamisch ungetypt (Cons True Nil) (λx.x) ist direkt dynamisch ungetypt (caseBool x of {True → True; False → False}) ist nicht (direkt) dynamisch ungetypt Entweder ist s eine WHNF, oder s ist direkt dynamisch ungetypt. (λx.caseBool x of {True → True; False → False}) (λy.y) ist dynamisch ungetypt EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 27/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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: 0 1 caseList y of { A True)) (λu, v.v)) (Cons (λw.w) Nil))? (((λx.λy.(@ Nil → Nil; (Cons z zs) → (x z)} (s t)? ⇒ (s? t) (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) 0 Fälle danach: Markierung ist an einer Abstraktion: 1 caseList y of { A True)) (Cons (λw.w) Nil))? ((λy.(@ Nil → Nil; (Cons z zs) → ((λu, v.v) z)} no,β −−−→ Wenn kein Kontext herum, dann FWHNF Wenn Applikation herum, dann reduziere die Applikation mit β Wenn case-herum, dann direkt dynamisch ungetypt 0 1 caseList (Cons (λw.w) Nil) of { A True)? (@ Nil → Nil; (Cons z zs) → ((λu, v.v) z)} no,β −−−→ Markierung ist an einer Konstruktorapplikation Wenn kein Kontext herum, dann CWHNF Wenn Applikation herum, dann direkt dynamisch ungetypt Wenn caseT -herum: Wenn T zum Typ des Konstruktors passt, dann reduziere mit (case), sonst direkt dynamisch ungetypt no,case −−−−−→ (((λu, v.v) (λw.w)) True)? no,β −−−→ Markierung ist an einer Variablen: Keine Reduktion möglich EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel no,β −−−→ 29/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen λ? Applikationen (s t) BBQQQQ mmm || BB QQQQ mmm ||| m m BB QQQ mm || m BB | QQ( m | mv m | ~ ... ... ... s1 sn wobei s Baum für s ?? ?? ?? case-Ausdrücke: n + 1 Kinder, caseT yp s of {Alt1 ; . . . ; Altn } caseT yp s @> s wobei s , t Bäume für s und t >> >> >> s kkktt kkkktttt k k k k t ztt kkkk u kkk k Alt1 ... GGRRR GG RRRR GG GG RRRRRR GG RRR ) G# ... yy yy y y y| y t 31/54 Altn →@ case-Alternative P at → t P at EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 30/54 Konstruktoranwendungen n-stellig: (c s1 . . . sn ) wobei si die Bäume für si mm c QBBQQ Variablen = ein Blatt x EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel Darstellung von Ausdrücken als Termgraphen (2) Knoten für je ein syntaktisches Konstrukt des Ausdrucks True Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Darstellung von Ausdrücken als Termgraphen Abstraktionen λx.s ((λv.v) True)? EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel @@ @@ @@ @ 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} hhhh @ SSSS x 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 ' { $ }| Nil Cons OO u OOO ' uz uu z zs False Nil Theorem (Standardisierung) ∗ 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. s@ @ no,∗ ~~ ~ @ ~~ @ ~ ~ _ o _ _ _ _ _ t t0 ∗ ∗ True WHNF NO-Redex-Suche: immer links, bis Abstraktion, Konstruktoranwendung EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 33/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel WHNF 34/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Rekursive Superkombinatoren: KFPTS KFPTS: Syntax Nächste Erweiterung: 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. 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. Beispiel: Superkombinator length length xs =caseList xs of { Nil → 0; (Cons y ys) → (1 + length ys)} EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 35/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 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 ist. FV (Expr) ⊆ {V1 , . . . , Vn } Dabei müssen alle in s verwendeten Superkombinatoren auch definiert sein. ar(SK) = n Stelligkeit des Superkombinators. EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 37/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 38/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen KFPTS: Operationale Semantik KFPTS: WHNFs und Dynamische Typisierung Reduktionskontexte: R ::= [·] | (R Expr) | caseT yp R of Alts WHNFs WHNF = CWHNF oder FWHNF Reduktionsregeln (β), (case) und (SK-β): CWHNF = Konstruktoranwendung (c s1 . . . sar(c) ) (β) (λ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) ] FWHNF = Abstraktion oder SK s1 . . . sm mit ar(SK) > m (SK-β) (SK s1 . . . sn ) → e[s1 /x1 , . . . , s2 /xn ], wenn SK x1 . . . xn = e die Definition von SK ist 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)] Neue Regel: R[caseT SK s1 . . . sm of Alts] ist direkt dynamisch ungetypt falls ar(SK) > m. Normalordnungsreduktion: s → t mit (β)-, (case)- oder (SK-β) no R[s] −→ R[t] EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 39/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 40/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Markierungsalgorithmus Beispiel 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} Markierung funktioniert genauso wie in KFPTS: (s t)? ⇒ (s? t) (caseT yp s of Alts)? ⇒ (caseT yp s? of Alts) Auswertung von map not (Cons True (Cons False Nil)): Neue Fälle: Ein Superkombinator ist mit ? markiert: map not (Cons True (Cons False Nil)) Genügend Argumente vorhanden: Reduziere mit (SK-β) Zu wenig Argumente und kein Kontext sonst: WHNF Zu wenig Argumente und ein case herum: direkt dynamisch ungetypt. 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)) WHNF erreicht! Beachte: Im Interpreter wird nur aufgrund des Anzeigens weiter ausgewertet EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 41/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Vorteil von seq seq kann Platz sparen, Beispiel Fakultät: Linear Platzbedarf: In Haskell gibt es seq: ½ fak 0 = 1 fak x = x*(fak (x-1)) b falls a ⇓ ⊥ falls a ⇑ Endrekursiv aber immer noch linearer Platzbedarf Operational: Werte erst a aus, dann b fak x = fakER x 1 where fakER 0 y = y fakER x y = fakER (x-1) (x*y) Analog: strict (in Haskell infix als $! geschrieben) strict f macht f strict im ersten Argument, d.h. strict f wertet erst das Argument aus, dann erfolgt die Definitionseinsetzung. Endrekursiv aber konstanter Platzbedarf (iterativ): seq und strict sind austauschbar: f $! x seq a b = = fak x = fakER x 1 where fakER 0 y = y fakER x y = let x’ = x-1 y’ = x*y in seq x’ (seq y’ (fakER x’ y’)) seq x (f x) (\x -> b) $! a EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 42/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Erweiterung um seq und strict (seq a b) = EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 43/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 44/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen ...+seq Sprachen Bemerkung: Die Sprache KFP 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 seq ist in KFPT, KFPTS nicht kodierbar! Wir bezeichnen mit KFPT+seq die Erweiterung von KFPT um seq KFPTS+seq die Erweiterung von KFPTS um seq Pati Wir verzichten auf die formale Definition! Man benötigt u.a. die Reduktionsregel: ::= (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 seq v t → t, wenn v WHNF In KFP ist seq kodierbar: seq a b := case a of {P at1 → b; . . . ; P atn → b; lambda → b} EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 45/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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, Schematische Typen 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 2010/11 – D. Sabel 47/54 EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 2010/11 – D. Sabel 49/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 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 2010/11 – D. Sabel 51/54 map :: (Bool → Bool) → [Bool] → [Bool] , not :: Bool → Bool (map not) :: [Bool] → [Bool] EFP – (04) Die KFP-Kernsprachen – WS 2010/11 – D. Sabel 52/54 Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Einleitung KFPT KFPTS Erweiterung um seq Polymorphe Typen Ausblick Übersicht Kernsprache KFP KFPT KFPTS 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. 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 2010/11 – D. Sabel 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 2010/11 – D. Sabel 54/54