Funktionale Kernsprachen

Werbung
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
Herunterladen