Exercise 3.1.
For (a), first alpha-rename the quantified variables so that all prefixes are disjoint. The substitution [𝛾/𝛼,𝛾/𝛽] sends the body 𝛼 →𝛽 to 𝛾 →𝛾. By lemma 3.9, ∀𝛼∀𝛽.𝛼→𝛽⊒∀𝛾.𝛾→𝛾.
For (b), the relation fails. An instance of ∀𝛼∀𝛽.𝛼 →𝛽 may have unequal domain and codomain, for example 𝖭𝖺𝗍 →𝖡𝗈𝗈𝗅. Every instance of ∀𝛾.𝛾 →𝛾 has identical domain and codomain, so no instantiation produces that arrow.
For (c), the free 𝛿 is fixed and [𝛿/𝛼](𝛼 →𝛿) =𝛿 →𝛿. Hence ∀𝛼.𝛼→𝛿⊒𝛿→𝛿.
For (d), alpha-rename the scheme on the right to ∀𝜖.𝜖 →𝜖, with 𝜖 fresh. If the generality relation held, the characterization lemma would give a monotype 𝜌 with 𝜌→𝛿=𝜖→𝜖. Constructor injectivity would force both 𝜌 =𝜖 and 𝛿 =𝜖. The latter is impossible: 𝛿 is free and fixed on the left, whereas 𝜖 is the freshly bound variable on the right. Thus the relation in (d) fails.
Exercise 3.2.
The arithmetic context has no free type variables. Therefore GenΓ0((𝛼→𝛼)→𝛼→𝛼)=∀𝛼.(𝛼→𝛼)→𝛼→𝛼,GenΓ0,𝑓:𝛼→𝛽(𝛼→(𝛽→𝛾)→𝛾)=∀𝛾.𝛼→(𝛽→𝛾)→𝛾. In the second line, 𝛼 and 𝛽 are free in the context and only 𝛾 is generalized.
For (c), ftv(∀𝛼.𝛼→𝛽)={𝛽},ftv(Γ0,𝑓:∀𝛼.𝛼→𝛽)={𝛽}. The 𝛼 in the proposed result type is therefore not fixed by the context, and GenΓ0,𝑓:∀𝛼.𝛼→𝛽(𝛼→𝛽)=∀𝛼.𝛼→𝛽.
For the requested instance of lemma 3.15, start from (b) and 𝑆 =[𝖭𝖺𝗍/𝛼]. Rename the generalized variable 𝛾 to a fresh 𝛾′ before applying 𝑆: 𝑇=[𝛾′/𝛾];𝑆. Then 𝑇 agrees with 𝑆 on the free variables 𝛼,𝛽 of the context, Γ[𝑇]=Γ[𝑆]=Γ0,𝑓:𝖭𝖺𝗍→𝛽, and GenΓ[𝑆](𝜏[𝑇])=∀𝛾′.𝖭𝖺𝗍→(𝛽→𝛾′)→𝛾′. On the other hand, GenΓ(𝜏)[𝑆]=∀𝛾.𝖭𝖺𝗍→(𝛽→𝛾)→𝛾. The two schemes are alpha-equivalent, so the required generality relation holds, in fact in both directions.
Exercise 3.3.
For (a), use two monomorphic assumptions and then generalize. Written one rule application per line, the complete derivation is Γ0,𝑥:𝛼,𝑦:𝛽⊢𝑥:𝛼(𝑉𝑎𝑟),Γ0,𝑥:𝛼⊢𝜆𝑦.𝑥:𝛽→𝛼(𝐿𝑎𝑚),Γ0⊢𝜆𝑥.𝜆𝑦.𝑥:𝛼→𝛽→𝛼(𝐿𝑎𝑚),Γ0⊢𝜆𝑥.𝜆𝑦.𝑥:∀𝛼∀𝛽.𝛼→𝛽→𝛼(𝐺𝑒𝑛 𝛼,𝛽). Both side conditions hold because Γ0 has no free type variables.
For (b), let 𝜎𝗂𝖽 =∀𝛼.𝛼 →𝛼. The bound expression has that scheme by Var, Lam, and Gen. In the body, two independent Inst steps give Γ0,𝗂𝖽:𝜎𝗂𝖽⊢𝗂𝖽:(𝛽→𝛽)→(𝛽→𝛽),Γ0,𝗂𝖽:𝜎𝗂𝖽⊢𝗂𝖽:𝛽→𝛽. Rule App combines them: Γ0,𝗂𝖽:𝜎𝗂𝖽⊢𝗂𝖽𝗂𝖽:𝛽→𝛽. Together with the typing of the bound identity, Let yields Γ0⊢𝗅𝖾𝗍 𝗂𝖽=𝜆𝑥.𝑥 𝗂𝗇 𝗂𝖽𝗂𝖽:𝛽→𝛽. Finally 𝛽 ∉ftv(Γ0), so one Gen step proves part (c): Γ0⊢𝗅𝖾𝗍 𝗂𝖽=𝜆𝑥.𝑥 𝗂𝗇 𝗂𝖽𝗂𝖽:∀𝛽.𝛽→𝛽.
Exercise 3.4.
Give the lambda-bound variables types 𝛼𝑓,𝛼𝑔,𝛼𝑥. Give 𝑔 𝑥 the fresh result type 𝛽 and 𝑓 (𝑔 𝑥) the fresh result type 𝛾. The two application nodes force exactly 𝛼𝑔≐𝛼𝑥→𝛽,𝛼𝑓≐𝛽→𝛾. Eliminating 𝛼𝑔 and 𝛼𝑓 gives the MGU 𝑈=[𝛼𝑥→𝛽/𝛼𝑔,𝛽→𝛾/𝛼𝑓]. The provisional type of the three lambdas is 𝛼𝑓 →𝛼𝑔 →𝛼𝑥 →𝛾; applying 𝑈 gives (𝛽→𝛾)→(𝛼𝑥→𝛽)→𝛼𝑥→𝛾. All three remaining variables are absent from Γ0. Renaming 𝛼𝑥 to 𝛼 and generalizing gives ∀𝛼∀𝛽∀𝛾.(𝛽→𝛾)→(𝛼→𝛽)→𝛼→𝛾.
exercise 3.5.
Let 𝐸0 be the printed two-equation list. Decomposition and elimination produce the following complete sequence: 𝐸0:=((𝛼→𝛽)→𝛾≐(𝖭𝖺𝗍→𝖡𝗈𝗈𝗅)→𝛿,𝛿≐𝖭𝖺𝗍),𝐸1𝑈−𝐷𝑒𝑐𝑜𝑚𝑝𝑜𝑠𝑒𝑜𝑛𝑡ℎ𝑒𝑜𝑢𝑡𝑒𝑟𝑎𝑟𝑟𝑜𝑤𝑠:=(𝛼→𝛽≐𝖭𝖺𝗍→𝖡𝗈𝗈𝗅,𝛾≐𝛿,𝛿≐𝖭𝖺𝗍),𝐸2𝑈−𝐷𝑒𝑐𝑜𝑚𝑝𝑜𝑠𝑒𝑜𝑛𝛼→𝛽:=(𝛼≐𝖭𝖺𝗍,𝛽≐𝖡𝗈𝗈𝗅,𝛾≐𝛿,𝛿≐𝖭𝖺𝗍),𝑅1𝑈−𝐸𝑙𝑖𝑚𝑖𝑛𝑎𝑡𝑒𝑓𝑜𝑟𝛼:=[𝖭𝖺𝗍/𝛼],𝐸3𝑡𝑎𝑖𝑙𝑜𝑓𝐸2[𝑅1]:=(𝛽≐𝖡𝗈𝗈𝗅,𝛾≐𝛿,𝛿≐𝖭𝖺𝗍),𝑅2𝑈−𝐸𝑙𝑖𝑚𝑖𝑛𝑎𝑡𝑒𝑓𝑜𝑟𝛽:=[𝖡𝗈𝗈𝗅/𝛽],𝐸4𝑡𝑎𝑖𝑙𝑜𝑓𝐸3[𝑅2]:=(𝛾≐𝛿,𝛿≐𝖭𝖺𝗍),𝑅3𝑈−𝐸𝑙𝑖𝑚𝑖𝑛𝑎𝑡𝑒𝑓𝑜𝑟𝛾:=[𝛿/𝛾],𝐸5𝑡𝑎𝑖𝑙𝑜𝑓𝐸4[𝑅3]:=(𝛿≐𝖭𝖺𝗍),𝑅4𝑈−𝐸𝑙𝑖𝑚𝑖𝑛𝑎𝑡𝑒𝑓𝑜𝑟𝛿:=[𝖭𝖺𝗍/𝛿],𝐸6:=(). The algorithm returns, in diagrammatic order, 𝑅1;𝑅2;𝑅3;𝑅4. It sends 𝛼,𝛾,𝛿 to 𝖭𝖺𝗍 and 𝛽 to 𝖡𝗈𝗈𝗅. If the last initial equation is 𝛿 ≐𝛿 →𝖭𝖺𝗍, the same two decompositions apply. The factors 𝑅1 and 𝑅2 do not mention 𝛿, and 𝑅3 changes only 𝛾, so that last equation remains 𝛿 ≐𝛿 →𝖭𝖺𝗍. Since 𝛿 occurs properly on its right, U-Eliminate is forbidden and the occurs-check failure clause applies.
exercise 3.6.
Give 𝑓 the fresh type 𝛼 and 𝑥 the fresh type 𝛽. The innermost application introduces fresh 𝛾 and solves 𝛼≐𝛽→𝛾,𝑆1=[𝛽→𝛾/𝛼]. For the middle application, fresh 𝛿 stands for the result. After applying 𝑆1, its ordered equation is 𝛽→𝛾≐𝛾→𝛿. Left-to-right decomposition produces (𝛽 ≐𝛾,𝛾 ≐𝛿). The first elimination is [𝛾/𝛽]; it leaves 𝛾 ≐𝛿, whose elimination is [𝛿/𝛾]. Thus the deterministic composite is 𝑆2=[𝛾/𝛽];[𝛿/𝛾]=[𝛿/𝛽,𝛿/𝛾]. Applying 𝑆1;𝑆2 to the provisional lambda type 𝛼 →𝛽 →𝛿 already yields the twice-shaped type. The third, outermost application introduces fresh 𝜖 and solves 𝛼[𝑆1;𝑆2]≐𝛿→𝜖,𝛿→𝛿≐𝛿→𝜖. Decomposition deletes the reflexive domain equation and returns 𝑆3 =[𝜖/𝛿]. Applying the full composite to the provisional lambda type 𝛼 →𝛽 →𝜖 yields (𝜖→𝜖)→𝜖→𝜖. Since 𝜖 is absent from Γ0, generalization returns ∀𝜖.(𝜖 →𝜖) →𝜖 →𝜖. The third use of 𝑓 forces only the already-known equality of its input and output type, so the principal scheme is the same as for twice.
Exercise 3.7.
Write the scheme inferred for 𝖼𝗈𝗆𝗉𝗈𝗌𝖾 as 𝐶=∀𝛼∀𝛽∀𝛾.(𝛽→𝛾)→(𝛼→𝛽)→𝛼→𝛾. The let-bound definition is generalized to 𝐶. In the body 𝑐 𝑐, take two disjoint fresh instances: 𝐶1=(𝛽1→𝛾1)→(𝛼1→𝛽1)→𝛼1→𝛾1,𝐶2=(𝛽2→𝛾2)→(𝛼2→𝛽2)→𝛼2→𝛾2. If 𝜌 is the fresh result type of the application, W solves 𝐶1 ≐𝐶2 →𝜌. Arrow decomposition first gives 𝛽1→𝛾1≐𝐶2,𝜌≐(𝛼1→𝛽1)→𝛼1→𝛾1. Decomposing the first equation gives the MGU components 𝛽1↦𝛽2→𝛾2,𝛾1↦(𝛼2→𝛽2)→𝛼2→𝛾2. Thus the body has monotype (𝛼1→𝛽2→𝛾2)→𝛼1→(𝛼2→𝛽2)→𝛼2→𝛾2. The four displayed variables are generalized over Γ0.
The corresponding explicitly instantiated core term is 𝗅𝖾𝗍 𝑐:𝐶=𝜆(𝑓:𝛽→𝛾).𝜆(𝑔:𝛼→𝛽).𝜆(𝑥:𝛼).𝑓(𝑔𝑥) 𝗂𝗇𝑐⟨𝛼1,𝛽2→𝛾2,(𝛼2→𝛽2)→𝛼2→𝛾2⟩𝑐⟨𝛼2,𝛽2,𝛾2⟩. The first static instance is precisely the function type required to accept the second instance as its first argument. Erasing annotations and type arguments returns the source term.
Exercise 3.8.
Work under 𝑑 :𝛼,𝑥𝑠 :𝛽. The list clause chooses fresh 𝛾. The scrutinee call returns (id,𝛽), and the first equation is 𝛽≐𝖫𝗂𝗌𝗍(𝛾). Its MGU is 𝑈 =[𝖫𝗂𝗌𝗍(𝛾)/𝛽]. The nil branch is the variable 𝑑, so it returns (id,𝛼). The cons branch is checked under 𝑑:𝛼,𝑥𝑠:𝖫𝗂𝗌𝗍(𝛾),ℎ:𝛾,𝑡:𝖫𝗂𝗌𝗍(𝛾). Its body is ℎ, so it returns (id,𝛾). The final branch equation is 𝛼 ≐𝛾, with 𝑉 =[𝛾/𝛼]. Hence the list clause returns (𝑈;𝑉,𝛾),𝛽[𝑈;𝑉]=𝖫𝗂𝗌𝗍(𝛾),𝛼[𝑈;𝑉]=𝛾. The two enclosing lambda clauses therefore return 𝛾→𝖫𝗂𝗌𝗍(𝛾)→𝛾. Over the empty context, generalization gives ∀𝛾.𝛾→𝖫𝗂𝗌𝗍(𝛾)→𝛾, which is the scheme in example 3.38, up to renaming.
exercise 3.9.
The allocation expression receives 𝖱𝖾𝖿(𝛼 →𝛼). Since it is not a generalizable form, Let-Mono binds 𝑟 :𝖱𝖾𝖿(𝛼 →𝛼) with the same free 𝛼. Typing 𝑟 :=(𝜆𝑥.𝗌𝗎𝖼𝖼 𝑥) produces 𝖱𝖾𝖿(𝛼→𝛼)≐𝖱𝖾𝖿(𝖭𝖺𝗍→𝖭𝖺𝗍), so unification fixes 𝛼 =𝖭𝖺𝗍. Dereferencing 𝑟 therefore returns a function of type 𝖭𝖺𝗍 →𝖭𝖺𝗍, while the final application to 𝗍𝗋𝗎𝖾 demands the equation 𝖭𝖺𝗍 ≐𝖡𝗈𝗈𝗅. Its distinct nullary constructors trigger the clash rule. By contrast, 𝜆𝑥.𝑥 is a generalizable form, so Let-Gen still assigns it ∀𝛼.𝛼 →𝛼.
Exercise 3.10.
In the first example, 𝜆𝑓.𝗅𝖾𝗍 𝑛=𝑓𝗓𝖾𝗋𝗈 𝗂𝗇 𝑓𝗍𝗋𝗎𝖾, rule Lam puts one monotype for 𝑓 in the context. The first application requires its domain to be 𝖭𝖺𝗍, while the second requires the same domain to be 𝖡𝗈𝗈𝗅. The rigid mismatch prevents a derivation. In an explicitly typed extension, the binder would be 𝑓 :∀𝛼.𝛼 →𝛼, and the two occurrences would be written 𝑓⟨𝖭𝖺𝗍⟩ 𝗓𝖾𝗋𝗈 and 𝑓⟨𝖡𝗈𝗈𝗅⟩ 𝗍𝗋𝗎𝖾. A value supplied for 𝑓 could be the explicit abstraction Λ𝛼.𝜆(𝑥 :𝛼).𝑥.
The second example asks for an arrow whose domain is itself ∀𝛼.𝛼 →𝛼. The monotype grammar of definition 3.6 has no ∀ constructor, so such an arrow is not an HM monotype and cannot annotate a lambda-bound variable. In an extended syntax the binder carries that polymorphic annotation, and each use again contains an explicit type application such as 𝑓⟨𝖭𝖺𝗍⟩ 𝗓𝖾𝗋𝗈.
The third example fails at instantiation. HM’s Inst substitutes monotypes for quantified variables, but ∀𝛼.𝛼 →𝛼 is a scheme rather than a monotype. Hence the identity cannot be instantiated at its own polymorphic type. The displayed extended term places that scheme in an explicit type-application bracket and uses Λ at the two polymorphic values. In all three cases those annotations and applications are part of the extended source program; Algorithm W does not infer them.
Exercise 3.11.
The variable 𝜑 is inherited from the declaration of 𝑓 and is free in the input context. To infer the definition of 𝑘, W gives 𝑥 a fresh type 𝛼. The body 𝑓 has type 𝜑, so 𝜆𝑥.𝑓:𝛼→𝜑. Generalization is relative to Γ0,𝑓 :𝜑: ftv(𝛼→𝜑)∖ftv(Γ0,𝑓:𝜑)={𝛼,𝜑}∖{𝜑}={𝛼}. Thus the let-bound declaration is 𝑘:∀𝛼.𝛼→𝜑.
At the occurrence 𝑘 𝗓𝖾𝗋𝗈, instantiate the prefix by a fresh 𝛽, obtaining 𝑘 :𝛽 →𝜑. If 𝛾 is the fresh application-result variable, unification solves 𝛽→𝜑≐𝖭𝖺𝗍→𝛾 with the deterministic eliminations [𝖭𝖺𝗍/𝛽] and [𝛾/𝜑]. The complete term therefore has result type 𝛾. Up to identity action on the other fresh variables, W’s principal pair is ([𝖭𝖺𝗍/𝛽,𝛾/𝜑],𝛾). Thus the returned substitution renames the inherited context parameter 𝜑 to the fresh result parameter 𝛾. This is still principal: the factor [𝜑/𝛾] recovers every typing over the original context, exactly as theorem 3.36, corollary 4.49 state. The fresh variables are 𝛼 for the definition, 𝛽 for the independent use of its scheme, and 𝛾 for the application result.
Exercise 3.12.
Process the equations first in their printed order. Eliminating 𝛼, then 𝛽, then 𝛾 produces the factors 𝑅1=[𝛽→𝛾/𝛼],𝑅2=[𝖭𝖺𝗍/𝛽],𝑅3=[𝛿/𝛾]. The returned composite 𝑈1 =𝑅1;𝑅2;𝑅3 acts on the problem variables by 𝛼[𝑈1]=𝖭𝖺𝗍→𝛿,𝛽[𝑈1]=𝖭𝖺𝗍,𝛾[𝑈1]=𝛿,𝛿[𝑈1]=𝛿.
Now process (𝛾≐𝛿,𝛽≐𝖭𝖺𝗍,𝛼≐𝛽→𝛾). The factors occur in the different order 𝑅′1=[𝛿/𝛾],𝑅′2=[𝖭𝖺𝗍/𝛽],𝑅′3=[𝖭𝖺𝗍→𝛿/𝛼], and 𝑈2 =𝑅′1;𝑅′2;𝑅′3. Direct calculation gives the same four images as for 𝑈1. Thus 𝑈1={𝛼,𝛽,𝛾,𝛿}𝑈2;id,𝑈2={𝛼,𝛽,𝛾,𝛿}𝑈1;id. Although the lists of elimination factors differ, the two returned substitutions mutually factor on every problem variable. More generally, the MGU theorem gives such factors even when different legal traversals choose different variable representatives, so the solution family does not depend on the work-list order.
Exercise 3.13.
Give the identity value the monotype 𝛼 →𝛼. Allocation then has type 𝗋𝖾𝖿(𝜆𝑥.𝑥):𝖱𝖾𝖿(𝛼→𝛼). The allocation is expansive, so the first binding must use Let-Mono; it introduces 𝑟:𝖱𝖾𝖿(𝛼→𝛼) with no generalized variable.
The expression bound to 𝑠 is the variable 𝑟, hence it is nonexpansive and the generalized let rule is syntactically available. Nevertheless 𝛼 occurs free in the surrounding declaration of 𝑟, so GenΓ0,𝑟:𝖱𝖾𝖿(𝛼→𝛼)(𝖱𝖾𝖿(𝛼→𝛼))=𝖱𝖾𝖿(𝛼→𝛼). The prefix is empty. Thus the whole term has the same monomorphic reference type.
Operationally the first binding allocates one location ℓ containing the identity. The second let reduces by substituting that existing location: 𝗅𝖾𝗍 𝑟=ℓ 𝗂𝗇 𝗅𝖾𝗍 𝑠=𝑟 𝗂𝗇 𝑠⇝0𝗅𝖾𝗍 𝑠=ℓ 𝗂𝗇 𝑠⇝0ℓ. No second cell is allocated. Hence 𝑟 and 𝑠 are aliases and must share the one monomorphic store type assigned to ℓ.
Exercise 3.14.
The only monotype instance of 𝖭𝖺𝗍 is 𝖭𝖺𝗍 itself. Instantiating the vacuous prefix in ∀𝛼.𝖭𝖺𝗍 also always returns 𝖭𝖺𝗍, because 𝛼 does not occur in the body. Therefore each scheme is at least as general as the other, although they are not alpha-equivalent: alpha-renaming may change a bound name but cannot add or remove a quantifier.
Consequently principality is uniqueness in the preorder of generality, or uniqueness after quotienting by equality of instance sets, not uniqueness of literal printed syntax. A canonical printing convention removes this example by deleting every vacuous quantifier, equivalently by permitting in a prefix only variables that occur free in the scheme body. The definition of Gen already follows that convention.
Exercise 3.15.
The bound application is pure and reduces to the identity, but it is not a generalizable form. Under the conservative restriction it is therefore checked by Let-Mono. Give the resulting identity the single monotype 𝛼 →𝛼 and introduce 𝑖 at that monotype.
The first use, 𝑖 𝗓𝖾𝗋𝗈, generates 𝛼→𝛼≐𝖭𝖺𝗍→𝛽, so unification sets 𝛼 =𝖭𝖺𝗍 and 𝛽 =𝖭𝖺𝗍. The inner binding of 𝑛 does not change the type of 𝑖. The final use 𝑖 𝗍𝗋𝗎𝖾 then requires 𝖭𝖺𝗍→𝖭𝖺𝗍≐𝖡𝗈𝗈𝗅→𝛾, whose domain equation 𝖭𝖺𝗍 ≐𝖡𝗈𝗈𝗅 is a rigid mismatch. That is the exact rejection.
A sound effect analysis could certify that evaluation of (𝜆𝑓.𝑓)(𝜆𝑥.𝑥) neither allocates a reference nor reads, writes, or otherwise mutates shared state. It could then generalize its result to ∀𝛼.𝛼 →𝛼, allowing the two uses to receive independent 𝖭𝖺𝗍 and 𝖡𝗈𝗈𝗅 instances. The same analysis must refuse that certificate for 𝑃𝗋𝖾𝖿: its bound expression performs allocation, and the later assignment mutates the allocated cell. Thus the effect-based relaxation accepts the pure application without reintroducing polymorphic references.
Practical route.
The inferencer requested by exercise 4.16 is built in appendix F; its exact Kappa acceptance oracle is recorded in appendix E.