The Recursive Union of Some Gradual Types Jeremy G. Siek Sam Tobin-Hochstadt Indiana University, Bloomington 1/ 24
Gradual Typing Goal: support the entire spectrum in one language. Program Dependent Static Dynamic Logics Types Typing Typing more guarantees greater burden of proof 1 1 Anderson and Drossopoulou, WOOD 2003. Ou et al., IFIP TCS 2004. Siek and Taha, SFP 2006. Gronksi et al., SFP 2006. Tobin-Hochstadt and Felleisen, DLS 2006. Matthews and Findler, POPL 2007. 2/ 24
Gradual typing provides fine-grained mixing A partially typed program: let f = λ y : int . 1 + y h = λ g . g 3 in h f − → 4 3/ 24
Gradual typing protects type invariants A buggy, partially typed program: let f = λ y : int . 1 + y h = ( λ g . g 1 true 2 ) 3 in h 4 f 5 − → blame − 5 2 2 Wadler & Findler, Well-typed programs can’t be blamed , ESOP 2009. Findler & Felleisen, Contracts for higher-order functions , ICFP 2002. 4/ 24
� Semantics via the Blame Calculus Gradually Typed Lambda Calculus insert casts run � result Blame Calculus 5/ 24
Translated to the blame calculus The buggy program: let f = λ y : int . 1 + y 1 2 3 h = ( λ g : ⋆. ( g : ⋆ ⇒ ⋆ → ⋆ ) ( true : bool ⇒ ⋆ )) : ⋆ → ⋆ ⇒ ⋆ in 4 5 ( h : ⋆ ⇒ ⋆ → ⋆ ) ( f : int → int ⇒ ⋆ ) − → ∗ 5 1 2 ( f : int → int ⇒ ⋆ → ⋆ ⇒ ⋆ → ⋆ ( true : bool ⇒ ⋆ )) − → ∗ 2 − 1 − 5 5 1 ( f (( true : bool ⇒ ⋆ ) : ⋆ ⇒ ⋆ ⇒ int )) : int ⇒ ⋆ ⇒ ⋆ − → ∗ blame − 5 6/ 24
Desiderata IntList = µ X . Unit + int × X letrec prod = λ ls : IntList . case ls of unit ⇒ 0 | ( hd , tl ) ⇒ hd ∗ prod ( tl ) in prod ⌈ ( 1 , ( 2 , unit )) ⌉ Racket & Typed Racket supports something like this, and here’s the essence of that story in terms of a Blame Calculus. 3 3 Tobin-Hochstadt and Felleisen, The Design and Impl. of Typed Scheme , POPL 2008. 7/ 24
The problem with disjoint sums What should the following reduce to? 4 : int ⇒ ⋆ ⇒ ( int + int ) Possible answers: 1. inl 4 2. inr 4 3. Jeremy, don’t ask that question! 8/ 24
Alternative: union types ◮ The case of set-theoretic union (Pierce, 1991) doesn’t provide dispatching. ( case V of x ⇒ N ) − → [ x := V ] N ◮ C Duce’s (Castagna, 2014) typecase is more powerful than Racket’s: � [ x �→ V ] M if ⊢ V : A ( x = V ∈ A ? M | N ) − → [ x �→ V ] N if ⊢ V : ¬ A ◮ The “true union” type of Cartwright and Fagan (1991) matches our needs. We’ll give an updated presentation. � M V if tycons ( V ) = c case c ?( V ) then M else N − → N V otherwise 9/ 24
Union types Base types ::= Unit | int | bool | · · · ι Type constructors c ::= ι |→| × c (¯ Types A , B , C , D ::= A ) | A ∪ B | ⊥ Unions are restricted to one type per top type-constructor: tycons ( A ) ∩ tycons ( B ) = ∅ ⊢ A i ∀ i ∈ 1 .. n ⊢ c (¯ ⊢ A ∪ B ⊢ ⊥ A ) tycons ( c (¯ A )) = { c } tycons ( A ∪ B ) = tycons ( A ) ∪ tycons ( B ) tycons ( ⊥ ) = ∅ 10/ 24
Why the restriction on union types? A = ( int → int ) ∪ ( bool → bool ) f : A case → ?( f ) then ( λ x : A . M ) else ( λ x : ⊥ . N ) Racket’s type predicates can’t eliminate arbitrary unions. 11/ 24
Unions as partial functions on constructors A ( c ) � c ′ (¯ A ) if c = c ′ c ′ (¯ A )( c ) = ⊥ otherwise � A ( c ) if c ∈ tycons ( A ) ( A ∪ B )( c ) = B ( c ) if c ∈ tycons ( B ) A − c � ⊥ if c = c ′ c ′ (¯ A ) − c = c ′ (¯ A ) otherwise ( A ∪ B ) − c = ( A − c ) ∪ ( B − c ) ⊥ − c = ⊥ 12/ 24
Blame calculus with unions c (¯ A , B , C , D ::= A ) | A ∪ B | ⊥ | ⋆ p , q + ℓ | − ℓ ::= k | op ( ¯ L , M , N ::= M ) | λ x : A . N | L N | p ( M , N ) | fst L | snd L | M : A ⇒ B | case c ?( L ) then M else N Γ ⊢ M : A A ∼ B Γ ⊢ M : A A < : B · · · p Γ ⊢ M : B Γ ⊢ M : A ⇒ B Γ ⊢ L : A Γ ⊢ M : A ( c ) → B Γ ⊢ N : A − c → B Γ ⊢ ( case c ?( L ) then M else N ) : B 13/ 24
Compatibility for unions A ∼ B A i ∼ B i ∀ i ∈ 1 .. n A ∼ ⋆ ⋆ ∼ A c (¯ A ) ∼ c (¯ B ) tycons ( A ) = tycons ( B ) ∀ c ∈ tycons ( A ) . A ( c ) ∼ B ( c ) A ∼ B ⊥ ∼ ⊥ 14/ 24
Subtyping for unions A < : B c (¯ ∀ c ∈ tycons ( A ) . A ( c ) < : B A ) < : B ( c ) c (¯ A < : B A ) < : B A < : C B < : D C < : A B < : D ι < : ι A × B < : C × D A → B < : C → D Also, we take A ∪ ⊥ = ⊥ ∪ A = A . 4 4 Inspired by Vouillon (2004). 15/ 24
Operational semantics for casting unions Ground types G , H c (¯ ⋆ ) | G ∪ H | ⊥ ::= p Values V , W ::= k | λ x : A . N | ( V , W ) | V : G ⇒ ⋆ p p V : A ⇒ B − → V : A ( c ) ⇒ B ( c ) if c = tycons ( V ) and ¬ ( A = A ( c ) ∧ B = B ( c )) q p V : G ⇒ ⋆ ⇒ H − → V if G < : H q p V : G ⇒ ⋆ ⇒ H − → blame p if G � < : H 16/ 24
� � � � Equi-recursive types IntList = µ X . Unit ∪ int × X = ∪ × Unit int c (¯ Pre-types P , Q ::= A ) | P ∪ Q | ⊥ | ⋆ A , B , C µ X . P | X Types ::= 17/ 24
Compatibility for equi-recursive types A i ∼ B i ∀ i ∈ 1 .. n P ∼ ⋆ ⋆ ∼ Q P ∼ Q c (¯ A ) ∼ c (¯ B ) tycons ( P ) = tycons ( Q ) ∀ c ∈ tycons ( P ) . P ( c ) ∼ Q ( c ) P ∼ Q ⊥ ∼ ⊥ P ∼ Q X ∼ X A ∼ B µ X . P ∼ µ X . Q 18/ 24
Subtyping for equi-recursive types Subtype Environment Σ ::= ∅ | Σ , A < : B Subtyping on pre-types Σ ⊢ P < : Q Σ ⊢ A < : C Σ ⊢ C < : A Σ ⊢ B < : D Σ ⊢ B < : D Σ ⊢ ι < : ι Σ ⊢ A × B < : C × D Σ ⊢ A → B < : C → D Σ ⊢ c (¯ ∀ c ∈ tycons ( C ) . Σ ⊢ P ( c ) < : Q A ) < : Q ( c ) Σ ⊢ c (¯ Σ ⊢ P < : Q A ) < : Q Subtyping Σ ⊢ A < : B A = µ X . P B = µ Y . Q Σ , A < : B ⊢ [ X �→ A ] P < : [ Y �→ B ] Q A < : B ∈ Σ Σ ⊢ A < : B Σ ⊢ A < : B 5 5 Inspired by Brandt and Henglein (1998). 19/ 24
Operational semantics for casting recursive types Ground pre-types γ c (¯ ⋆ ) | γ ∪ γ | ⊥ ::= Ground types G , H ::= µ X . γ | X p Values V , W k | λ x : A . N | ( V , W ) | V : G ⇒ ⋆ ::= p p V : µ X . A ⇒ µ X . B − → V : [ X �→ µ X . A ] A ⇒ [ X �→ µ X . B ] B 20/ 24
Back to the example IntList ≡ µ X . Unit ∪ ( int × X ) DynList ≡ µ X . Unit ∪ ( ⋆ × ⋆ ) q p → ∗ ( 1 , ( 2 , unit )) : ( ⋆ × ⋆ ) − ⇒ ⋆ ⇒ IntList q p p − → ( 1 , ( 2 , unit )) : ( ⋆ × ⋆ ) ⇒ ⋆ ⇒ DynList ⇒ IntList p − → ( 1 , ( 2 , unit )) : DynList ⇒ IntList p − → ( 1 , ( 2 , unit )) : ( Unit ∪ ( ⋆ × ⋆ )) ⇒ ( Unit ∪ ( int × IntList )) p − → ( 1 , ( 2 , unit )) : ( ⋆ × ⋆ ) ⇒ ( int × IntList ) p p − → ( 1 : ⋆ ⇒ int , ( 2 , unit ) : ⋆ ⇒ IntList ) p − → ( 1 , ( 2 , unit ) : ⋆ ⇒ IntList ) → ∗ ( 1 , ( 2 , unit )) − 21/ 24
Other things in the paper ◮ Definition of a gradually typed lambda calculus with unions and equi-recursive types. ◮ Type checking algorithm for this source language. ◮ Translation to the blame calculus. ◮ Proofs of Type Safety and Blame Safety for the blame calculus. 22/ 24
A remark about types Real Types Type Enhancers n : int { n : int | n > 0 } ( V , W ) : A × B A ∩ B inl V , inr W : A + B A ∪ B (Λ X . M ) : ∀ X . A type schemes (ML) fold M : µ X . A equi-recursive Is there already a name for this distinction? 23/ 24
Conclusion Thank you to Philip for a great collaboration! 24/ 24
Recommend
More recommend