Gradual Typing with Inference Jeremy Siek University of Colorado at Boulder joint work with Manish Vachharajani
Overview • Motivation • Background • Gradual Typing • Unification-based inference • Exploring the Solution Space • Type system (specification) • Inference algorithm (implementation)
Why Gradual Typing? • Static and dynamic type systems have complimentary strengths. • Static typing provides full-coverage error checking, efficient execution, and machine-checked documentation. • Dynamic typing enables rapid development and fast adaption to changing requirements. • Why not have both in the same language? Python Java
Goals for gradual typing • Treat programs without type annotations as dynamically typed. • Programmers may incrementally add type annotations to gradually increase static checking. • Annotate all parameters and the type system catches all type errors. 4
Goals for gradual typing • Treat programs without type annotations as dynamically typed. • Programmers may incrementally add type annotations to gradually increase static checking. • Annotate all parameters and the type system catches all type errors. dynamic static 4
Goals for gradual typing • Treat programs without type annotations as dynamically typed. • Programmers may incrementally add type annotations to gradually increase static checking. • Annotate all parameters and the type system catches all type errors. dynamic gradual static 4
The Gradual Type System • Classify dynamically typed expressions with the type ‘ ? ’ • Allow implicit coercions to ? and from ? with any other type • Extend coercions to compound types using a new consistency relation 5
Coercions to and from ‘ ?’ ( λ a:int. ( λ x. x + 1) a) 1 Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ ? ( λ a:int. ( λ x. x + 1) a) 1 Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ int ? ( λ a:int. ( λ x. x + 1) a) 1 Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ int ? int ⇒ ? ( λ a:int. ( λ x. x + 1) a) 1 Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ int ⇒ ? ( λ a:int. ( λ x. x + 1) a) 1 int x int → int Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ ? int ⇒ ? ( λ a:int. ( λ x. x + 1) a) 1 int x int → int Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions to and from ‘ ?’ ? int ⇒ ? ( λ a:int. ( λ x. x + 1) a) 1 int x int → int ? ⇒ int Parameters with no type annotation are given the dynamic type ‘ ?’ . 6
Coercions between compound types ( λ f:int → int. f 1) ( λ x. 1) 7
Coercions between compound types ? → int ( λ f:int → int. f 1) ( λ x. 1) 7
Coercions between compound types ? → int ( λ f:int → int. f 1) ( λ x. 1) ? → int ⇒ int → int 7
Detect static type errors ( λ f:int → int. f 1) 1 int ⇒ int → int 8
Type system: replace = with ~ Γ ⊢ e 1 : σ → τ Γ ⊢ e 2 : σ ‘ σ ‘ ~ σ Γ ⊢ e 1 e 2 : τ 9
Type system: replace = with ~ Γ ⊢ e 1 : σ → τ Γ ⊢ e 2 : σ ‘ σ ‘ ~ σ Γ ⊢ e 1 e 2 : τ 9
The consistency relation • Definition: a type is consistent , written ~, with another type when they are equal where they are both defined. • Examples: int ~ int int ~ bool ? ~ int int ~ ? int → ? ~ ? → bool ? → bool ~ ? → int 10
The consistency relation τ 1 ~ τ 2 ? ~ τ τ ~ ? τ ~ τ τ 1 ~ τ 3 τ 2 ~ τ 4 τ 1 → τ 2 ~ τ 3 → τ 4 11
Compiler inserts run-time checks Γ ⊢ e 1 ⇒ e’ 1 : σ → τ Γ ⊢ e 2 ⇒ e’ 2 : σ ‘ σ ‘ ~ σ Γ ⊢ e 1 e 2 ⇒ e’ 1 〈 σ ⇐ σ ‘ 〉 e’ 2 : τ Example: ( λ a:int. ( λ x. x + 1) a) 1 ⇒ ( λ a:int. ( λ x. 〈 int ⇐ ? 〉 x + 1) 〈 ? ⇐ int 〉 a) 1 12
Recent Developments • Integration with objects (Siek & Taha, ECOOP’07) • Space-efficiency (Herman et al, TFP’07) • Blame tracking (Wadler & Findler, Scheme’07) • In JavaScript (Herman & Flanagan, ML’07) 13
Why Inference? • Interesting research question: how does the dynamic type interact with type variables? • Practical applications • Help programmers migrate dynamically typed code to statically typed code • Explain how gradual typing can be integrated with functional languages with inference (ML, Haskell, etc.) 14
STLC with type vars: Specification Γ ⊢ e : τ Standard STLC judgment: An STLC term with type variables is well typed if there exists an S such that S( Γ ) ⊢ S(e) : S( τ ) e.g., ( λ x:int. ( λ y: α . y) x) S = { α ↦ int} 15
Inference Algorithm λ x:int. ( λ y: α . y) x constraint generation α → α = int → β unification S = { α ↦ int, β ↦ int} 16
Huet’s Unification α → α = int → β 17
Huet’s Unification α → α = int → β � � � int � 17
Huet’s Unification α → α = int → β � � � � int � � int � 17
Huet’s Unification α → α = int → β � � � � int � � int � � int � 17
Huet’s Unification α → α = int → β � � � � int � � int � � � int � int 17
Huet’s Unification • When merging nodes, the algorithm needs to decide which label to keep • In this setting, non-type variables trump type variables � int int 18
Gradual Typing with Inference • Setting: STLC with α and ?. • To migrate from dynamic to static, change ? to α and the inferencer will tell you the solution for α or give an error . λ f:?. λ x:?. f x x λ f: α . λ x:?. f x x 19
Syntactic Sugar λ f. λ x. f x x ? 20
Syntactic Sugar λ f. λ x. f x x λ f:?. λ x:?. f x x ? 20
Syntactic Sugar λ f. λ x. f x x λ f:?. λ x:?. f x x λ f: α . λ x: β . f x x ? 20
Non-solution #1 Well typed in gradual type system after substitution S( Γ ) ⊢ S(e) : S( τ ) Problem: the following is accepted ( λ f: α . f 1) 1 S = { α ↦ ?} 21
Non-solution #2 Forbid ? s from appearing in a solution S Problem: sometimes this forces cast errors at runtime λ x : ? . ( λ y: α . y) x λ x : ? . ( λ y:int. y) x λ x : ? . ( λ y:int. y) 〈 int ⇐ ? 〉 x 22
Non-solution #2 Forbid ? s from appearing in a solution S Problem: sometimes this forces cast errors at runtime λ x : ? . ( λ y: α . y) x λ x : ? . ( λ y:int. y) x λ x : ? . ( λ y:int. y) 〈 int ⇐ ? 〉 x 22
Non-solution #3 Treat each ? as a different type variable then check for well typed in STLC after substitution Problem: the following is rejected λ f:int → bool → int. λ x:?. f x x λ f:int → bool → int. λ x: α . f x x 23
Non-solution #4 Treat each occurrence of ? in a constraint as a different type variable Problem: if no type vars in the program, the resulting type should not have type vars λ f:int → ? . λ x:int. (f x) int → ? = int → β int → α = int → β 24
Lessons • Need to restrict the occurrences of ? in solutions • But can’t completely outlaw the use of ? • Idea: a solution for α at least as informative as any of the types that constrain α constrain • i.e., the solution for α must be an upper bound of all the types that constrain α 25
Information Ordering τ 1 ⊑ τ 2 int → int ? → int int → ? ? → ? bool int semi-lattice ? 26
Type System • But what does it mean for a type to constrain α ? λ f: α → α . λ g:( ? → int) → int. g f ? → int α → α 27
Type System • But what does it mean for a type to constrain α ? λ f: α → α . λ g:( ? → int) → int. g f ? → int α → α ? ⊑ S( α ) 27
Type System • But what does it mean for a type to constrain α ? λ f: α → α . λ g:( ? → int) → int. g f ? → int α → α ? ⊑ S( α ) int ⊑ S( α ) 27
Type System • The typing judgment: S; Γ ⊢ e : τ • Consistent-equal: S ⊨ τ ≃ τ • Consistent-less: S ⊨ τ ⊑ τ 28
Type System S; Γ ⊢ e : τ S; Γ ⊢ e 1 : τ 1 S; Γ ⊢ e 2 : τ 2 S ⊨ τ 1 ≃ τ 2 → β ( β fresh) S; Γ ⊢ e 1 e 2 : β 29
Type System S; Γ ⊢ e : τ S; Γ ⊢ e 1 : τ 1 S; Γ ⊢ e 2 : τ 2 S ⊨ τ 1 ≃ τ 2 → β ( β fresh) S; Γ ⊢ e 1 e 2 : β 29
Consistent-equal S ⊨ τ ≃ τ S ⊨ ? ≃ τ S ⊨ τ ≃ ? S ⊨ τ ⊑ S( α ) S ⊨ τ ⊑ S( α ) S ⊨ α ≃ τ S ⊨ τ ≃ α S ⊨ τ 1 ≃ τ 3 S ⊨ τ 2 ≃ τ 4 S ⊨ γ ≃ γ S ⊨ τ 1 → τ 2 ≃ τ 3 → τ 4 30
Consistent-less S ⊨ τ ⊑ τ S ⊨ ? ⊑ τ S ⊨ S( α ) = τ S ⊨ α ⊑ τ S ⊨ τ 1 ⊑ τ 3 S ⊨ τ 2 ⊑ τ 4 S ⊨ γ ⊑ γ S ⊨ τ 1 → τ 2 ⊑ τ 3 → τ 4 31
Properties • When there are no type variables in the program, the type system acts like the original gradual type system • When there are no ? in the program, the type system acts like the STLC with variables 32
Recommend
More recommend