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
(𝑥:𝜎)∈Γ
Γ⊢𝑥:𝜎
Var
Γ⊢𝑒:𝜎𝜎⊒𝜎′
Γ⊢𝑒:𝜎′
Inst
Γ⊢𝑒:𝜎𝛼∉ftv(Γ)
Γ⊢𝑒:∀𝛼.𝜎
Gen
Γ,𝑥:𝜏1⊢𝑒:𝜏2
Γ⊢𝜆𝑥.𝑒:𝜏1→𝜏2
Lam
Γ⊢𝑒1:𝜏2→𝜏Γ⊢𝑒2:𝜏2
Γ⊢𝑒1𝑒2:𝜏
App
Γ⊢𝑒1:𝜎Γ,𝑥:𝜎⊢𝑒2:𝜏
Γ⊢𝗅𝖾𝗍𝑥=𝑒1𝗂𝗇𝑒2:𝜏
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
𝗓𝖾𝗋𝗈𝗇𝗎𝗆
N-Z
𝑛𝗇𝗎𝗆
𝗌𝗎𝖼𝖼𝑛𝗇𝗎𝗆
N-S
Constraint generation, unification, and Algorithm W
For the let-free teaching calculation, the ordered constraint judgment is Γ⊢c𝑒:𝜏∣𝐸, where 𝐸⋅𝐸′ is list concatenation:
Γ(𝑥)=𝜏
Γ⊢c𝑥:𝜏∣()
C-Var
Γ,𝑥:𝛼⊢c𝑒:𝜏∣𝐸𝛼fresh
Γ⊢c𝜆𝑥.𝑒:𝛼→𝜏∣𝐸
C-Lam
Γ⊢c𝑒1:𝜏1∣𝐸1Γ⊢c𝑒2:𝜏2∣𝐸2𝛽fresh
Γ⊢c𝑒1𝑒2:𝛽∣𝐸1⋅𝐸2⋅(𝜏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 𝜏[𝑆;𝑇]=(𝜏[𝑆])[𝑇]. Its complete clauses are 𝗎𝗇𝗂𝖿𝗒(())=id,𝑈−𝐷𝑜𝑛𝑒𝗎𝗇𝗂𝖿𝗒(𝜏≐𝜏,𝐸)=𝗎𝗇𝗂𝖿𝗒(𝐸),𝑈−𝐷𝑒𝑙𝑒𝑡𝑒𝜏≐𝛼ispreprocessedas𝛼≐𝜏(𝜏notavariable),𝑈−𝑂𝑟𝑖𝑒𝑛𝑡𝗎𝗇𝗂𝖿𝗒(𝛼≐𝜏,𝐸)=let𝑅=[𝜏/𝛼],𝑈=𝗎𝗇𝗂𝖿𝗒(𝐸[𝑅])in𝑅;𝑈,𝑈−𝐸𝑙𝑖𝑚𝑖𝑛𝑎𝑡𝑒𝗎𝗇𝗂𝖿𝗒(𝐹(¯𝜏)≐𝐹(¯𝜌),𝐸)=𝗎𝗇𝗂𝖿𝗒(𝜏1≐𝜌1,…,𝜏𝑛≐𝜌𝑛,𝐸)𝑈−𝐷𝑒𝑐𝑜𝑚𝑝𝑜𝑠𝑒 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
Γ(𝑥)=𝜎𝜎≽𝜏
Γ⊢s𝑥:𝜏
S-Var
Γ,𝑥:𝜏1⊢s𝑒:𝜏2
Γ⊢s𝜆𝑥.𝑒:𝜏1→𝜏2
S-Lam
Γ⊢s𝑒1:𝜏1→𝜏2Γ⊢s𝑒2:𝜏1
Γ⊢s𝑒1𝑒2:𝜏2
S-App
Γ⊢s𝑒1:𝜏1Γ,𝑥:GenΓ(𝜏1)⊢s𝑒2:𝜏2
Γ⊢s𝗅𝖾𝗍𝑥=𝑒1𝗂𝗇𝑒2:𝜏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 𝖶(Γ,𝑥)=(id,𝖿𝗋𝖾𝗌𝗁(Γ(𝑥))),𝖶(Γ,𝜆𝑥.𝑒)=let(𝑆,𝜏)=𝖶((Γ,𝑥:𝛼),𝑒)in(𝑆,𝛼[𝑆]→𝜏),𝖶(Γ,𝑒1𝑒2)=let(𝑆1,𝜏1)=𝖶(Γ,𝑒1),(𝑆2,𝜏2)=𝖶(Γ[𝑆1],𝑒2),𝑈=𝗎𝗇𝗂𝖿𝗒((𝜏1[𝑆2]≐𝜏2→𝛽)),in(𝑆1;𝑆2;𝑈,𝛽[𝑈]),𝖶(Γ,𝗅𝖾𝗍𝑥=𝑒1𝗂𝗇𝑒2)=let(𝑆1,𝜏1)=𝖶(Γ,𝑒1),𝜎=GenΓ[𝑆1](𝜏1),(𝑆2,𝜏2)=𝖶((Γ[𝑆1],𝑥:𝜎),𝑒2),in(𝑆1;𝑆2,𝜏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 Θ;Γ⊢𝖾𝗏𝑑:𝜏, and erasure is defined in definition 4.50.
For lists add 𝖫𝗂𝗌𝗍, nil, cons, and the rules
Γ⊢𝗇𝗂𝗅:𝖫𝗂𝗌𝗍(𝜏)
ListNil
Γ⊢𝑒1:𝜏Γ⊢𝑒2:𝖫𝗂𝗌𝗍(𝜏)
Γ⊢𝖼𝗈𝗇𝗌𝑒1𝑒2:𝖫𝗂𝗌𝗍(𝜏)
ListCons
Γ⊢s𝗇𝗂𝗅:𝖫𝗂𝗌𝗍(𝜏)
S-ListNil
Γ⊢s𝑒1:𝜏Γ⊢s𝑒2:𝖫𝗂𝗌𝗍(𝜏)
Γ⊢s𝖼𝗈𝗇𝗌𝑒1𝑒2:𝖫𝗂𝗌𝗍(𝜏)
S-ListCons
Γ⊢𝑒:𝖫𝗂𝗌𝗍(𝜏)Γ⊢𝑒0:𝜌Γ,ℎ:𝜏,𝑡:𝖫𝗂𝗌𝗍(𝜏)⊢𝑒1:𝜌
Γ⊢𝖼𝖺𝗌𝖾𝑒𝗈𝖿{𝗇𝗂𝗅↦𝑒0;𝖼𝗈𝗇𝗌ℎ𝑡↦𝑒1}:𝜌
ListCase
Γ⊢s𝑒:𝖫𝗂𝗌𝗍(𝜏)Γ⊢s𝑒0:𝜌Γ,ℎ:𝜏,𝑡:𝖫𝗂𝗌𝗍(𝜏)⊢s𝑒1:𝜌
Γ⊢s𝖼𝖺𝗌𝖾𝑒𝗈𝖿{𝗇𝗂𝗅↦𝑒0;𝖼𝗈𝗇𝗌ℎ𝑡↦𝑒1}:𝜌
S-ListCase
W returns (id,𝖫𝗂𝗌𝗍(𝛼)) for nil with fresh 𝛼. For cons it computes (𝑆1,𝜏1)=𝖶(Γ,𝑒1),(𝑆2,𝜏2)=𝖶(Γ[𝑆1],𝑒2),𝑈=𝗎𝗇𝗂𝖿𝗒((𝜏2≐𝖫𝗂𝗌𝗍(𝜏1[𝑆2]))) and returns (𝑆1;𝑆2;𝑈,𝖫𝗂𝗌𝗍(𝜏1[𝑆2;𝑈])). The case clause computes, in order, (𝑆0,𝜏0)=𝖶(Γ,𝑒),𝑈=𝗎𝗇𝗂𝖿𝗒((𝜏0≐𝖫𝗂𝗌𝗍(𝛼))),(𝑆1,𝜌0)=𝖶(Γ[𝑆0;𝑈],𝑒0),(𝑆2,𝜌1)=𝖶((Γ[𝑆0;𝑈;𝑆1],ℎ:𝛼[𝑈;𝑆1],𝑡:𝖫𝗂𝗌𝗍(𝛼[𝑈;𝑆1])),𝑒1),𝑉=𝗎𝗇𝗂𝖿𝗒((𝜌0[𝑆2]≐𝜌1)), and returns (𝑆0;𝑈;𝑆1;𝑆2;𝑉,𝜌1[𝑉]).
For references, add 𝖴𝗇𝗂𝗍, 𝖱𝖾𝖿(𝜏), locations, and the standard rules
Γ⊢𝗎𝗇𝗂𝗍:𝖴𝗇𝗂𝗍
Unit
Γ⊢𝑒:𝜏
Γ⊢𝗋𝖾𝖿𝑒:𝖱𝖾𝖿(𝜏)
Ref
Γ⊢𝑒:𝖱𝖾𝖿(𝜏)
Γ⊢!𝑒:𝜏
Deref
Γ⊢𝑒1:𝖱𝖾𝖿(𝜏)Γ⊢𝑒2:𝜏
Γ⊢𝑒1:=𝑒2:𝖴𝗇𝗂𝗍
Assign
The conservative value restriction replaces unrestricted generalization at let by
Γ⊢𝑣:𝜏1Γ,𝑥:GenΓ(𝜏1)⊢𝑒2:𝜏2
Γ⊢𝗅𝖾𝗍𝑥=𝑣𝗂𝗇𝑒2:𝜏2
Let-Gen
Γ⊢𝑒1:𝜏1Γ,𝑥:𝜏1⊢𝑒2:𝜏2
Γ⊢𝗅𝖾𝗍𝑥=𝑒1𝗂𝗇𝑒2:𝜏2
Let-Mono
where 𝑣 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
Γ⊢s𝑣:𝜏1Γ,𝑥:GenΓ(𝜏1)⊢s𝑒2:𝜏2
Γ⊢s𝗅𝖾𝗍𝑥=𝑣𝗂𝗇𝑒2:𝜏2
S-Let-Gen
Γ⊢s𝑒1:𝜏1Γ,𝑥:𝜏1⊢s𝑒2:𝜏2
Γ⊢s𝗅𝖾𝗍𝑥=𝑒1𝗂𝗇𝑒2:𝜏2
S-Let-Mono
The first rule requires a generalizable form and the second a nongeneralizable expression. The store forms are
Γ⊢s𝗎𝗇𝗂𝗍:𝖴𝗇𝗂𝗍
S-Unit
Γ⊢s𝑒:𝜏
Γ⊢s𝗋𝖾𝖿𝑒:𝖱𝖾𝖿(𝜏)
S-Ref
Γ⊢s𝑒:𝖱𝖾𝖿(𝜏)
Γ⊢s!𝑒:𝜏
S-Deref
Γ⊢s𝑒1:𝖱𝖾𝖿(𝜏)Γ⊢s𝑒2:𝜏
Γ⊢s𝑒1:=𝑒2:𝖴𝗇𝗂𝗍
S-Assign
At run time a store typing Σ maps locations to monotypes, and
ℓ∈dom(Σ)
Γ⊢Σℓ:𝖱𝖾𝖿(Σ(ℓ))
Loc
Γ⊢Σ𝑒:𝜎𝛼∉ftv(Γ)∪ftv(Σ)
Γ⊢Σ𝑒:∀𝛼.𝜎
GenΣ
Γ⊢Σ𝑣:𝜏1Γ,𝑥:GenΓ,Σ(𝜏1)⊢Σ𝑒2:𝜏2
Γ⊢Σ𝗅𝖾𝗍𝑥=𝑣𝗂𝗇𝑒2:𝜏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 (𝜇,𝗋𝖾𝖿𝑣)⟶(𝜇[ℓ↦𝑣],ℓ)(ℓ∉dom(𝜇)),(𝜇,!ℓ)⟶(𝜇,𝜇(ℓ)),(𝜇,ℓ:=𝑣)⟶(𝜇[ℓ↦𝑣],𝗎𝗇𝗂𝗍).