Lectures onType Theory
Hindley–Milner polymorphism and the value restriction
appendix sectionrules

Hindley–Milner polymorphism and the value restriction

HM monotypes are finite constructor trees whose leaves may be type variables. Schemes have only an outer quantifier prefix, σ::=τα.σ, and contexts assign schemes to distinct term variables. Write σσ when every monotype instance of σ is an instance of σ. The complete declarative core is

(x:σ)Γ
Γx:σ
Var
Γe:σσσ
Γe:σ
Inst
Γe:σαftv(Γ)
Γe:α.σ
Gen
Γ,x:τ1e:τ2
Γλx.e:τ1τ2
Lam
Γe1:τ2τΓe2:τ2
Γe1e2:τ
App
Γe1:σΓ,x:σe2:τ
Γlet x=e1 in e2:τ
Let

Here the types displayed in Lam and App are monotypes; only a let-bound variable may receive a scheme.

For the closed primitive diagnostic, numerals are generated by

zero num
N-Z
n num
succ n num
N-S

Constraint generation, unification, and Algorithm W

For the let-free teaching calculation, the ordered constraint judgment is Γce:τE, where EE is list concatenation:

Γ(x)=τ
Γcx:τ()
C-Var
Γ,x:αce:τEα fresh
Γcλx.e:ατE
C-Lam
Γce1:τ1E1Γce2:τ2E2β fresh
Γce1e2:βE1E2(τ1τ2β)
C-App

This judgment collects once; it is not Algorithm W.

The deterministic unifier consumes a finite equation list from the left. Substitutions act postfix, and τ[S;T]=(τ[S])[T]. Its complete clauses are unify(())=id,UDoneunify(ττ,E)=unify(E),UDeleteτα is preprocessed as ατ(τ not a variable),UOrientunify(ατ,E)=let R=[τ/α],U=unify(E[R]) in R;U,UEliminateunify(F(τ¯)F(ρ¯),E)=unify(τ1ρ1,,τnρn,E)UDecompose Orientation is a nonrecursive preprocessing rewrite. The elimination clause requires ατ and αftv(τ). It fails when the occurs check fails. Unequal rigid constructors or unequal arities fail. Decomposition prepends component equations in the displayed order.

Syntax-directed typing is

Γ(x)=σστ
Γsx:τ
S-Var
Γ,x:τ1se:τ2
Γsλx.e:τ1τ2
S-Lam
Γse1:τ1τ2Γse2:τ1
Γse1e2:τ2
S-App
Γse1:τ1Γ,x:GenΓ(τ1)se2:τ2
Γslet x=e1 in e2:τ2
S-Let

Algorithm W carries one monotonically consumed fresh-variable supply. With every fresh variable new for the entire run, its complete pure clauses are W(Γ,x)=(id,fresh(Γ(x))),W(Γ,λx.e)=let (S,τ)=W((Γ,x:α),e) in (S,α[S]τ),W(Γ,e1e2)=let (S1,τ1)=W(Γ,e1),(S2,τ2)=W(Γ[S1],e2),U=unify((τ1[S2]τ2β)),in (S1;S2;U,β[U]),W(Γ,let x=e1 in e2)=let (S1,τ1)=W(Γ,e1),σ=GenΓ[S1](τ1),(S2,τ2)=W((Γ[S1],x:σ),e2),in (S1;S2,τ2).

The evidence checker records variable instantiation, lambda domains, application, and let generalization by the four rules Ev-Var, Ev-Lam, Ev-App, and Ev-Let of definition 4.51; its judgment is Θ;Γevd:τ, and erasure is defined in definition 4.50.

For lists add List, nil, cons, and the rules

Γnil:List(τ)
ListNil
Γe1:τΓe2:List(τ)
Γcons e1 e2:List(τ)
ListCons
Γsnil:List(τ)
S-ListNil
Γse1:τΓse2:List(τ)
Γscons e1 e2:List(τ)
S-ListCons
Γe:List(τ)Γe0:ρΓ,h:τ,t:List(τ)e1:ρ
Γcase e of {nile0;cons h te1}:ρ
ListCase
Γse:List(τ)Γse0:ρΓ,h:τ,t:List(τ)se1:ρ
Γscase e of {nile0;cons h te1}:ρ
S-ListCase

W returns (id,List(α)) for nil with fresh α. For cons it computes (S1,τ1)=W(Γ,e1),(S2,τ2)=W(Γ[S1],e2),U=unify((τ2List(τ1[S2]))) and returns (S1;S2;U,List(τ1[S2;U])). The case clause computes, in order, (S0,τ0)=W(Γ,e),U=unify((τ0List(α))),(S1,ρ0)=W(Γ[S0;U],e0),(S2,ρ1)=W((Γ[S0;U;S1],h:α[U;S1],t:List(α[U;S1])),e1),V=unify((ρ0[S2]ρ1)), and returns (S0;U;S1;S2;V,ρ1[V]).

B::={nile0;cons h te1},E::=[]EevElet x=E in eref E!EE:=ev:=Econs E econs v Ecase E of B.

For references, add Unit, Ref(τ), locations, and the standard rules

Γunit:Unit
Unit
Γe:τ
Γref e:Ref(τ)
Ref
Γe:Ref(τ)
Γ!e:τ
Deref
Γe1:Ref(τ)Γe2:τ
Γe1:=e2:Unit
Assign

The conservative value restriction replaces unrestricted generalization at let by

Γv:τ1Γ,x:GenΓ(τ1)e2:τ2
Γlet x=v in e2:τ2
Let-Gen
Γe1:τ1Γ,x:τ1e2:τ2
Γlet x=e1 in e2:τ2
Let-Mono

where v ranges over the generalizable forms (variables, constants, abstractions, and fully applied data constructors whose arguments are generalizable forms) and GenΓ(τ)=(ftv(τ)ftv(Γ)).τ, with the finite prefix listed in the fixed global type-variable order.

The syntax-directed value-restricted rules are

Γsv:τ1Γ,x:GenΓ(τ1)se2:τ2
Γslet x=v in e2:τ2
S-Let-Gen
Γse1:τ1Γ,x:τ1se2:τ2
Γslet x=e1 in e2:τ2
S-Let-Mono

The first rule requires a generalizable form and the second a nongeneralizable expression. The store forms are

Γsunit:Unit
S-Unit
Γse:τ
Γsref e:Ref(τ)
S-Ref
Γse:Ref(τ)
Γs!e:τ
S-Deref
Γse1:Ref(τ)Γse2:τ
Γse1:=e2:Unit
S-Assign

At run time a store typing Σ maps locations to monotypes, and

dom(Σ)
ΓΣ:Ref(Σ())
Loc
ΓΣe:σαftv(Γ)ftv(Σ)
ΓΣe:α.σ
GenΣ
ΓΣv:τ1Γ,x:GenΓ,Σ(τ1)Σe2:τ2
ΓΣlet x=v in e2:τ2
Let-GenΣ

where GenΓ,Σ(τ)=(ftv(τ)(ftv(Γ)ftv(Σ))).τ. All nongeneralizing rules lift by adding the same Σ subscript. For a store μ, the three value-restricted roots are (μ,ref v)(μ[v],)(dom(μ)),(μ,!)(μ,μ()),(μ,:=v)(μ[v],unit).

Search the book

Type to search the local edition.