Exercise 2.1.
The inserted conditional has free variable 𝑦, so rename the displayed binder to a fresh 𝑢 before substituting: (𝜆𝑦:𝟐.𝗂𝖿(𝑥;𝑦;𝑥))[𝗂𝖿(𝑦;𝗍𝗍;𝖿𝖿)/𝑥]=𝛼(𝜆𝑢:𝟐.𝗂𝖿(𝑥;𝑢;𝑥))[𝗂𝖿(𝑦;𝗍𝗍;𝖿𝖿)/𝑥]=𝜆𝑢:𝟐.𝗂𝖿(𝗂𝖿(𝑦;𝗍𝗍;𝖿𝖿);𝑢;𝗂𝖿(𝑦;𝗍𝗍;𝖿𝖿)). The two displayed occurrences of 𝑦, one in each inserted copy, are free; the binder binds only 𝑢.
For the second term, the binder shadows the substitution variable. The stopping equation for substitution therefore gives (𝜆𝑥:𝟐.𝑥)[𝗍𝗍/𝑥]=𝜆𝑥:𝟐.𝑥, not 𝜆𝑥 :𝟐. 𝗍𝗍. Substitution replaces free occurrences only.
Exercise 2.2.
Let Γ =𝑥 :𝟐,𝑦 :𝟐. The full derivation for or is (𝑥:𝟐)∈ΓΓ⊢𝑥:𝟐Var𝑋Γ⊢𝗍𝗍:𝟐True(𝑦:𝟐)∈ΓΓ⊢𝑦:𝟐VarΓ⊢𝗂𝖿(𝑥;𝗍𝗍;𝑦):𝟐If𝑥:𝟐⊢𝜆𝑦:𝟐.𝗂𝖿(𝑥;𝗍𝗍;𝑦):𝟐→𝟐Lam⋅⊢or:𝟐→𝟐→𝟐Lam.
Take xor:=𝜆𝑥:𝟐.𝜆𝑦:𝟐.𝗂𝖿(𝑥;𝗂𝖿(𝑦;𝖿𝖿;𝗍𝗍);𝑦). Its body derivation is the complete tree X=(𝑥:𝟐)∈ΓΓ⊢𝑥:𝟐Var(𝑦:𝟐)∈ΓΓ⊢𝑦:𝟐Var𝑋Γ⊢𝖿𝖿:𝟐False𝑋Γ⊢𝗍𝗍:𝟐TrueΓ⊢𝗂𝖿(𝑦;𝖿𝖿;𝗍𝗍):𝟐If(𝑦:𝟐)∈ΓΓ⊢𝑦:𝟐VarΓ⊢𝗂𝖿(𝑥;𝗂𝖿(𝑦;𝖿𝖿;𝗍𝗍);𝑦):𝟐If. The two abstraction nodes complete the typing derivation: X𝑥:𝟐⊢𝜆𝑦:𝟐.𝗂𝖿(𝑥;𝗂𝖿(𝑦;𝖿𝖿;𝗍𝗍);𝑦):𝟐→𝟐Lam⋅⊢xor:𝟐→𝟐→𝟐Lam.
Exercise 2.3.
Any typing of 𝗂𝖿(𝜆𝑥 :𝟐. 𝑥;𝗍𝗍;𝖿𝖿) must end in If. Its guard premise would require Γ⊢𝜆𝑥:𝟐.𝑥:𝟐. But the only final rule for an abstraction is Lam, whose result type is an arrow, here 𝟐 →𝟐, never 𝟐. Thus the guard premise fails.
Any typing of 𝖿𝖿 (𝜆𝑥 :𝟐. 𝑥) must end in App. Its function premise requires Γ ⊢𝖿𝖿 :𝐴 →𝐶 for some 𝐴,𝐶. The only final rule for 𝖿𝖿 is False, which assigns 𝟐, not an arrow. Hence that premise fails in every context.
Exercise 2.4.
Renaming the three variable leaves and rebuilding the conditional gives (𝑦:𝟐)∈𝑦:𝟐𝑦:𝟐⊢𝑦:𝟐Var(𝑦:𝟐)∈𝑦:𝟐𝑦:𝟐⊢𝑦:𝟐Var𝑋𝑦:𝟐⊢𝖿𝖿:𝟐False𝑦:𝟐⊢𝗂𝖿(𝑦;𝑦;𝖿𝖿):𝟐If. Every node is the image of the corresponding node in the original tree.
The premise in example 2.6 is displayed under 𝑥 :𝟐. Renaming 𝑥 to fresh 𝑢 gives 𝑢:𝟐∈𝑢:𝟐𝑢:𝟐⊢𝑢:𝟐Var𝑋𝑢:𝟐⊢𝖿𝖿:𝟐False𝑋𝑢:𝟐⊢𝗍𝗍:𝟐True𝑢:𝟐⊢𝗂𝖿(𝑢;𝖿𝖿;𝗍𝗍):𝟐If. Applying Lam produces 𝜆𝑢 :𝟐. 𝗂𝖿(𝑢;𝖿𝖿;𝗍𝗍), which is alpha-equivalent to the original 𝜆𝑥 :𝟐. 𝗂𝖿(𝑥;𝖿𝖿;𝗍𝗍).
Exercise 2.5.
Let 𝑎 =𝗂𝖿(𝗍𝗍;𝖿𝖿;𝗍𝗍). The two premise derivations for typed substitution are 𝑥:𝟐∈𝑥:𝟐,𝑦:𝟐𝑥:𝟐,𝑦:𝟐⊢𝑥:𝟐Var𝑦:𝟐∈𝑥:𝟐,𝑦:𝟐𝑥:𝟐,𝑦:𝟐⊢𝑦:𝟐Var𝑋𝑥:𝟐,𝑦:𝟐⊢𝖿𝖿:𝟐False𝑥:𝟐,𝑦:𝟐⊢𝗂𝖿(𝑥;𝑦;𝖿𝖿):𝟐If𝑥:𝟐⊢𝜆𝑦:𝟐.𝗂𝖿(𝑥;𝑦;𝖿𝖿):𝟐→𝟐Lam, and 𝑋⋅⊢𝗍𝗍:𝟐True𝑋⋅⊢𝖿𝖿:𝟐False𝑋⋅⊢𝗍𝗍:𝟐True⋅⊢𝑎:𝟐If. Weakening the second tree inserts 𝑦 :𝟐, giving the same If tree with all three constant conclusions under 𝑦 :𝟐; call it A𝑦 :𝑦 :𝟐 ⊢𝑎 :𝟐. Substitution replaces the first guard leaf, while the 𝑦-leaf and false branch remain: A𝑦𝑦:𝟐∈𝑦:𝟐𝑦:𝟐⊢𝑦:𝟐Var𝑋𝑦:𝟐⊢𝖿𝖿:𝟐False𝑦:𝟐⊢𝗂𝖿(𝑎;𝑦;𝖿𝖿):𝟐If⋅⊢𝜆𝑦:𝟐.𝗂𝖿(𝑎;𝑦;𝖿𝖿):𝟐→𝟐Lam. The first premise of the rebuilt If is precisely the weakened inserted derivation.
Exercise 2.6.
For guard congruence, typing inversion and the induction hypothesis transform the tree as follows: Γ⊢𝑒:𝟐Γ⊢𝑒1:𝐶Γ⊢𝑒2:𝐶Γ⊢𝗂𝖿(𝑒;𝑒1;𝑒2):𝐶If When 𝑒 ⟼𝑒′, the induction hypothesis changes the first premise and the rebuilt tree is Γ⊢𝑒′:𝟐Γ⊢𝑒1:𝐶Γ⊢𝑒2:𝐶Γ⊢𝗂𝖿(𝑒′;𝑒1;𝑒2):𝐶If. All three premises of the rebuilt rule are displayed.
For the two root contractions, inversion already contains the selected branch: Γ⊢𝗍𝗍:𝟐Γ⊢𝑒1:𝐶Γ⊢𝑒2:𝐶Γ⊢𝗂𝖿(𝗍𝗍;𝑒1;𝑒2):𝐶If⇝Γ⊢𝑒1:𝐶, Γ⊢𝖿𝖿:𝟐Γ⊢𝑒1:𝐶Γ⊢𝑒2:𝐶Γ⊢𝗂𝖿(𝖿𝖿;𝑒1;𝑒2):𝐶If⇝Γ⊢𝑒2:𝐶. Both arrows are metalevel transformations of derivation trees, not term steps. Thus every conditional rule preserves the result type 𝐶.
Exercise 2.7.
The complete derivation is the zero-premise introduction instance 𝑋𝑥:𝐴⊢⋆:𝟏Unit−I. If a closed value 𝑣 has type 𝟏, inspect its value form and invert its typing. A lambda has an arrow type, a Boolean has type 𝟐, a pair has a product type, and an injection has a sum type. Disjointness of type constructors excludes all four possibilities, leaving 𝑣 = ⋆.
Exercise 2.8.
For 𝐴 𝗍𝗒𝗉𝖾, the required derivation is (𝑥:𝟎)∈(𝑥:𝟎,𝑦:𝐴)𝑥:𝟎,𝑦:𝐴⊢𝑥:𝟎Var𝐴 𝗍𝗒𝗉𝖾𝑋𝟐 𝗍𝗒𝗉𝖾Ty−Bool𝐴×𝟐 𝗍𝗒𝗉𝖾Ty−Prod𝑥:𝟎,𝑦:𝐴⊢𝖺𝖻𝗈𝗋𝗍𝐴×𝟐(𝑥):𝐴×𝟐Empty−E. Abort is not a value form. Its only evaluation rule is E-Abort, whose premise would require a step from the variable 𝑥; no evaluation rule has a variable source. Hence this open neutral term has no root or congruence step.
Exercise 2.7.
Recall 𝖢𝗈𝗅𝗈𝗋 =𝟏 +(𝟏 +𝟏), with red the outer left injection, amber the outer-right/inner-left injection, and green the outer-right/inner-right injection. Abbreviate 𝐾(𝑢):=𝖼𝖺𝗌𝖾(𝑢;𝑎.𝗋𝖾𝖽;𝑔.𝖺𝗆𝖻𝖾𝗋),𝐿(𝑐):=𝖼𝖺𝗌𝖾(𝑐;𝑟.𝗀𝗋𝖾𝖾𝗇;𝑢.𝐾(𝑢)), and define next:=𝜆𝑐 :𝖢𝗈𝗅𝗈𝗋. 𝐿(𝑐). For any context Θ, let RΘ, AΘ, and GΘ be the following complete constructor derivations. Here U is the axiom 𝟏 𝗍𝗒𝗉𝖾, while S is Ty-Sum applied to two copies of U, deriving 𝟏 +𝟏 𝗍𝗒𝗉𝖾: RΘ=𝑋Θ⊢⋆:𝟏Unit−ISΘ⊢𝗋𝖾𝖽:𝖢𝗈𝗅𝗈𝗋Inl, AΘ=U𝑋Θ⊢⋆:𝟏Unit−IUΘ⊢𝗂𝗇𝗅(⋆):𝟏+𝟏InlΘ⊢𝖺𝗆𝖻𝖾𝗋:𝖢𝗈𝗅𝗈𝗋Inr, and GΘ=UU𝑋Θ⊢⋆:𝟏Unit−IΘ⊢𝗂𝗇𝗋(⋆):𝟏+𝟏InrΘ⊢𝗀𝗋𝖾𝖾𝗇:𝖢𝗈𝗅𝗈𝗋Inr. Put Γ =𝑐 :𝖢𝗈𝗅𝗈𝗋 and Δ =Γ,𝑢 :𝟏 +𝟏. These constructor trees make every premise in the typing derivation explicit: (𝑐:𝖢𝗈𝗅𝗈𝗋)∈ΓΓ⊢𝑐:𝖢𝗈𝗅𝗈𝗋VarGΓ,𝑟:𝟏(𝑢:𝟏+𝟏)∈ΔΔ⊢𝑢:𝟏+𝟏VarRΔ,𝑎:𝟏AΔ,𝑔:𝟏Δ⊢𝐾(𝑢):𝖢𝗈𝗅𝗈𝗋CaseΓ⊢𝐿(𝑐):𝖢𝗈𝗅𝗈𝗋Case⋅⊢next:𝖢𝗈𝗅𝗈𝗋→𝖢𝗈𝗅𝗈𝗋Lam.
The reductions are next𝗋𝖾𝖽⟼𝐿(𝗋𝖾𝖽)⟼𝗀𝗋𝖾𝖾𝗇,next𝖺𝗆𝖻𝖾𝗋⟼𝐿(𝖺𝗆𝖻𝖾𝗋)⟼𝐾(𝗂𝗇𝗅(⋆))⟼𝗋𝖾𝖽,next𝗀𝗋𝖾𝖾𝗇⟼𝐿(𝗀𝗋𝖾𝖾𝗇)⟼𝐾(𝗂𝗇𝗋(⋆))⟼𝖺𝗆𝖻𝖾𝗋. The first step of each line is beta; the remaining steps are the appropriate case contractions.
exercise 2.8.
For the right contraction, inversion of the typing derivation before the step gives Γ⊢𝗂𝗇𝗋(𝑣):𝐴+𝐵,Γ,𝑥:𝐴⊢𝑒1:𝐶,Γ,𝑦:𝐵⊢𝑒2:𝐶. Inverting the injection premise gives Γ ⊢𝑣 :𝐵. The source of the complete derivation transformation is 𝐴 𝗍𝗒𝗉𝖾Γ⊢𝑣:𝐵Γ⊢𝗂𝗇𝗋(𝑣):𝐴+𝐵InrΓ,𝑥:𝐴⊢𝑒1:𝐶Γ,𝑦:𝐵⊢𝑒2:𝐶Γ⊢𝖼𝖺𝗌𝖾(𝗂𝗇𝗋(𝑣);𝑥.𝑒1;𝑦.𝑒2):𝐶Case. Its target is Γ,𝑦:𝐵⊢𝑒2:𝐶Γ⊢𝑣:𝐵Γ⊢𝑒2[𝑣/𝑦]:𝐶Substitution. This is a metalevel transformation of derivation trees, not a term evaluation step. For scrutinee congruence, inversion gives Γ ⊢𝑒 :𝐴 +𝐵 and the same two branch premises. The induction hypothesis changes the first premise to Γ ⊢𝑒′ :𝐴 +𝐵; reapplying Case yields Γ ⊢𝖼𝖺𝗌𝖾(𝑒′;𝑥.𝑒1;𝑦.𝑒2) :𝐶.
Exercise 2.9.
Let 𝑎 =(𝜆𝑦. 𝑦)𝗍𝗍. Call by value evaluates the argument first: (𝜆𝑥.𝑥𝑥)𝑎⟼v(𝜆𝑥.𝑥𝑥)𝗍𝗍⟼v𝗍𝗍𝗍𝗍. The endpoint is stuck because its function is a boolean value rather than an abstraction.
Call by name substitutes the unevaluated argument twice and then evaluates the function position: (𝜆𝑥.𝑥𝑥)𝑎⟼n𝑎𝑎⟼n𝗍𝗍𝑎. This endpoint is stuck; call by name has no context that evaluates the argument after a nonlambda function has become final.
If 𝑥 :𝑋 typed 𝑥 𝑥 :𝐶, App would require the function occurrence to have 𝐷 →𝐶 and the argument occurrence to have 𝐷. Both occurrences refer to the same declaration, so uniqueness of types gives 𝑋 =𝐷 →𝐶 and 𝑋 =𝐷, hence 𝐷 =𝐷 →𝐶. No finite type tree is equal to a proper arrow tree containing itself as a subtree, so no simple type solves these equations.
exercise 2.10.
Put 𝐹 =𝐴 ⇒𝐵, 𝐺 =𝐵 ⇒𝐶, 𝑇 =𝐹 ⇒𝐺 ⇒(𝐴 ⇒𝐶), and Δ =𝑓 :𝐹,𝑔 :𝐺,𝑥 :𝐴. The complete natural-deduction tree is 𝑔:𝐺∈ΔΔ⊢𝖭𝐺Hyp𝑓:𝐹∈ΔΔ⊢𝖭𝐹Hyp𝑥:𝐴∈ΔΔ⊢𝖭𝐴HypΔ⊢𝖭𝐵Δ⊢𝖭𝐶𝑓:𝐹,𝑔:𝐺⊢𝖭𝐴⇒𝐶𝑓:𝐹⊢𝖭𝐺⇒(𝐴⇒𝐶)⋅⊢𝖭𝑇. Decorating the three Hyp leaves by variables, the two elimination nodes by App, and the three discharge nodes by Lam gives the complete typing tree for 𝜆𝑓:𝐴→𝐵.𝜆𝑔:𝐵→𝐶.𝜆𝑥:𝐴.𝑔(𝑓𝑥). Every node in this arrow-only example has the corresponding typing node and there are no extra formation premises. Skeleton erasure therefore recovers the displayed natural-deduction tree node for node.
Exercise 2.11.
Let 𝐹 be the proof term from example 2.35. The injection 𝗂𝗇𝗅(𝑎) has type 𝐴 +𝐵 because 𝑎 :𝐴 and 𝐵 is a formed type. Write 𝑝0 =(𝑓,𝑔). Compatible proof reduction gives 𝐹𝑝0𝗂𝗇𝗅(𝑎)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉(𝜆𝑠:𝐴+𝐵.𝖼𝖺𝗌𝖾(𝑠;𝑥.𝖿𝗌𝗍(𝑝0)𝑥;𝑦.𝗌𝗇𝖽(𝑝0)𝑦))𝗂𝗇𝗅(𝑎)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉𝖼𝖺𝗌𝖾(𝗂𝗇𝗅(𝑎);𝑥.𝖿𝗌𝗍(𝑝0)𝑥;𝑦.𝗌𝗇𝖽(𝑝0)𝑦)𝑟𝑜𝑜𝑡𝑐𝑎𝑠𝑒𝐿⟶𝗉𝖿𝗌𝗍(𝑝0)𝑎𝑟𝑜𝑜𝑡𝑓𝑠𝑡⟶𝗉𝑓𝑎. The first beta step occurs compatibly in function position of the outer application. The second is the outer application itself. Subject reduction assigns type 𝐶 to every displayed line: 𝑓 :𝐴 →𝐶, 𝑔 :𝐵 →𝐶, and 𝑎 :𝐴 are unchanged throughout.
exercise 2.12.
Suppose 𝑒 ∈R𝐴×𝐵 and 𝑒 ⟶𝗉𝑒′. By definition, 𝖿𝗌𝗍(𝑒) ∈R𝐴 and 𝗌𝗇𝖽(𝑒) ∈R𝐵. The proof contexts 𝖿𝗌𝗍([ −]) and 𝗌𝗇𝖽([ −]) give 𝖿𝗌𝗍(𝑒)⟶𝗉𝖿𝗌𝗍(𝑒′),𝗌𝗇𝖽(𝑒)⟶𝗉𝗌𝗇𝖽(𝑒′). Reduction closure at 𝐴 and 𝐵 gives both defining conditions for 𝑒′ ∈R𝐴×𝐵.
Now let 𝑎 ∈R𝐴 and 𝑏 ∈R𝐵. Saturation clause 1 makes both strongly normalizing. The root contractions 𝖿𝗌𝗍((𝑎,𝑏))⟶𝗉𝑎,𝗌𝗇𝖽((𝑎,𝑏))⟶𝗉𝑏 have reducible contracta and strongly normalizing proper arguments. Principal expansion makes the two projections reducible, and the product clause gives (𝑎,𝑏) ∈R𝐴×𝐵.
Exercise 2.13.
The two identity derivations are (𝑥:𝟐)∈𝑥:𝟐𝑥:𝟐⊢𝑥:𝟐Var⋅⊢id𝟐:𝟐→𝟐Lam, and (𝑥:𝟏)∈𝑥:𝟏𝑥:𝟏⊢𝑥:𝟏Var⋅⊢id𝟏:𝟏→𝟏Lam. One term using each twice is ((id𝟐𝗍𝗍,id𝟐𝖿𝖿),(id𝟏⋆,id𝟏⋆)), of type (𝟐 ×𝟐) ×(𝟏 ×𝟏).
If one simply typed variable 𝑖 replaced both definitions, its boolean uses would require 𝑖 :𝟐 →𝟐, while its unit uses would require 𝑖 :𝟏 →𝟏. Uniqueness of typing for a variable in a fixed context would identify these two arrow types, and arrow injectivity would then give 𝟐 =𝟏, impossible. A single monomorphic declaration cannot serve both uses.
Exercise 2.14.
Extend the old evaluation contexts by 𝐸::=⋯∣(𝐸,𝑒)∣(𝑣,𝐸)∣𝖿𝗌𝗍(𝐸)∣𝗌𝗇𝖽(𝐸)∣𝗂𝗇𝗅(𝐸)∣𝗂𝗇𝗋(𝐸)∣𝖼𝖺𝗌𝖾(𝐸;𝑥.𝑒1;𝑦.𝑒2)∣𝖺𝖻𝗈𝗋𝗍𝐴(𝐸). The side metavariable 𝑣 ranges over values. The new basic redexes are the two projections of a value pair and the two case expressions whose scrutinee is a value injection.
We prove the value/redex/stuck trichotomy by structural induction on a closed term, without assuming that it is typed. A variable case is impossible by closedness; a Boolean, lambda, or the Unit constructor ⋆ is a value. In an application, first apply the induction hypothesis to the function. Its step or stuck outcome lifts to the application. If it is a value, apply the hypothesis to the argument; an argument step or stuck outcome lifts, while two values form a beta redex exactly when the function is a lambda and otherwise form a stuck application. In a conditional, the guard’s step or stuck outcome lifts; a true or false guard determines its unique root contraction, and any other value guard makes the conditional stuck.
For a pair, decompose the left component first; only when it is a value decompose the right. If both are values, the pair is a value. In a projection, decompose the scrutinee. A value pair has the corresponding projection redex; every other value scrutinee makes the projection stuck. In an injection, decompose its payload; the injection becomes a value exactly when the payload does. In a case, decompose the scrutinee. A value left or right injection determines the corresponding contraction, while every other value scrutinee makes the case stuck. Abort decomposes its scrutinee; any value scrutinee makes the abort stuck. These clauses also propagate a stuck selected subterm to a stuck whole term.
For uniqueness, structural induction compares two proposed decompositions. The Unit constructor has no decomposition because it is already a value. In an application, the argument frame requires a value function, whereas the function frame contains a reducible function; a value has no step. The induction hypotheses make the selected function or argument decomposition unique, and a beta root has both subterms values, so it cannot overlap either nonempty frame. A conditional root has a Boolean value guard and cannot overlap its guard frame. In a pair, the right frame requires the left component to be a value, whereas the left frame requires that component to decompose; no value steps. A projection, injection, case, or abort has only the displayed frame for its outer constructor, and the induction hypothesis makes the selected child decomposition unique. At the empty context, projection and case roots are separated by their outer constructors, and the two case roots are separated because an injection cannot be both left and right. The outer constructor ⋆ is disjoint from every redex and from every nonempty frame. A root redex cannot also have a nonempty decomposition: every subterm at an earlier selected position is a value, while plugging a basic redex into a context produces a step and no value steps.
These cases exhaust the grammar and establish exactly one of value, unique context-and-redex decomposition, or stuckness. If 𝑒 ⟼𝑒1 and 𝑒 ⟼𝑒2, both derivations therefore expose the same context and basic redex. Every basic redex has one contractum, and filling the common context yields 𝑒1 =𝑒2.
Exercise 2.15.
The substituend (𝑥,𝑦) has both 𝑥 and 𝑦 free. Freshen the left branch binder 𝑥 to 𝑢, and the right branch binder 𝑦 to 𝑣: 𝖼𝖺𝗌𝖾(𝑧;𝑥.(𝑥,𝑤);𝑦.(𝑤,𝑦))[(𝑥,𝑦)/𝑤]=𝛼𝖼𝖺𝗌𝖾(𝑧;𝑢.(𝑢,𝑤);𝑣.(𝑤,𝑣))[(𝑥,𝑦)/𝑤]=𝖼𝖺𝗌𝖾(𝑧;𝑢.(𝑢,(𝑥,𝑦));𝑣.((𝑥,𝑦),𝑣)). The occurrences of 𝑥,𝑦 inside both inserted pairs are free, as is the scrutinee variable 𝑧; 𝑢,𝑣 are bound in their respective branches. Retaining the original left binder would bind the inserted 𝑥 in that branch. Retaining the original right binder would similarly bind the inserted 𝑦. Both freshening steps are therefore necessary.
Exercise 2.16.
Define 𝑁:=𝜆ℎ:(𝐴+𝐵)→𝟎.(𝜆𝑎:𝐴.ℎ𝗂𝗇𝗅(𝑎),𝜆𝑏:𝐵.ℎ𝗂𝗇𝗋(𝑏)). Put 𝐻 =ℎ :(𝐴 +𝐵) →𝟎, Γ𝐴 =𝐻,𝑎 :𝐴, and Γ𝐵 =𝐻,𝑏 :𝐵. The two component derivations are D𝐴=(ℎ:(𝐴+𝐵)→𝟎)∈Γ𝐴Γ𝐴⊢ℎ:(𝐴+𝐵)→𝟎Var(𝑎:𝐴)∈Γ𝐴Γ𝐴⊢𝑎:𝐴Var𝐵 𝗍𝗒𝗉𝖾Γ𝐴⊢𝗂𝗇𝗅(𝑎):𝐴+𝐵InlΓ𝐴⊢ℎ𝗂𝗇𝗅(𝑎):𝟎Appℎ:(𝐴+𝐵)→𝟎⊢𝜆𝑎:𝐴.ℎ𝗂𝗇𝗅(𝑎):𝐴→𝟎Lam. The right component is not left implicit: D𝐵=(ℎ:(𝐴+𝐵)→𝟎)∈Γ𝐵Γ𝐵⊢ℎ:(𝐴+𝐵)→𝟎Var𝐴 𝗍𝗒𝗉𝖾(𝑏:𝐵)∈Γ𝐵Γ𝐵⊢𝑏:𝐵VarΓ𝐵⊢𝗂𝗇𝗋(𝑏):𝐴+𝐵InrΓ𝐵⊢ℎ𝗂𝗇𝗋(𝑏):𝟎App𝐻⊢𝜆𝑏:𝐵.ℎ𝗂𝗇𝗋(𝑏):𝐵→𝟎Lam. The remaining Pair and Lam nodes give the complete outer tree: D𝐴D𝐵𝐻⊢(𝜆𝑎:𝐴.ℎ𝗂𝗇𝗅(𝑎),𝜆𝑏:𝐵.ℎ𝗂𝗇𝗋(𝑏)):(𝐴→𝟎)×(𝐵→𝟎)Pair⋅⊢𝑁:((𝐴+𝐵)→𝟎)→((𝐴→𝟎)×(𝐵→𝟎))Lam.
For the converse define 𝑀:=𝜆𝑝:(𝐴→𝟎)×(𝐵→𝟎).𝜆𝑠:𝐴+𝐵.𝖼𝖺𝗌𝖾(𝑠;𝑎.𝖿𝗌𝗍(𝑝)𝑎;𝑏.𝗌𝗇𝖽(𝑝)𝑏). Let 𝑃 =𝑝 :(𝐴 →𝟎) ×(𝐵 →𝟎), Σ =𝑃,𝑠 :𝐴 +𝐵, Σ𝐴 =Σ,𝑎 :𝐴, and Σ𝐵 =Σ,𝑏 :𝐵. The complete branch trees are E𝐴=𝑃∈Σ𝐴Σ𝐴⊢𝑝:(𝐴→𝟎)×(𝐵→𝟎)VarΣ𝐴⊢𝖿𝗌𝗍(𝑝):𝐴→𝟎Fst(𝑎:𝐴)∈Σ𝐴Σ𝐴⊢𝑎:𝐴VarΣ𝐴⊢𝖿𝗌𝗍(𝑝)𝑎:𝟎App, and E𝐵=𝑃∈Σ𝐵Σ𝐵⊢𝑝:(𝐴→𝟎)×(𝐵→𝟎)VarΣ𝐵⊢𝗌𝗇𝖽(𝑝):𝐵→𝟎Snd(𝑏:𝐵)∈Σ𝐵Σ𝐵⊢𝑏:𝐵VarΣ𝐵⊢𝗌𝗇𝖽(𝑝)𝑏:𝟎App. Thus the case and abstraction nodes are E=(𝑠:𝐴+𝐵)∈ΣΣ⊢𝑠:𝐴+𝐵VarE𝐴E𝐵Σ⊢𝖼𝖺𝗌𝖾(𝑠;𝑎.𝖿𝗌𝗍(𝑝)𝑎;𝑏.𝗌𝗇𝖽(𝑝)𝑏):𝟎Case, E𝑃⊢𝜆𝑠:𝐴+𝐵.𝖼𝖺𝗌𝖾(𝑠;𝑎.𝖿𝗌𝗍(𝑝)𝑎;𝑏.𝗌𝗇𝖽(𝑝)𝑏):(𝐴+𝐵)→𝟎Lam⋅⊢𝑀:((𝐴→𝟎)×(𝐵→𝟎))→((𝐴+𝐵)→𝟎)Lam.
On constructor inputs, with 𝑓 :𝐴 →𝟎 and 𝑔 :𝐵 →𝟎, put 𝑝0 =(𝑓,𝑔). Then 𝑀𝑝0𝗂𝗇𝗅(𝑎)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉(𝜆𝑠.𝖼𝖺𝗌𝖾(𝑠;𝑎′.𝖿𝗌𝗍(𝑝0)𝑎′;𝑏′.𝗌𝗇𝖽(𝑝0)𝑏′))𝗂𝗇𝗅(𝑎)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉𝖼𝖺𝗌𝖾(𝗂𝗇𝗅(𝑎);𝑎′.𝖿𝗌𝗍(𝑝0)𝑎′;𝑏′.𝗌𝗇𝖽(𝑝0)𝑏′)𝑟𝑜𝑜𝑡𝑐𝑎𝑠𝑒𝐿⟶𝗉𝖿𝗌𝗍(𝑝0)𝑎𝑟𝑜𝑜𝑡𝑓𝑠𝑡⟶𝗉𝑓𝑎, while the other injection has its own complete trace 𝑀𝑝0𝗂𝗇𝗋(𝑏)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉(𝜆𝑠.𝖼𝖺𝗌𝖾(𝑠;𝑎′.𝖿𝗌𝗍(𝑝0)𝑎′;𝑏′.𝗌𝗇𝖽(𝑝0)𝑏′))𝗂𝗇𝗋(𝑏)𝑟𝑜𝑜𝑡𝑏𝑒𝑡𝑎⟶𝗉𝖼𝖺𝗌𝖾(𝗂𝗇𝗋(𝑏);𝑎′.𝖿𝗌𝗍(𝑝0)𝑎′;𝑏′.𝗌𝗇𝖽(𝑝0)𝑏′)𝑟𝑜𝑜𝑡𝑐𝑎𝑠𝑒𝑅⟶𝗉𝗌𝗇𝖽(𝑝0)𝑏𝑟𝑜𝑜𝑡𝑠𝑛𝑑⟶𝗉𝑔𝑏.
Exercise 2.17.
Define 𝑑:=𝜆𝑝:𝐴×(𝐵+𝐶).𝖼𝖺𝗌𝖾(𝗌𝗇𝖽(𝑝);𝑏.𝗂𝗇𝗅((𝖿𝗌𝗍(𝑝),𝑏));𝑐.𝗂𝗇𝗋((𝖿𝗌𝗍(𝑝),𝑐))). In the other direction, define 𝑢𝐵(𝑞):=(𝖿𝗌𝗍(𝑞),𝗂𝗇𝗅(𝗌𝗇𝖽(𝑞))),𝑢𝐶(𝑟):=(𝖿𝗌𝗍(𝑟),𝗂𝗇𝗋(𝗌𝗇𝖽(𝑟))). Then 𝑢:=𝜆𝑠:(𝐴×𝐵)+(𝐴×𝐶).𝖼𝖺𝗌𝖾(𝑠;𝑞.𝑢𝐵(𝑞);𝑟.𝑢𝐶(𝑟)). Product inversion gives 𝖿𝗌𝗍(𝑝) :𝐴 and 𝗌𝗇𝖽(𝑝) :𝐵 +𝐶; the two branches of 𝑑 have the common type (𝐴 ×𝐵) +(𝐴 ×𝐶). Conversely, each branch of 𝑢 has type 𝐴 ×(𝐵 +𝐶). The Case, Pair, projection, and injection rules therefore give the two advertised arrow typings.
Put 𝑝𝐵=(𝑎,𝗂𝗇𝗅(𝑏)),𝑞𝐵=(𝑎,𝑏),𝑝𝐶=(𝑎,𝗂𝗇𝗋(𝑐)),𝑞𝐶=(𝑎,𝑐). For a fixed product term 𝑝, abbreviate the fully displayed case context by 𝐷𝑝(𝑡):=𝖼𝖺𝗌𝖾(𝑡;𝑏′.𝗂𝗇𝗅((𝖿𝗌𝗍(𝑝),𝑏′));𝑐′.𝗂𝗇𝗋((𝖿𝗌𝗍(𝑝),𝑐′))), and put 𝑈(𝑡):=𝖼𝖺𝗌𝖾(𝑡;𝑞.𝑢𝐵(𝑞);𝑟.𝑢𝐶(𝑟)). All contractions needed by both composites are the following four calculations: 𝑑𝑝𝐵⟶𝗉𝐷𝑝𝐵(𝗌𝗇𝖽(𝑝𝐵))(root beta)⟶𝗉𝐷𝑝𝐵(𝗂𝗇𝗅(𝑏))(P-Ctx, 𝐾=𝐷𝑝𝐵([−]))⟶𝗉𝗂𝗇𝗅((𝖿𝗌𝗍(𝑝𝐵),𝑏))(root 𝖼𝖺𝗌𝖾𝖫)⟶𝗉𝗂𝗇𝗅(𝑞𝐵)(P-Ctx, 𝐾=𝗂𝗇𝗅(([−],𝑏))),𝑢𝗂𝗇𝗅(𝑞𝐵)⟶𝗉𝑈(𝗂𝗇𝗅(𝑞𝐵))(root beta)⟶𝗉(𝖿𝗌𝗍(𝑞𝐵),𝗂𝗇𝗅(𝗌𝗇𝖽(𝑞𝐵)))(root 𝖼𝖺𝗌𝖾𝖫)⟶𝗉(𝑎,𝗂𝗇𝗅(𝗌𝗇𝖽(𝑞𝐵)))(P-Ctx, 𝐾=([−],𝗂𝗇𝗅(𝗌𝗇𝖽(𝑞𝐵))))⟶𝗉𝑝𝐵(P-Ctx, 𝐾=(𝑎,𝗂𝗇𝗅([−]))). For the right constructors: 𝑑𝑝𝐶⟶𝗉𝐷𝑝𝐶(𝗌𝗇𝖽(𝑝𝐶))(root beta)⟶𝗉𝐷𝑝𝐶(𝗂𝗇𝗋(𝑐))(P-Ctx, 𝐾=𝐷𝑝𝐶([−]))⟶𝗉𝗂𝗇𝗋((𝖿𝗌𝗍(𝑝𝐶),𝑐))(root 𝖼𝖺𝗌𝖾𝖱)⟶𝗉𝗂𝗇𝗋(𝑞𝐶)(P-Ctx, 𝐾=𝗂𝗇𝗋(([−],𝑐))),𝑢𝗂𝗇𝗋(𝑞𝐶)⟶𝗉𝑈(𝗂𝗇𝗋(𝑞𝐶))(root beta)⟶𝗉(𝖿𝗌𝗍(𝑞𝐶),𝗂𝗇𝗋(𝗌𝗇𝖽(𝑞𝐶)))(root 𝖼𝖺𝗌𝖾𝖱)⟶𝗉(𝑎,𝗂𝗇𝗋(𝗌𝗇𝖽(𝑞𝐶)))(P-Ctx, 𝐾=([−],𝗂𝗇𝗋(𝗌𝗇𝖽(𝑞𝐶))))⟶𝗉𝑝𝐶(P-Ctx, 𝐾=(𝑎,𝗂𝗇𝗋([−]))). Thus 𝑢(𝑑(𝑝𝐵)) and 𝑢(𝑑(𝑝𝐶)) concatenate respectively the first and second chains in each display and return 𝑝𝐵,𝑝𝐶. Conversely, 𝑑(𝑢(𝗂𝗇𝗅(𝑞𝐵))) and 𝑑(𝑢(𝗂𝗇𝗋(𝑞𝐶))) concatenate the same chains in the opposite order and return 𝗂𝗇𝗅(𝑞𝐵),𝗂𝗇𝗋(𝑞𝐶). Every step is beta, projection, or case contraction; no eta law has been used.
Exercise 2.18.
We reconstruct, rather than cite, neutral expansion. For each type 𝐴, let 𝑁(𝐴) assert: if 𝑛 is neutral and every immediate reduct of 𝑛 lies in R𝐴, then 𝑛 ∈R𝐴. We prove 𝑁(𝐴) by structural induction on 𝐴, using only normalization and reduction closure at proper component types.
At 𝑃,𝟐,𝟏,𝟎, every immediate reduct is strongly normalizing. There are finitely many, so adjoining the root 𝑛 produces no infinite branch. Hence 𝖲𝖭(𝑛) and the base candidate contains 𝑛.
Let 𝐴 =𝐵 →𝐶 and fix 𝑎 ∈R𝐵. Normalization at 𝐵 gives 𝜈(𝑎). By induction on 𝜈(𝑎) we show 𝑛 𝑎 ∈R𝐶. Its immediate reducts have exactly two forms. If 𝑛 ⟶𝗉𝑛′, the premise of 𝑁(𝐴) gives 𝑛′ ∈R𝐵→𝐶, and the arrow clause gives 𝑛′𝑎 ∈R𝐶. If 𝑎 ⟶𝗉𝑎′, reduction closure at 𝐵 gives 𝑎′ ∈R𝐵 and the height induction gives 𝑛𝑎′ ∈R𝐶. The outer induction hypothesis 𝑁(𝐶) now admits 𝑛𝑎. Since 𝑎 was arbitrary, the arrow clause admits 𝑛.
Let 𝐴 =𝐵 ×𝐶. The term 𝖿𝗌𝗍(𝑛) is neutral, and each of its immediate reducts is 𝖿𝗌𝗍(𝑛′) for an immediate 𝑛′ of 𝑛. The premise gives 𝑛′ ∈R𝐵×𝐶, hence 𝖿𝗌𝗍(𝑛′) ∈R𝐵. The outer induction hypothesis 𝑁(𝐵) admits 𝖿𝗌𝗍(𝑛). Replacing 𝐵,𝖿𝗌𝗍 by 𝐶,𝗌𝗇𝖽 proves the second projection condition, so the product clause admits 𝑛.
Let 𝐴 =𝐵 +𝐶. Every immediate 𝑛′ is reducible and therefore strongly normalizing; finite branching makes 𝑛 strongly normalizing. A reduction from neutral 𝑛 to 𝗂𝗇𝗅(𝑏) has positive length and factors through an immediate 𝑛′ ∈R𝐵+𝐶, whose canonical-reduct condition gives 𝑏 ∈R𝐵. A reduction to 𝗂𝗇𝗋(𝑐) factors the same way and the right condition of 𝑛′ gives 𝑐 ∈R𝐶. Thus the sum clause admits 𝑛.
This completes the proof of 𝑁(𝐴) without invoking saturation clause 3. A variable 𝑥 is neutral and has no immediate reducts, so the premise of 𝑁(𝐴) is vacuous and 𝑥 ∈R𝐴 for every type 𝐴.
Exercise 2.19.
Let 𝑒 ∈R𝟐 and 𝑏,𝑐 ∈R𝐶. Saturation normalization gives finite heights 𝜈(𝑒),𝜈(𝑏),𝜈(𝑐). Induct on their sum. The conditional is neutral. Its complete list of immediate reducts is 𝗂𝖿(𝑒′;𝑏;𝑐)𝑒⟶𝗉𝑒′,𝗂𝖿(𝑒;𝑏′;𝑐)𝑏⟶𝗉𝑏′,𝗂𝖿(𝑒;𝑏;𝑐′)𝑐⟶𝗉𝑐′,𝑏𝑒=𝗍𝗍,𝑐𝑒=𝖿𝖿. In the first three cases, saturation reduction closure keeps the changed component in its candidate, and its reduction height strictly decreases. The induction hypothesis therefore places the resulting conditional in R𝐶. In the last two cases the reduct is respectively 𝑏 or 𝑐, reducible by assumption. Thus every immediate reduct is in R𝐶; saturation neutral expansion gives 𝗂𝖿(𝑒;𝑏;𝑐) ∈R𝐶.
Finally, R𝟐 ={𝑒 ∣𝖲𝖭(𝑒)}. Neither 𝗍𝗍 nor 𝖿𝖿 has an immediate proof reduct, hence neither begins an infinite reduction. Therefore 𝗍𝗍,𝖿𝖿 ∈R𝟐 directly from the base definition.
Practical route.
The checker and evaluator requested by exercise 2.22 are built in appendix F; the exact executable record is in appendix E.