Type Inference Rules (3)

Static Semantics
Type Checking and Inference
Type Inference Rules (3)
αi ∈ AE
Ci ∈ dom(C)
0
J = {C1 α1 , . . . , Cm αm }
(ΓE , AE , J ∪ J 0 ) `e e : τ
E `o e : hC1 α1 , . . . , Cm αm i ⇒ τ
A0 = {α1 , . . . , αk }
E ⊕ A0 `o e : θ ⇒ τ
E `p e : ∀α1 . . . αk .θ ⇒ τ
[P]
[G]
• rule P: collect assumptions about classes of which type
variables are instances
• rule G: use of ⊕ implies introduction of fresh type variables
104
Static Semantics
Type Checking and Inference
Checking Instances
Given local instance environment J and an instance environment I,
is simple type τ an instance of type class C: inst (J, C , τ)?
Inference rules:
Cτ∈J
inst (J, C , τ)
inst (J, Ci , τi )
insto (J, hC1 τ1 , . . . , Ck τk i ⇒ C τ)
inst (J, C , τ)
∀α1 . . . αn .θ ⇒ C τ ∈ I
insto (J, (θ ⇒ C τ)[τ1 /α1 , . . . , τm /αm ]
[I1]
[I2]
[I3]
105
Static Semantics
Type Checking and Inference
Example: Identity (1)
Type check let f = λx.x in f f
principal type scheme: ∀α.hi ⇒ α → α
([], {α}, ∅) `e let f = λx.x in f f : α → α
([], {α}, ∅) `o let f = λx.x in f f : hi ⇒ α → α
([], ∅, ∅) `p let f = λx.x in f f : ∀α.hi ⇒ α → α
Specialization: create a simple type from a type scheme.
106
Static Semantics
Type Checking and Inference
Example: Identity (2)
• let E0 = ([], {α}, ∅)
• apply the L rule, check local definition, generalize, check
body
• specialize type scheme, use A to derive typing for λx.x
~ [f : ∀β.hi ⇒ β → β]
• use A with E1 = E0 ⊕
• both judgements can be proven by specializing ΓE1 with
[α → α/β] and [α/β], respectively
~ [x : β])(x ) = β
(E0 ⊕
~ [x : β] `e x : β
E0 ⊕
E1 `e f : (α → α) → (α → α)
E1 `e f : (α → α)
E0 `e λx.x : β → β
E0 `p λx.x : ∀β.hi ⇒ β → β
~ [f : ∀β.hi ⇒ β → β] `e f f : α → α
E0 ⊕
([], {α}, ∅) `e let f = λx.x in f f : α → α
107
Static Semantics
Type Checking and Inference
Example: palindrome (1)
Assume an initial environment E0 with
Γ0 (==) = ∀α.hEq αi ⇒ α → α → Bool
Γ0 (reverse) = ∀α.hi[α] → [α]
Prove that E0 `p palindrome : ∀α.hEq αi ⇒ [α] → Bool
• E0 `p λxs .xs == reverse xs : ∀α.hEq αi ⇒ [α] → Bool
• G:
E0 ⊕ {α} `o λxs .xs == reverse xs : hEq αi ⇒ [α] → Bool
• P: (Γ0 , {α}, {Eq α}) `e λxs .xs == reverse xs : [α] → Bool
• local instance environment {Eq α} is used as an assumption
• after A, needs to prove (among others) that
~ [xs : [α]], {α}, {Eq α}) `e (==) : [α] → [α] → Bool
(Γ0 ⊕
108
Static Semantics
Type Checking and Inference
Example: palindrome (2)
• Γ0 (==) = ∀α.hEq αi ⇒ α → α → Bool
• apply V first, then in rule S instantiate with [α]/α to obtain
~ [xs : [α]], {α}, {Eq α}) `o (==) :
(Γ0 ⊕
hEq [α]i ⇒ [α] → [α] → Bool
• rule R is applicable, if we can prove inst ({Eq α}, Eq, [α])
Discharging Instance Constraints [I2]
inst ({Eq α}, Eq, α) insto ({Eq α}, hEq αi ⇒ Eq [α])
inst ({Eq α}, Eq, [α])
• first condition holds because of local instance environment
[I1]
• second condition holds, if ∀α.hEq αi ⇒ Eq [α] is in the global
instance environment [I3]
109
Static Semantics
Type Checking and Inference
But?
• inference rules so far are declarative
• environments and types must be guessed
• not well-suited for an implementation
Overview
1. new inference rules that generate constraints on type variables
2. constraint solving by unification
110
Static Semantics
Type Checking and Inference
Constraint-Based Judgments
constraint-based judgments have the following form:
Γ ` e : τ ∇ (U, V)
• Γ is a type environment as before
• e expression, τ a simple type for that expression
• principal type will be computed afterwards by unification
• U is a set of unification problems: τ=τ
˙ 0
• V is a set of instance constraints: C τ
Static Semantics
Type Checking and Inference
Constraint-Based Rules
Γ(x ) = ∀α1 . . . αk .θ ⇒ τ
βi fresh
Γ ` x : τ[β1 /α1 , . . . , βk /αk ] ∇ (∅, θ[β1 /α1 , . . . , βk /αk ])
[C-V]
~ [x : α] ` e : τ ∇ (U, V)
Γ⊕
α fresh
Γ ` λx .e : α → τ ∇ (U, V)
[C-A]
Γ ` e1 : τ1 ∇ (U1 , V1 ) Γ ` e2 : τ2 ∇ (U2 , V2 ) α fresh
Γ ` e1 e2 : α ∇ (U1 ∪ U2 ∪ {τ1 =τ
˙ 2 → α}, V1 ∪ V2 )
[C-A]
Γ ` e 0 : τ0 ∇ (U 0 , V0 ) σ = gen(Γ, τ0 , U 0 , V0 )
~ [x : σ] ` e : τ ∇ (U, V)
Γ⊕
Γ ` let x = e 0 in e : τ ∇ (U, V)
• fresh: occurs nowhere else in inference
• generalization: gen(Γ, τ, U, V)
[C-L]
Static Semantics
Type Checking and Inference
Example: palindrome (again)
• let Γ0 , I0 as on Example: palindrome (2)
• Γ0 ` λxs .xs == reverse xs : α → α → ∇ ({β → β →
Bool =α
˙ → δ → , [γ] → [γ]=α
˙ → δ}, {Eq β})
~ [xs : α] ` xs == reverse xs :
• Γ0 ⊕
∇ ({β → β → Bool =α
˙ → δ → , [γ] → [γ]=α
˙ → δ}, {Eq β})
~ [xs : α])
• C-A (slightly generalized, Γ1 = Γ0 ⊕
• Γ1 ` (==) : β → β → Bool ∇ (∅, {Eq β}) (after [C-V])
• Γ1 ` xs : α ∇ (∅, ∅) (after [C-V])
• Γ1 ` reverse xs : δ ∇ ({[γ] → [γ]=α
˙ → δ}, ∅)
• Γ1 ` reverse : [γ] → [γ] ∇ (∅, ∅)
• Γ1 ` xs : α ∇ (∅, ∅)
113
Static Semantics
Type Checking and Inference
Example: palindrome (yet again)
We have inferred that
\xs.
xs == reverse xs
• has simple type α → • with the constraints
• β → β → Bool =α
˙ →δ→
• [γ] → [γ]=α
˙ →δ
• on types, and the additional requirement
• Eq β
• on the instance environment
now: use this information to compute the principal type
Static Semantics
Type Checking and Inference
Generalization
• if Γ ` e : τ ∇ (U, V), then the principal type σ of e is the result
of gen(Γ, τ, U, V)
• this function is also used in [C-L]
gen(Γ, τ, U, V)
1. unification of type constraints: Θ = uni (U)
2. instance checking: θ = ins (I, VΘ)
3. free variables: {α1 , . . . , αk } = fv (τΘ) \ fv (Γ)
• variable is free in Γ, if it’s free in the range of Γ
• variables are bound by ∀ only
4. principal type: ∀α1 , . . . , αk .θ ⇒ τΘ
If any of the steps fails, type inference fails!
115
Static Semantics
Type Checking and Inference
Substitution
• substitution is a finite mapping from type variables to types as
in Θ = [τ/α, τ0 /α0 ]
• substitutions are simultaneously applied to types in postfix
notation
• α → β[Bool /α, α → α/β] =Bool → (α → α)
• substitutions are applied pointwise to environments, contexts,
constraints, . . .
• can be composed : τ(Θ1 ; Θ2 ) = (τΘ1 )Θ2
• Θ is more general than Θ0 , written Θ ⊆ Θ0 if there exists Θ00
such that Θ0 = Θ; Θ00
• substitution Θ is solution to τ=τ
˙ 0 if τΘ = τ0 Θ
• Theorem: Substitutions preserve well-typedness: E `e e : τ
=⇒ E `e e : τΘ
• this does not hold for contexts!
116
Static Semantics
Type Checking and Inference
Unification
Function uni (U) returns a substitution Θ
uni (U)
1. if U = ∅: return []
2. else if U = U 0 ∪ {τ=τ
˙ 0}
2.1 τ = τ0 : return uni (U 0 )
2.2 τ = α and α < fv (τ0 ): return [τ0 /α]; uni (U 0 [τ0 /α])
2.3 τ0 = α and α < fv (τ): return [τ/α]; uni (U 0 [τ/α])
2.4 τ = τ1 → τ2 and τ0 = τ01 → τ02 : return uni (U 0 ∪ {τ1 =τ
˙ 01 , τ2 =τ
˙ 02 })
0
0
0
2.5 τ = T τ1 . . . τm and τ = T τ1 . . . τm : return
uni (U 0 ∪ {τ1 =τ
˙ 01 , . . . , τm =τ
˙ 0m })
2.6 all other cases fail
Static Semantics
Type Checking and Inference
Properties of Unification
• cases 2.2 and 2.3 are called occurs check
• failing the occurs check may lead to infinite types
• succesful run of uni (U) returns most general unifier, which is
the most general subsitution that is a solution to U
• here: naive algorithm
• cleverer algorithm based on graph-based representation of
constraints and union-find data structures
118
Static Semantics
Type Checking and Inference
More Palindromes
Consider the unification problem obtained from type checking
palindrome!
uni ({β → β → Bool =α
˙ → δ → , [γ] → [γ]=α
˙ → δ})
= uni ({β=α,
˙ β=δ,
˙ Bool =,
˙ [γ] → [γ]=α
˙ → δ})
= [α/β]; uni ({β=δ,
˙ Bool =,
˙ [γ] → [γ]=α
˙ → δ})
= [α/β]; [δ/α];uni ({Bool =,
˙ [γ] → [γ]=δ
˙ → δ})
= [α/β]; [δ/α]; [Bool /]; uni ({[γ] → [γ]=δ
˙ → δ})
= [α/β]; [δ/α]; [Bool /]; uni ({[γ]=δ})
˙
= [α/β]; [δ/α]; [Bool /]; [[γ]/δ]
= Θp
• we inferred simple type α → for palindrome
• (α → )Θp = [γ] → Bool
119
Static Semantics
Type Checking and Inference
Instance Checking
• function ins is provided with
• a set of instance constraints of form C τ
• an instance environment such as I0
• ins returns a reduced context of form hC1 α1 , . . . , Ck αk i
ins (I, V)
1. while V contains constraints C τ with τ < TVar
1.1 let T τ1 . . . τm = τ (comprises T = (→))
1.2 if I contains ∀α1 . . . αk .θ ⇒ C (T αi1 . . . αim )
then return ins ((V \ {C τ}) ∪ {C 0 τj | C 0 αij ∈ θ})
1.3 if I contains ∀α1 . . . αk .θ ⇒ C β
then return ins ((V \ {C τ}) ∪ {C 0 τ | C 0 β ∈ θ})
1.4 else fail
2. while V contains pairs C1 α and C2 α such that C1 is
superclass of C2 remove C1 α from V
120
Static Semantics
Type Checking and Inference
Palindromes, Eventually
• step 2 of generalization computes θ = ins (I0 , VΘp )
• we have: ins (I0 , {Eq β}Θp and
Θp = [α/β]; [δ/α]; [Bool /]; [[γ]/δ]
• compute: ins (I0 , {Eq [γ]}
• I0 contains ∀α.hEq αi ⇒ Eq [α]
• apply step 1.2 of instance checking with T = [], τ1 = γ, and
αi1 = α
• yields: {Eq γ} and we are done
principal type of palindrome
∀γ.hEq γi ⇒ [γ] → Bool
Static Semantics
Type Checking and Inference
Concluding Remarks
• recursion: must not generalize recursive variables (type
monomorphically)
• soundness: `p and ` are equivalent
• complexity: exponential
• let a = \x → (x,x) in let b = \x → a(a(x)) in let
c = \x → b(b(x)) in . . . f (\x → x)
• inference traditionally know as algorithm W (Milner 1978)
Good luck with your assignment!