SLIDE 1
Well-typed programs can’t be blamed
Philip Wadler University of Edinburgh NII Shonan Meeting 26–30 May 2014
SLIDE 2 Publications
Well-typed programs can’t be blamed ESOP 2009
Threesomes, with and without blame POPL 2010
- Ahmed, Findler, Siek, and Wadler
Blame for all POPL 2011
Blame, coercions, and threesomes, precisely draft
SLIDE 3
SLIDE 4
A repeated theme
Henglein (1994): Coercions Findler and Felleisen (2002): Contracts Flanagan (2006): Hybrid types Siek and Taha (2006): Gradual types
SLIDE 5
A repeated theme
Dynamic in .Net C#, Visual Basic JavaScript TypeScript Dart Perl 6.0 Python Reticulated Python
SLIDE 6
Part I
From untyped to typed
SLIDE 7
An untyped program
⌈let x = 2 f = λy. y + 1 h = λg. g (g x) in h f⌉ − → ⌈4⌉
SLIDE 8
A typed program
let x = 2 f = λy : Int. y + 1 h = λg : Int → Int. g (g x) in h f − → 4 : Int
SLIDE 9 A partly typed program—narrowing
let x = 2 f = ⌈λy. y + 1⌉ : ⋆
p
⇒ Int → Int h = λg : Int → Int. g (g x) in h f − → 4 : Int
SLIDE 10 A partly typed program—narrowing
let x = 2 f = ⌈λy. false⌉ : ⋆
p
⇒ Int → Int h = λg : Int → Int. g (g x) in h f − → blame p Positive (covariant): blame the term contained in the cast
SLIDE 11 Another partly typed program—widening
let x = ⌈2⌉ f = (λy : Int. y + 1) : Int → Int
p
⇒ ⋆ h = ⌈λg. g (g x)⌉ in ⌈h f⌉ − → ⌈4⌉
SLIDE 12 Another partly typed program—widening
let x = ⌈true⌉ f = (λy : Int. y + 1) : Int → Int
p
⇒ ⋆ h = ⌈λg. g (g x)⌉ in ⌈h f⌉ − → blame ¯ p Negative (contravariant): blame the context containg the cast
SLIDE 13
Part II
Untyped and supertyped
SLIDE 14 Untyped = Uni-typed
⌈x⌉ = x ⌈k⌉ = k : A
p
⇒ ⋆ if ty(k) = A ⌈op( M)⌉ =
M⌉ : ⋆
⇒ A) : B
p
⇒ ⋆ if ty(op) = A → B ⌈λx. N⌉ = (λx : ⋆. ⌈N⌉) : ⋆ → ⋆ ⇒ ⋆ ⌈L M⌉ = (⌈L⌉ : ⋆
p
⇒ ⋆ → ⋆) ⌈M⌉ (slogan due to Dana Scott, repeated by Bob Harper)
SLIDE 15 Contracts
Nat = {x : Int | x ≥ 0} let x = 2 : Int
p
⇒ Nat f = (λy : Int. y + 1) : Int → Int
q
⇒ Nat → Nat h = λg : Nat → Nat. g (g x) in h f − → 4 : Nat
SLIDE 16
Part III
The Blame Calculus
SLIDE 17 Notation
It took us four years to find the right notation! A ⇒ Bp s B ⇐ Ap s s : A
p
⇒ B We want composition to be easy to read: B ⇒ Cq A ⇒ Bp s C ⇐ Bq B ⇐ Ap s s : A
p
⇒ B : B
q
⇒ C And there is a convenient abbreviation: s : A
p
⇒ B
q
⇒ C
SLIDE 18 Blame calculus: Compatibility
Γ ⊢ M : A A ≺ B Γ ⊢ (M : A
p
⇒ B) : B A ≺ ⋆ ⋆ ≺ A ι ≺ ι A′ ≺ A B ≺ B′ A → B ≺ A′ → B′
SLIDE 19 Reductions
Ground types G ::= ι | ⋆ → ⋆ (V : A→B
p
⇒ A′→B′) W − → (V (W : A′
p
⇒ A) : B
p
⇒ B′) V : ι
p
⇒ ι − → V V : A
p
⇒ ⋆ − → V : A
p
⇒ G ⇒ ⋆ if ⋆ = A ≺ G V : G ⇒ ⋆
p
⇒ A − →
V : G
p
⇒ A blame p if G ≺ A if G ≺ A
SLIDE 20 Blame
⌈2⌉ : ⋆
p
⇒ Int = 2 : Int ⇒ ⋆
p
⇒ Int − → 2 ⌈true⌉ : ⋆
p
⇒ Int = true : Bool ⇒ ⋆
p
⇒ Int − → blame p
SLIDE 21 The Blame Game—widening
((λy : Int. y + 1) : Int → Int
p
⇒ ⋆ → ⋆) ⌈2⌉ − → (λy : Int. y + 1) (⌈2⌉ : ⋆
p
⇒ Int) : Int
p
⇒ ⋆ − → ⌈3⌉
SLIDE 22 The Blame Game—widening
((λy : Int. y + 1) : Int → Int
p
⇒ ⋆ → ⋆) ⌈true⌉ − → (λy : Int. y + 1) (⌈true⌉ : ⋆
p
⇒ Int) : Int
p
⇒ ⋆ − → blame p Widening can give rise to negative blame, but never positive blame
SLIDE 23 The Blame Game—narrowing
((λy : ⋆. ⌈y + 1⌉) : ⋆ → ⋆
p
⇒ Int → Int) 2 − → (λy : ⋆. ⌈y + 1⌉) (2 : Int
p
⇒ ⋆) : ⋆
p
⇒ Int − → 3
SLIDE 24 The Blame Game—narrowing
((λy : ⋆. ⌈false⌉) : ⋆ → ⋆
p
⇒ Int → Int) 2 − → (λy : ⋆. ⌈false⌉) (2 : Int
p
⇒ ⋆) : ⋆
p
⇒ Int − → blame p Narrowing can give rise to positive blame, but never negative blame
SLIDE 25
Part IV
Subtyping <: <:+ <:− <:n
SLIDE 26
Subtype
⋆ <: ⋆ ι <: ι A <: G A <: ⋆ A′ <: A B <: B′ A → B <: A′ → B′ Example: Int <: Int Int <: ⋆ Int <: Int Int <: ⋆ ⋆ → Int <: Int → ⋆
SLIDE 27
Positive subtype—widening
A <:+ ⋆ ι <: ι A′ <:− A B <:+ B′ A → B <:+ A′ → B′ Example: ⋆ <:− Int Int <:+ ⋆ Int → Int <: ⋆ → ⋆
SLIDE 28
Negative subtype—narrowing
⋆ <:− A ι <: ι A <:− G A <:− ⋆ A′ <:+ A B <:− B′ A → B <:− A′ → B′ Example: Int <:+ ⋆ ⋆ <:− Int ⋆ → ⋆ <:− Int → Int
SLIDE 29
Naive subtype
A <:n ⋆ ι <:n ι A <:n A′ B <:n B′ A → B <:n A′ → B′ Example: Int <:n ⋆ Int <:n ⋆ Int → Int <:n ⋆ → ⋆
SLIDE 30
Part V
The Blame Theorem
SLIDE 31 Blame Safety
x safe p N safe p λx. N safe p L safe p M safe p L M safe p M safe p A <:+ B M : A
p
⇒ B safe p M safe p A <:− B M : A
p
⇒ B safe p s safe p p = q ¯ p = q M : A
q
⇒ B safe p
SLIDE 32
The Blame Theorem
Preservation If M safe p and M − → N then N safe p. Progress If M safe p then M − → blame p.
SLIDE 33
SLIDE 34 The First Tangram Theorem
A <: B if and only if A <:+ B and A <:− B
The First Blame Corollary
Let M be a term where N : A
p
⇒ B is the only subterm with label p. If A <: B then M − → blame p and M − → blame ¯ p.
SLIDE 35 The Second Tangram Theorem
A <:n B if and only if A <:+ B and B <:− A
The Second Blame Corollary
Let M be a term where N : A
p
⇒ B is the only subterm with label p. If A <:n B then M − → blame p. Let M be a term where N : A
p
⇒ B is the only subterm with label p. If B <:n A then M − → blame p.
SLIDE 36
Part VI
Blame and coercions
SLIDE 37 Lambda calculus with coercions
Γ ⊢ M : A c : A ⇒ B Γ ⊢ M : A
c
⇒ B
SLIDE 38
Coercion typing
id(A) : A ⇒ A (G !) : G ⇒ ⋆ (p ? G) : ⋆ ⇒ G c : A′ ⇒ A d : B ⇒ B′ (c → d) : A → B ⇒ A′ → B′ c : A ⇒ B d : B ⇒ C (c ; d) : A ⇒ C
SLIDE 39 Blame safety is preserved and reflected
Let cast A
p
⇒ B translate to coercion c. A <:+ B if and only if p does not appear in c. A <:− B if and only if ¯ p does not appear in c.
SLIDE 40
Part VII
Polymorphism
SLIDE 41
A magic trick
r :: [a] → [a]
SLIDE 42 Theorems for Free!
r r r r ✲ ❄ ✲❄
[a] map f [b] [a] map f [b] ra rb
SLIDE 43 Theorems for Free!
r r r r ✲ ❄ ✲❄
[97,98,99] map chr [’a’,’b’,’c’] [99,98,97] map chr [’c’,’b’,’a’] reverseInt reverseChar
SLIDE 44 Explicit binding
Γ, X:=A ⊢ N : B X / ∈ ftv(B) Γ ⊢ νX:=A. N : B Γ ⊢ N : B (X:=A) ∈ Γ Γ ⊢ N : B[X:=A] Γ ⊢ N : B[X:=A] (X:=A) ∈ Γ Γ ⊢ N : B (ΛX. N) A − → νX:=A. N Global store vs. Local bindings George Neis, Derek Dreyer, and Andreas Rossberg. Non-parametric
- parametricity. ICFP 2009, Edinburgh.
SLIDE 45 Compatibility and reductions
X ≺ X A ≺ B A ≺ ∀X. B X / ∈ ftv(A) A[X:=⋆] ≺ B ∀X. A ≺ B V : A
p
⇒ (∀X. B) − → ΛX. (V : A
p
⇒ B) if X / ∈ ftv(A) V : (∀X. A)
p
⇒ B − → (V ⋆) : A[X:=⋆]
p
⇒ B V : X
p
⇒ ⋆
q
⇒ X − → V V : X
p
⇒ ⋆
q
⇒ Y − → blame q if X = Y
SLIDE 46 Instantiate
V : ∀X. A
p
⇒ B − → V ⋆ : A[X:=⋆]
p
⇒ B K = λx : X. λy : X. x (((ΛX. K) : ∀X. X→X→X
p
⇒ ⋆→ ⋆ →⋆) 42 7 − → (((ΛX. K) ⋆ : ⋆→ ⋆ →⋆
p
⇒ ⋆→ ⋆ →⋆) 42 7 − → νX:=⋆. (K : ⋆→ ⋆ →⋆
p
⇒ ⋆→ ⋆ →⋆) 42 7 − → νX:=⋆. (K (42 : ⋆
p
⇒ ⋆) (7 : ⋆
p
⇒ ⋆)) : ⋆
p
⇒ ⋆ − → νX:=⋆. (42 : ⋆
p
⇒ ⋆) : ⋆
p
⇒ ⋆ − → νX:=⋆. 42 − → 42
SLIDE 47 ⋆ is a Jack-of-all-Trades
V : ∀X. A
p
⇒ B − → V ⋆ : A[X:=⋆]
p
⇒ B K = λx : X. λy : X. x ((ΛX. K) : ∀X. X→X→X
p
⇒ Int→Int→Int) 42 7 − → ((ΛX. K) ⋆ : ⋆→ ⋆ →⋆
p
⇒ Int→Int→Int) 42 7 − → νX:=⋆. (K : ⋆→ ⋆ →⋆
p
⇒ Int→Int→Int) 42 7 − → νX:=⋆. (K (42 : Int
p
⇒ ⋆) (7 : Int
p
⇒ ⋆)) : ⋆
p
⇒ Int − → νX:=⋆. (42 : Int
p
⇒ ⋆) : ⋆
p
⇒ Int − → νX:=⋆. 42 − → 42
SLIDE 48 ... but master of none
V : ∀X. A
p
⇒ B − → V ⋆ : A[X:=⋆]
p
⇒ B K = λx : X. λy : X. x ((ΛX. K) : ∀X. X→X→X
p
⇒ Int→Bool→Int) 42 true − → ((ΛX. K) ⋆ : ⋆→ ⋆ →⋆
p
⇒ Int→Bool→Int) 42 true − → νX:=⋆. (K : ⋆→ ⋆ →⋆
p
⇒ Int→Bool→Int) 42 true − → νX:=⋆. (K (42 : Int
p
⇒ ⋆) (true : Bool
p
⇒ ⋆)) : ⋆
p
⇒ Int − → νX:=⋆. (42 : Int
p
⇒ ⋆) : ⋆
p
⇒ Int − → νX:=⋆. 42 − → 42
SLIDE 49 Generalise
V : A
p
⇒ ∀X. B − → ΛX. (V : A
p
⇒ B) X not free in A K = λx : ⋆. λy : ⋆. x (K : ⋆→ ⋆ →⋆
p
⇒ ∀X. ∀Y. X→Y →X) Int Int 42 7 − → (ΛX. ΛY. (K : ⋆→ ⋆ →⋆
p
⇒ X→Y →X)) Int Int 42 7 − → νX:=Int. νY :=Int. (K : ⋆→ ⋆ →⋆
p
⇒ X→Y →X) 42 7 − → νX:=Int. νY :=Int. (K (42 : X
p
⇒ ⋆) (7 : Y
p
⇒ ⋆)) : ⋆
p
⇒ X − → νX:=Int. νY :=Int. (42 : X
p
⇒ ⋆) : ⋆
p
⇒ X − → νX:=Int. νY :=Int. 42 − → 42
SLIDE 50 Enforcing semantic parametricity
V : A
p
⇒ ∀X. B − → ΛX. (V : A
p
⇒ B) X not free in A K′ = λx : ⋆. λy : ⋆. y (K′ : ⋆→ ⋆ →⋆
p
⇒ ∀X. ∀Y. X→Y →X) Int Int 42 7 − → (ΛX. ΛY. (K′ : ⋆→ ⋆ →⋆
p
⇒ X→Y →X)) Int Int 42 7 − → νX:=Int. νY :=Int. (K′ : ⋆→ ⋆ →⋆
p
⇒ X→Y →X) 42 7 − → νX:=Int. νY :=Int. (K′ (42 : X
p
⇒ ⋆) (7 : Y
p
⇒ ⋆)) : ⋆
p
⇒ X − → νX:=Int. νY :=Int. (7 : Y
p
⇒ ⋆) : ⋆
p
⇒ X − → blame p
SLIDE 51 You can’t look inside a seal
(V : G
p
⇒ ⋆) is H − →
true false blame pis if G = H if G = H and G = X if G = X test = λx. if (x is Int) then ⌈x + 1⌉ else x (test : ⋆→⋆
p
⇒ ∀X. X→X) Int 2 − → νX:=Int. test (2 : X
p
⇒ ⋆) : ⋆
p
⇒ X − → νX:=Int. if ((2 : X ⇒ ⋆) is Int) then · · · else · · · − → blame pis
SLIDE 52
Part VIII
Threesomes
SLIDE 53 Even and odd, untyped
⌈let even⋆ = λn. if n = 0 then true else odd⋆ (n − 1)
then false else even⋆ (n − 1) in even⋆ 2⌉
SLIDE 54 Even and odd, partly typed
let even⋆ = ⌈λn. if n = 0 then true else odd⋆ (n − 1)⌉
then false else even (n − 1) even = even⋆ : ⋆
p
⇒ Int → Int
q
⇒ ⋆ in ⌈even⋆ 2⌉
SLIDE 55 Goodbye tail recursion!
⌈even⋆ 4⌉ − → (odd 3) : Bool
q
⇒ ⋆ − → ⌈even⋆ 2⌉ : ⋆
p
⇒ Bool
q
⇒ ⋆ − → (odd 1) : Bool
q
⇒ ⋆
p
⇒ Bool
q
⇒ ⋆ − → ⌈even⋆ 0⌉ : ⋆
p
⇒ Bool
q
⇒ ⋆
p
⇒ Bool
q
⇒ ⋆ − → ⌈true⌉
SLIDE 56 Recovering tail recursion!
⌈even⋆ 4⌉ − → (odd 3) : Bool
q
⇒ ⋆ − → ⌈even⋆ 2⌉ : ⋆
p
⇒ Bool
q
⇒ ⋆ − → (odd 1) : Bool
q
⇒ ⋆ − → ⌈even⋆ 0⌉ : ⋆
p
⇒ Bool
q
⇒ ⋆ − → ⌈true⌉
SLIDE 57
Part IX
Twosomes: a small change to blame calculus
SLIDE 58
Add the empty type
Types A, B, C ::= ι | A → B | ⋆ | ⊥ Every type is incompatible with ⊥. A ≺ ⊥ ⊥ ≺ A There are no values of type ⊥.
SLIDE 59 Allow casts between any types
Change one type rule Γ ⊢ M : A A ≺ B Γ ⊢ (M : A
p
⇒ B) : B becomes Γ ⊢ M : A Γ ⊢ (M : A
p
⇒ B) : B Add one reduction V : A
p
⇒ ⊥ − → blame p
SLIDE 60
Naive subtype
A <:n ⋆ ι <:n ι A <:n A′ B <:n B′ A → B <:n A′ → B′ ⊥ <:n A
SLIDE 61 Meet
A & ⋆ = A ⋆ & A = A ι & ι = ι (A → B) & (A′ → B′) = (A & A′) → (B & B′) A & B = ⊥
A & B is the greatest lower bound of A and B. C <:n A & B if and only if C <:n A and C <:n B
SLIDE 62 First factoring theorem
V : A
p
⇒ B = V : A
p
⇒ A & B
p
⇒ B An example V : (Int → ⋆)
p
⇒ (⋆ → Bool) = V : (Int → ⋆)
p
⇒ (Int → Bool)
p
⇒ (⋆ → Bool)
SLIDE 63 Second factoring theorem
V : A
p
⇒ B = V : A
p
⇒ ⋆
p
⇒ B An example V : (Int → ⋆)
p
⇒ (⋆ → Bool) = V : (Int → ⋆)
p
⇒ ⋆
p
⇒ (⋆ → Bool)
SLIDE 64 Third factoring theorem
V : A
p
⇒ B = V : A
p
⇒ C
p
⇒ B whenever A & B <:n C This result subsumes the other two. Take C = A & B for the first theorem. Take C = ⋆ for the second theorem.
SLIDE 65
Part X
Threesomes, without blame
SLIDE 66 Threesomes
Let A, B, C, P, Q range over types. V : A
P
= ⇒ B =def V : A ⇒ P ⇒ B whenever P <:n A and P <:n B. A B
SLIDE 67 Combining threesomes
V : A
P
= ⇒ B
Q
= ⇒ C = Def’n: P <:n A, P <:n B, Q <:n B, Q <:n C V : A ⇒ P ⇒ B ⇒ Q ⇒ C = 3’rd thm, P & Q <:n B V : A ⇒ P ⇒ Q ⇒ C = 1’st thm V : A ⇒ P ⇒ P & Q ⇒ Q ⇒ C = 3’rd thm, A & P & Q <:n P, P & Q & C <:n Q V : A ⇒ P & Q ⇒ C = Def’n: P & Q <:n A, P & Q <:n C V : A
P&Q
= ⇒ C
SLIDE 68 Combining threesomes
V : A
P
= ⇒ B
Q
= ⇒ C − → V : A
P&Q
= ⇒ C A B
SLIDE 69
Recovering tail recursion!
⌈even⋆ 4⌉ − → (odd 3) : Bool Bool = ⇒ ⋆ − → ⌈even⋆ 2⌉ : ⋆ Bool = ⇒ ⋆ − → (odd 1) : Bool Bool = ⇒ ⋆ − → ⌈even⋆ 0⌉ : ⋆ Bool = ⇒ ⋆ − → ⌈true⌉
SLIDE 70
Part XI
Coercions and Threesomes
SLIDE 71
Coercions and threesomes
Coercions c, d ::= id(A) | G ! | p ? G | c → d | c ; d Threesome coercions s, t ::= ⋆ | p ? i | i Injection coercions i ::= g ! | g | ⊥GpH Ground coercions g, h ::= ι | s → t c : A ⇒ B s : A ⇒ B i : A ⇒ B implies A = ⋆ g : A ⇒ B implies A = ⋆ and B = ⋆
SLIDE 72 Threesomes are coercions
Int → ⋆
(¯ p ? Int)→(p ? Bool)
= ⇒ ⋆ → Bool ⋆ → Bool
(Int !)→(Bool !)
= ⇒ Int → ⋆ ⋆ → ⋆
(Int !)→(p ? Bool)
= ⇒ Int → Bool Int → Bool
(¯ p ? Int)→(Bool !)
= ⇒ ⋆ → ⋆
SLIDE 73 Threesomes are coercions
Int → Int
⊥Bool ¯
p Int→⊥Int p Bool
= ⇒ Bool → Bool Int → ⋆
Int→⋆
= ⇒ Int → ⋆
SLIDE 74
Threesome typing
ι : ι ⇒ ι ⋆ : ⋆ ⇒ ⋆ g : A ⇒ G (g !) : A ⇒ ⋆ i : G ⇒ A (p ? i) : ⋆ ⇒ A s : A′ ⇒ A t : B ⇒ B′ (s → t) : A → B ⇒ A′ → B′ ⋆ = A A ≺ G G = H (⊥GpH) : A ⇒ B
SLIDE 75 Threesome composition
ι ι = ι (s → t) (s′ → t′) = (s′ s) → (t t′) ⋆ t = t (g !) ⋆ = g ! (p ? i) t = p ? (i t) g (h !) = (g h) ! (g !) (p ? i) =
g i ⊥GpH if G = H if G = H where g : A ⇒ G i : H ⇒ B ⊥GpH s = ⊥GpH g ⊥GpH = ⊥GpH
SLIDE 76
Part XII
Conclusion
SLIDE 77 Publications
Well-typed programs can’t be blamed ESOP 2009
Threesomes, with and without blame POPL 2010
- Ahmed, Findler, Siek, and Wadler
Blame for all POPL 2011
Blame, coercions, and threesomes, precisely draft
SLIDE 78
A new slogan for type safety
Milner (1978): Well-typed programs can’t go wrong. Felleisen and Wright (1994); Harper (2002): Well-typed programs don’t get stuck. Wadler and Findler (2008): Well-typed programs can’t be blamed.