The gradual typing approach to mixing static and dynamic...
Transcript of The gradual typing approach to mixing static and dynamic...
The gradual typing approach tomixing static and dynamic typing
Jeremy G. Siek
University of Colorado =⇒ Indiana University
TFP 2013 at Provo, Utah, May 2013
1 / 38
The Goals of Gradual Typing
I Enjoy the benefits of static & dynamic typing in differentparts of the same program.
I Provide seamless interoperability between the static &dynamic parts.
Static Typing Dynamic Typing
Reliability & Efficiency Productivity
2 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
3 / 38
How can Static and Dynamic Coexist?1
def abs(n: int) int:return -n if n<0 else n
def dist(x, y):return abs(x - y)
1Gradual Typing for Functional Languages, Siek and Taha, SFP 2006.4 / 38
How can Static and Dynamic Coexist?2
def abs(n: int) int:return -n if n<0 else n
def dist(x : ?, y : ?) ?:return abs(x - y)
? ∼ int
Consistency:
T ∼ ? ? ∼ T
int ∼ int str ∼ str
T1 ∼ T3 T2 ∼ T4
T1 → T2 ∼ T3 → T4
Type rule for application:
Γ ` e1 : T1 → T3Γ ` e2 : T2 T1 ∼ T2
Γ ` e1 e2 : T3
2Gradual Typing for Functional Languages, Siek and Taha, SFP 2006.5 / 38
Properly Catch Static Errors
def abs(n: int) int:return -n if n<0 else n
x : str = input_string()...abs(x)
str 6∼ int
Consistency:
T ∼ ? ? ∼ T
int ∼ int str ∼ str
T1 ∼ T3 T2 ∼ T4
T1 → T2 ∼ T3 → T4
6 / 38
Compiler Performs Cast Insertion
def abs(n: int) int:return -n if n<0 else n
def dist(x : ?, y : ?) ?:return abs(x - y : ?⇒ int) : int⇒ ?
dist(7 : int⇒ ?, 3 : int⇒ ?)
The dynamic semantics specifies the behavior of casts, e.g.,
(7 : int⇒ ?) : ?⇒ int −→ 7(7 : int⇒ ?) : ?⇒ str −→ error
7 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
8 / 38
The Prehistory of Gradual Typing
Lisp, early 1980’s types as optimization hintsAbadi et al., 1991 defined a “dynamic” type
with explicit injection andprojection terms.
Cartwright & Fagan, 1991 soft typing: staticanalysis of dynamic programs
Henglein, 1992 expressed “dynamic” casts usingan algebra of coercions.
Thatte, 1994 introduced implicit casts based onsubtyping, which didn’t quite work.
Findler & Felleisen, 2002 designed contracts forhigher-order functions.
9 / 38
History of Gradual Typing (Abbreviated)*Siek & Taha, 2006 implicit casts, consistencyHerman et al., 2006 space-efficient casts*Siek & Taha, 2007 gradual typing & objectsAdobe, 2006 ActionScript becomes gradualSam TH & Felleisen, 2008 Typed SchemeWadler & Findler, 2009 the Blame Theorem*Garcia et. al, 2009 space-efficient blameLarry Wall, 2009 Perl 6 becomes gradualBierman et al, 2010 C# becomes gradual*Ahmed, et al., 2011 gradual typing & genericsHejlsberg, 2012 Microsoft releases TypeScript*Siek et al., 2012 gradual typing & mutable state
10 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
11 / 38
Higher-Order Functions are Hard
def deriv(d: float, f: float→float) float:return lambda(x:float): (f(x+d)-f(x-d)) / (2.0*d)
1 def g(y):2 if y > 0:3 return y**3 - y - 14 else:5 return "yikes"67 deriv(0.01, g)(3.0)8 deriv(0.01, g)(-3.0)
12 / 38
Higher-Order Functions and Blame
def deriv(d: float, f: float→float) float:return lambda(x:float): (f(x+d)-f(x-d)) / (2.0*d)
1 def g(y):2 if y > 0:3 return y**3 - y - 14 else:5 return "yikes"67 deriv(0.01, g)(3.0)8 deriv(0.01, g)(-3.0)
Casting a function creates a“wrapper”:
g : ?→ ?⇒8 float→ float−→
λp : float.g (p : float⇒8 ?)
: ?⇒8 float
”yikes” : str⇒ ?⇒8 float −→ blame 8
13 / 38
Is Gradual Typing Unsound? 3 4
“adding type annotations at random places is unsound”— Matthias Felleisen, PLT Mailing List, June 10, 2008.
Too weak:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ error.
Too strong:If ` e : T , then either e diverges or e −→∗ v and ` v : T .
Just right:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ blame ` where e = C[e′ : T1 ⇒` T2] and T1 6<: T2.
3Well-typed Program’s Can’t be Blamed, Wadler & Findler, ESOP 20094Exploring the Design Space of H.O. Casts, Siek et al., ESOP 2009
14 / 38
Is Gradual Typing Unsound? 3 4
“adding type annotations at random places is unsound”— Matthias Felleisen, PLT Mailing List, June 10, 2008.
Too weak:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ error.
Too strong:If ` e : T , then either e diverges or e −→∗ v and ` v : T .
Just right:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ blame ` where e = C[e′ : T1 ⇒` T2] and T1 6<: T2.
3Well-typed Program’s Can’t be Blamed, Wadler & Findler, ESOP 20094Exploring the Design Space of H.O. Casts, Siek et al., ESOP 2009
14 / 38
Is Gradual Typing Unsound? 3 4
“adding type annotations at random places is unsound”— Matthias Felleisen, PLT Mailing List, June 10, 2008.
Too weak:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ error.
Too strong:If ` e : T , then either e diverges or e −→∗ v and ` v : T .
Just right:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ blame ` where e = C[e′ : T1 ⇒` T2] and T1 6<: T2.
3Well-typed Program’s Can’t be Blamed, Wadler & Findler, ESOP 20094Exploring the Design Space of H.O. Casts, Siek et al., ESOP 2009
14 / 38
Is Gradual Typing Unsound? 3 4
“adding type annotations at random places is unsound”— Matthias Felleisen, PLT Mailing List, June 10, 2008.
Too weak:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ error.
Too strong:If ` e : T , then either e diverges or e −→∗ v and ` v : T .
Just right:If ` e : T , then either e diverges, e −→∗ v and ` v : T , ore −→∗ blame ` where e = C[e′ : T1 ⇒` T2] and T1 6<: T2.
3Well-typed Program’s Can’t be Blamed, Wadler & Findler, ESOP 20094Exploring the Design Space of H.O. Casts, Siek et al., ESOP 2009
14 / 38
Blame and Subtyping
Wadler & Finder, 2009:
int <: int ? <: ? int <: ?
T <: ??→ T <: ?
T3 <: T1 T2 <: T4
T1→T2 <: T3→T4
Siek, Garcia, & Taha, 2009:
int <: int T <: ?
T3 <: T1 T2 <: T4
T1→T2 <: T3→T4
15 / 38
But Wrappers are Not Space Efficient5
def even(n: int, k: ?→ Bool) Bool:if n == 0:return k(True)
else:return odd(n - 1, k)
def odd(n: int, k: Bool→Bool) Bool:if n == 0:return k(False)
else:return even(n - 1, k)
5Space-Efficient Gradual Typing. Herman, et al., TFP 200616 / 38
Toward Efficient Casts: Reified Wrappers
Regular wrappers:
v ::= . . . | λx : T . e
v : T1→T2 ⇒ T3→T4 −→ λx : T3. (v (x : T3 ⇒ T1)) : T2 ⇒ T4
⇓
Reified wrappers:
v ::= . . . | λx : T . e | v : T1→T2 ⇒ T3→T4
(v1 : T1→T2 ⇒ T3→T4) v2 −→ (v1 (v2 : T3 ⇒ T1)) : T2 ⇒ T4
17 / 38
Compressing a Sequence of Casts6
v : ? → ?⇒ ? → str→ ?⇒ int→ ? → ?⇒ ? → ? → int
v : ? → ?⇒ int→ str→ int⇒ ? → ? → int
Define an information ordering:
? v T int v int str v strT1 v T3 T2 v T4
T1 → T2 v T3 → T4
Take the least upper bound to ob-tain a “triple”:
e : T1 ⇒ T2 ⇒ · · · ⇒ Tn−1 ⇒ Tn
e : T1 ⇒ t{T2, . . . ,Tn−1} ⇒ Tn6Threesomes, with and without blame. Siek & Wadler, POPL 2010.
18 / 38
Space Efficiency
Notation: |e| erases the casts from e.
Theorem (Space Efficiency)For any program e there is a constant factor c such that ife 7−→∗ e′, then size(e′) ≤ c · size(|e′|).
19 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
20 / 38
Gradual Typing and Subtyping
At the heart of most OO languages is a subsumption rule:
Γ ` e : T1 T1 <: T2
Γ ` e : T2
Thatte’s early attempt at gradual typing didn’t use consistencybut instead put the dynamic type at the top and bottom of thesubtyping relation.
T <: ? ? <: T
21 / 38
The Problem with Subtyping
Subtyping is transitive, so we have:
str <: ? ? <: intstr <: int
In general, for any types T1 and T2 we have T1 <: T2.
So the type checker accepts all programs!(Even ones that get stuck.)
22 / 38
Consistency and Subtyping are Orthogonal7
Let subtyping deal with object types:
[li : Tii∈1..n+m] <: [li : Ti
i∈1..n] ? <: ?
Let consistency deal with the dynamic type:
T ∼ ? ? ∼ T
Include the subsumption rule
Γ ` e : T1 T1 <: T2
Γ ` e : T2
and use consistency instead of equality:
Γ ` e1 : T1 → T3 Γ ` e2 : T2 T1 ∼ T2
Γ ` e1 e2 : T37Gradual Typing for Objects, Siek and Taha, ECOOP 2007
23 / 38
An Algorithmic Type System
The usual trick is to remove the subsumption rule and usesubtyping in place of equality.
Γ ` e1 : T1 → T3 Γ ` e2 : T2 T2 <: T1
Γ ` e1 e2 : T3
but for gradual typing, this would look like
Γ ` e1 : T1 → T3 Γ ` e2 : T2 T2 <: T ′1 T ′1 ∼ T1
Γ ` e1 e2 : T3
which is not syntax directed. We need a relation thatcomposes the two:
Γ ` e1 : T1 → T3 Γ ` e2 : T2 T2 . T1
Γ ` e1 e2 : T3
24 / 38
Consistent-Subtyping
T . ? ? . T
int . int str . str
T3 . T1 T2 . T4
T1 → T2 . T3 → T4
Ti . T ′i ∀i ∈ 1..n[li : Ti
i∈1..n+m] . [li : T ′i i∈1..n]
(This is a more direct definition than the one I gave inGradual Typing for Objects.)
25 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
26 / 38
Gradual Typing & Polymorphism
Review of System F:
T ::= . . . | ∀X.Te ::= . . . | ΛX. e | e[T ]
(ΛX. e)[T ] −→ e[X:=T ]
Γ,X ` e : TΓ ` ΛX. e : ∀X.T
Γ ` e : ∀X.T1
Γ ` e[T2] : T1[X:=T2]
27 / 38
Parametric Polymorphism (Generics)
Ahmed, Findler, and Wadler proposed a design at STOP 2009.
Their goals:I Seamless interoperability.
v : (∀X. S)⇒ T −→ v[?] : S[X:=?]⇒ Tv : S ⇒ (∀X.T ) −→ ΛX. (v : S ⇒ T )
I Retain relational parametricity (i.e., theorems for free).I Provide a natural subtyping relation and blame theorem.
I helped refine the design for the POPL 2011 paper.
28 / 38
Challenges to Parametricity
K? = (λx: ? .λy: ? .x) : ?→ ?→?⇒ ?
Consider two casts:
K? : ?⇒m ∀X.∀Y .X → Y → XK? : ?⇒` ∀X.∀Y .X → Y → Y
The second cast should lead to a cast failure.But a naive semantics lets it go through.
(K? : ?⇒` ∀X.∀Y .X → Y → Y )[int][int] 2 3
−→∗ (K? : ?⇒` int→ int→ int) 2 3
−→∗ 2 : int⇒ ?⇒` int−→ 2
29 / 38
Enforcement of Parametricity
(K? : ?⇒` ∀X.∀Y .X → Y → X)[int][int] 2 3
−→∗ (νX:=int.νY :=int.K? : ?⇒` X → Y → X) 2 3
−→∗ (νX:=int.νY :=int. 2 : X ⇒ ?⇒` X)
−→ 2
(K? : ?⇒` ∀X.∀Y .X → Y → Y )[int][int] 2 3
−→∗ (νX:=int.νY :=int.K? : ?⇒` X → Y → Y ) 2 3
−→∗ (νX:=int.νY :=int. 2 : X ⇒ ?⇒` Y )
−→ blame `
This mechanism “should” work, but the parametricitytheorem is an open problem.
30 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
31 / 38
Gradual Typing & Mutable State
Consider ML-style references
T ::= . . . | refTe ::= . . . | ref e | e := e | !e
with a permissive rule for consistency of reference types:
T1 ∼ T2
refT1 ∼ refT2
32 / 38
The Standard Semantics Incurs Overhead
The Herman TFP 2006 semantics induces overhead, even instatically-typed regions of code.
a ∈ Nv ::= . . . | a | v : refT1 ⇒ refT2
ref v | µ 7−→ a | µ(a := v) if a /∈ dom(µ)
!v | µ 7−→
{µ(a) | µ if v = a(!v′) : T1 ⇒ T2 | µ if v = v′ : refT1 ⇒ refT2
v1 := v2 | µ 7−→
{v2 | µ(a := v2) if v1 = av′1 := (v2:T2⇒T1) | µ if v1 = v′1 : refT1⇒refT2
33 / 38
Monotonic References
e ::= . . . | ref e | e := e | !e | e := e@T | !e@Tv ::= . . . | a
let r1 = ref (42 : int ⇒ ?) inlet r2 = r1 : ref ?⇒ ref int in(!r1@?, !r2)
ref ?
(((42 : int⇒ ?, ?)
ref ?
%%
+3 ref int
��(42, int)
34 / 38
Standard vs. Monotonic
1 let r1 = ref (1 : int ⇒ ?) in2 let r2 = r1 : ref ?⇒ ref int in3 let r3 = r1 : ref ?⇒ ref bool in4 let x = !r2 in5 r3 := true;6 let y = !r3 in7 (x,y)
7−→∗ (1, true) (standard)7−→∗ blame 3 (monotonic)
35 / 38
e | µ −→ e′ | ∆ Monotonic ReferencesrefT v | µ −→ a | a := (v,T ) if a /∈ dom(µ)
!a | µ −→ µ(a)1 | εa := v | µ −→ a | a := (v, µ(a)2)
a : refT1 ⇒ refT2 | µ −→ error | ε if T2 6∼ µ(a)2
a : refT1 ⇒ refT2 | µ −→ a | ε if T2 v µ(a)2
a : refT1 ⇒ refT2 | µ −→ a | a := (e, µ(a)2 t T2)
if T2 6v µ(a)2, e = µ(a)1 : µ(a)2 ⇒ µ(a)2 t T2
!a@T | µ −→ (µ(a)1 : µ(a)2 ⇒ T ) | εa := v@T | µ −→ a | a := (v : T ⇒ µ(a)2, µ(a)2)
e | µ 7−→ e′ | µ′
e | µ −→ e′ | ∆e | µ 7−→ e′ | ∆(µ)
µ(a)=(e1,T ) e1 | µ −→ e′1 | ∆e | µ 7−→ e | ∆(µ(a := (e′1,T )))
36 / 38
Overview
Gradual Typing:I BasicsI HistoryI FunctionsI ObjectsI GenericsI Mutable StateI The Future
37 / 38
The Future
I Gradually-typed Python (Michael Vitousek)I Monotonic references with blame (some ideas, not easy)I Monotonic objects (draft)I “Putting it all together”, e.g. can we maintain space
efficiency with polymorphic blame? (no idea)I Parametricity for the Polymorphic Blame Calculus
(Amal Ahmed is part way there)I Compiling and optimizing gradually-typed programs
(e.g. Rastogi, Chaudhuri, and Hosmer, POPL 2012)
Questions?
38 / 38