the gradual typing approach to mixing static and dynamic...

Post on 25-Jul-2020

8 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

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

top related