Die KFP-Kernsprachen

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