Gradual Typing with Union and Intersection Types Giuseppe Castagna, Victor Lanvin ICFP 17 September 6, 2017 1 / 14
Outline 1 Motivating Example 2 Types and Subtyping 3 Function Types and Operators 4 Conclusion 1 / 14
Motivating Example (1/3) [Siek and Vachharajani, 2008] let succ : Int -> Int =... let not : Bool -> Bool =... let f (condition : Bool) (x : ) : = if condition then succ x else not x 2 / 14
Motivating Example (1/3) [Siek and Vachharajani, 2008] let succ : Int -> Int =... let not : Bool -> Bool =... let f (condition : Bool) (x :?) :? = if condition then succ x else not x Cannot be typed with simple types, but valid with gradual types. 2 / 14
Motivating Example (1/3) [Siek and Vachharajani, 2008] let succ : Int -> Int =... let not : Bool -> Bool =... let f (condition : Bool) (x :?) :? = if condition then succ x else not x Cannot be typed with simple types, but valid with gradual types. What if we apply it to a string? 2 / 14
Motivating Example (2/3) Set-theoretic version: let f (condition : Bool) (x : (Int Bool)) : (Int Bool) = if condition then if x Int then succ x else assert false else if x Bool then not x else assert false 3 / 14
Motivating Example (2/3) Set-theoretic version: let f (condition : Bool) (x : (Int Bool)) : (Int Bool) = if condition then if x Int then succ x else assert false else if x Bool then not x else assert false Syntactically heavy, but safe 3 / 14
Motivating Example (3/3) Mixing the two: let f (condition : Bool) (x : (Int Bool) &?) : (Int Bool) = if condition then succ x else not x 4 / 14
Motivating Example (3/3) Mixing the two: let f (condition : Bool) (x : (Int Bool) &?) : (Int Bool) = if condition then succ x else not x Cannot be applied to something else than an integer or a boolean, and has a precise return type Syntactically straightforward 4 / 14
Summary of the Motivations Gradualization of single expressions is sometimes too coarse Set-theoretic types are powerful but syntactically heavy (no reconstruction) 5 / 14
Summary of the Motivations Gradualization of single expressions is sometimes too coarse Set-theoretic types are powerful but syntactically heavy (no reconstruction) Mixing the two would: Make the transition between dynamic types and static types smoother Reduce the syntactic overhead of set-theoretic types 5 / 14
Outline 1 Motivating Example 2 Types and Subtyping 3 Function Types and Operators 4 Conclusion 5 / 14
Type Syntax t STypes ::= b t t t t t t t Empty Any τ GTypes ::=? b τ τ τ τ τ τ t Empty Any 6 / 14
Type Syntax t STypes ::= b t t t t t t t Empty Any τ GTypes ::=? b τ τ τ τ τ τ t Empty Any Note:? Any Any = unknown type, explicitly deconstructed? = unknown type, implicitly deconstructed 6 / 14
Type Semantics: Concretization First idea: apply AGT [Garcia et al., 2016] 7 / 14
Type Semantics: Concretization First idea: apply AGT [Garcia et al., 2016] We define a concretization function γ : GTypes P(STypes). γ(?) = STypes γ(τ 1 τ 2 ) = {t 1 t 2 t i γ(τ i )} γ(τ 1 τ 2 ) = {t 1 t 2 t i γ(τ i )} γ(b) = {b} etc... 7 / 14
Type Semantics: Concretization First idea: apply AGT [Garcia et al., 2016] We define a concretization function γ : GTypes P(STypes). γ(?) = STypes γ(τ 1 τ 2 ) = {t 1 t 2 t i γ(τ i )} γ(τ 1 τ 2 ) = {t 1 t 2 t i γ(τ i )} γ(b) = {b} etc... For example, γ((? Int)?) = {(t Int) t (t, t ) STypes 2 } 7 / 14
Type Semantics: Subtyping (1/2) Consistent subtyping [Garcia et al., 2016] σ τ (s, t) γ(σ) γ(τ), s t 8 / 14
Type Semantics: Subtyping (1/2) Consistent subtyping [Garcia et al., 2016] σ τ (s, t) γ(σ) γ(τ), s t However, we can show the existence of extremal concretizations: t γ(τ), τ t τ 8 / 14
Type Semantics: Subtyping (1/2) Consistent subtyping [Garcia et al., 2016] σ τ (s, t) γ(σ) γ(τ), s t However, we can show the existence of extremal concretizations: t γ(τ), τ t τ (??) = (Any Empty) (??) = (Empty Any) 8 / 14
Type Semantics: Subtyping (2/2) Consistent subtyping σ τ σ τ 9 / 14
Type Semantics: Subtyping (2/2) Consistent subtyping σ τ σ τ = Consistent subtyping reduces in linear time to semantic subtyping! 9 / 14
Type Semantics: Subtyping (2/2) Consistent subtyping σ τ σ τ = Consistent subtyping reduces in linear time to semantic subtyping! Note: emphasizes the fact that consistent subtyping is not transitive. 9 / 14
Type Semantics: Abstraction? What about the abstraction function? 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) = Int 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) = Int? 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) = Int? α({int Bool, Bool Int}) =??? 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) = Int? α({int Bool, Bool Int}) =?? 10 / 14
Type Semantics: Abstraction? What about the abstraction function? Problem: and are connectives, not constructors. α({int Bool,Int Int, Int Empty}) = α({int, Int, Int}) α({bool, Int, Empty}) = Int? α({int Bool, Bool Int}) = Int Bool 10 / 14
Outline 1 Motivating Example 2 Types and Subtyping 3 Function Types and Operators 4 Conclusion 10 / 14
Typing Applications: Modus Ponens We start from the usual rule: Γ e 1 : σ 1 τ 1 Γ e 2 : σ 2 σ 2 σ 1 Γ e 1 e 2 : τ 1 Three components: 11 / 14
Typing Applications: Modus Ponens We start from the usual rule: Γ e 1 : σ 1 τ 1 Γ e 2 : σ 2 σ 2 σ 1 Γ e 1 e 2 : τ 1 Three components: Domain 11 / 14
Typing Applications: Modus Ponens We start from the usual rule: Γ e 1 : σ 1 τ 1 Γ e 2 : σ 2 σ 2 σ 1 Γ e 1 e 2 : τ 1 Three components: Domain Subtyping check 11 / 14
Typing Applications: Modus Ponens We start from the usual rule: Γ e 1 : σ 1 τ 1 Γ e 2 : σ 2 σ 2 σ 1 Γ e 1 e 2 : τ 1 Three components: Domain Subtyping check Result 11 / 14
Typing Applications: Modus Ponens Revisited Problem: what is the domain of ((Int Bool) Int) ( (Bool Int) (Int Int))? 12 / 14
Typing Applications: Modus Ponens Revisited Problem: what is the domain of ((Int Bool) Int) ( (Bool Int) (Int Int))? What is the result of ((Int Bool) (Bool Int)) (Nat Nat) applied to Nat? 12 / 14
Typing Applications: Modus Ponens Revisited Problem: what is the domain of ((Int Bool) Int) ( (Bool Int) (Int Int))? What is the result of ((Int Bool) (Bool Int)) (Nat Nat) applied to Nat? Γ e 1 : σ Γ e 2 : τ τ dom(σ) Γ e 1 e 2 : σ τ 12 / 14
Typing Applications: Modus Ponens Revisited Problem: what is the domain of ((Int Bool) Int) ( (Bool Int) (Int Int))? Int What is the result of ((Int Bool) (Bool Int)) (Nat Nat) applied to Nat? Nat Bool Γ e 1 : σ Γ e 2 : τ τ dom(σ) Γ e 1 e 2 : σ τ 12 / 14
Function Operators: Examples dom((int Int) (??)) = 13 / 14
Function Operators: Examples dom((int Int) (??)) = Any since it can accept any value 13 / 14
Function Operators: Examples dom((int Int) (??)) = Any since it can accept any value dom((int Int) (??)) = 13 / 14
Function Operators: Examples dom((int Int) (??)) = Any since it can accept any value dom((int Int) (??)) = Int 13 / 14
Function Operators: Examples dom((int Int) (??)) = Any since it can accept any value dom((int Int) (??)) = Int ((? Int) (? Bool)) Int = 13 / 14
Function Operators: Examples dom((int Int) (??)) = Any since it can accept any value dom((int Int) (??)) = Int ((? Int) (? Bool)) Int = Int Bool 13 / 14
Outline 1 Motivating Example 2 Types and Subtyping 3 Function Types and Operators 4 Conclusion 13 / 14
Conclusion and Future Work Current results: + Efficient characterization of consistent subtyping + Sound system + Supports polymorphism (W.I.P.) No blame theorem, and no gradual guarantee yet 14 / 14
Conclusion and Future Work Current results: + Efficient characterization of consistent subtyping + Sound system + Supports polymorphism (W.I.P.) No blame theorem, and no gradual guarantee yet Future work: Provide a statically-typed cast-calculus and prove the gradual guarantee Study blame 14 / 14