Lectures onType Theory
ch:inductive-types: ch:inductive-types
appendix sectionsolutions

ch:inductive-types: ch:inductive-types

exercise 28.1.

Unfolding ¬A:=A0, the term is λh.λa.h(λk.k(a)). Indeed, under h:¬¬¬A and a:A, the abstraction λk.k(a) has type ¬¬A; applying h produces an element of 0, as required for a term of ¬A.

exercise 28.11.

Using the argument order for recN fixed in definition 28.22, put pred:=λn.recN(0,λk.λr.k,n):NN. The two recursor equations give pred(0)0 and pred(suc(k))k. Truncated subtraction can now recurse on its second argument: ˙:=λm.λn.recN(m,λk.λr.pred(r),n):NNN. Consequently m˙0m and m˙suc(n)pred(m˙n), which is the usual truncated subtraction.

exercise 73.27.

For a closed type C, weaken it to the constant family w:WC. The W-elimination step therefore has type h:a:Af:B(a)W(B(a)C)C. Define recW(h,t):=indW(w.C;h,t). Rule W-comp calculates recW(h,sup(a,f))h(a,f,λy.recW(h,f(y))):C. The constant specialization erases the tree argument from the motive. It therefore cannot synthesize a result in a genuinely varying fiber C(t); that dependency must already be supplied to W-elimination.

exercise 73.28.

Use constructors leaf:ATree(A) and node:Tree(A)2Tree(A). The eliminator gives leaves(leaf(a))1,leaves(node(l,r))leaves(l)+leaves(r),mirror(leaf(a))leaf(a),mirror(node(l,r))node(mirror(r),mirror(l)). Induct on the tree. The leaf case computes to reflexivity. In the node case, the two induction hypotheses reduce the double mirror to node(l,r); this is precisely the constructor congruence case of the eliminator.

exercise 73.29.

Let ω:=δ(roll(δ)). Unfolding δ and then using the proposed pattern equation gives the nonempty cycle ωunroll(roll(δ))(roll(δ))δ(roll(δ))=ω. In the constructor argument DD, the occurrence of D in the domain is negative. Admitting the constructor together with the displayed destructor equation therefore destroys strong normalization, which strict positivity is designed to protect.

Exercise 28.2.

Recall that ¬X:=X0. The required terms are λf.λb.λa.f(a)(b):(A¬B)(B¬A) and λa.λk.k(a):A¬¬A. For the first, in context f:A(B0),b:B,a:A, application gives f(a):B0, hence f(a)(b):0; three uses of Π-intro give the displayed type. For the second, in context a:A,k:A0, application gives k(a):0, and two abstractions finish the derivation. Neither construction eliminates a term of 0; each merely constructs a function whose codomain is 0.

Exercise 28.3.

Let ΓD type. Restore the constant motive on empty elimination and define λc.ind0(x.D;h(c)):CD. Indeed, in Γ,c:C we have h:C0 by weakening, so h(c):0. Weakening D once more gives Γ,c:C,x:0D type. Therefore 0-elim yields Γ,c:Cind0(x.D;h(c)):D, and Π-intro gives the claimed map. Thus a map from C into 0 permits a map from C into every type.

Exercise 28.4.

For ΓC type, the fully annotated definition is abortC:=λa:0.ind0(x.C;a):0C. Here the variable x is bound in the motive annotation; C does not actually depend on it. The body is the following instance of 0-elim. We display the structural premises that the book’s compressed convention ordinarily suppresses: ΓC typeΓ,a:0 ctxΓ,a:0C typeWkΓ,a:0,x:0 ctxΓ,a:0,x:0C typeWkΓ,a:0 ctxΓ,a:0a:0VarΓ,a:0ind0(x.C;a):CelimΓλa:0.ind0(x.C;a):0CΠintro. The two context judgments in this tree follow from Γ ctx, 0-form, and context extension. More explicitly, Γ ctxΓ ctxΓ0 typeformΓ,a:0 ctxCtxExt, and the second extension is identical after weakening 0 to Γ,a:0. Since C[a/x] is literally C, the conclusion of empty elimination has exactly the required type.

Exercise 28.5.

Orienting case analysis by the first argument, define or:=λa.λb.rec2(tt,b,a),implies:=λa.λb.rec2(b,tt,a),xor:=λa.λb.rec2(neg(b),b,a). In each body both branches have type 2, so Boolean recursion and two uses of Π-intro give type 222. Two function-beta steps followed by the appropriate Boolean computation rule give or(tt,b)rec2(tt,b,tt)tt,or(ff,b)rec2(tt,b,ff)b,implies(tt,b)rec2(b,tt,tt)b,implies(ff,b)rec2(b,tt,ff)tt,xor(tt,b)rec2(neg(b),b,tt)neg(b),xor(ff,b)rec2(neg(b),b,ff)b. These are judgmental equations; no propositional equality type is involved.

Exercise 28.6.

Write Tt:=C(tt),Tf:=C(ff),P:=b:2C(b). Substitution into Γ,x:2C type forms Tt and Tf in Γ. Starting from the context Δ:=Γ,ct:Tt,cf:Tf,b:2, repeated weakening supplies Δ,x:2C type,Δct:C(tt),Δcf:C(ff), while Var supplies Δb:2. Thus Δ,x:2C typeΔct:C(tt)Δcf:C(ff)Δb:2Δind2(x.C;ct,cf,b):C(b)elim. The weakening sequence can be read explicitly as Γ,x:2C typeWkΓ,ct:Tt,x:2C typeWkΓ,ct:Tt,cf:Tf,x:2C type. followed by weakening the resulting family by b:2; exchange merely moves the fresh motive variable x to the final displayed position. The branch terms are obtained by Var and weakened over declarations to their right.

Applying Π-intro successively to b,cf,ct yields Γλct.λcf.λb.ind2(x.C;ct,cf,b):TtTfP. Call this term IC. At the constructors, three Pi-beta steps expose the eliminator and then Boolean computation applies: IC(ct)(cf)(tt)ind2(x.C;ct,cf,tt)ct:C(tt),IC(ct)(cf)(ff)ind2(x.C;ct,cf,ff)cf:C(ff).

Conversely, suppose for every such family C we are given JC:TtTfb:2C(b) with the two displayed constructor equations. Define the eliminator constructed from this principle by ind2(x.C;ct,cf,b):=JC(ct)(cf)(b). Three uses of Π-elim give it type C(b). Its constructor computations are exactly the assumed equations JC(ct)(cf)(tt)ct,JC(ct)(cf)(ff)cf. Hence the binder-form principle and the primitive elimination principle construct one another. This proves equivalence of principles, not a raw-term identity between JC and the primitive eliminator.

Exercise 28.7.

Let 2:=1+1,tt:=inl(),ff:=inr(). Formation and the two introduction rules are immediate from 1-form, 1-intro, and the coproduct rules.

For elimination, suppose Γ,z:2C type,ct:C(tt),cf:C(ff),s:2. In the left branch, the family over u:1 is C(inl(u)). The derived dependent unit eliminator therefore gives f:=λu.ind1(v.C(inl(v));ct;u):u:1C(inl(u)). Here the semicolon grouping only makes the motive, base point, and scrutinee visible; by proposition 27.17 the body is the unchanged raw term ct, converted from C(inl()) to C(inl(u)). In the right branch, unit elimination converts the unchanged term cf from C(inr()) to C(inr(u)), giving g:=λu.ind1(v.C(inr(v));cf;u):u:1C(inr(u)). Define ind2(z.C;ct,cf;s):=ind+(z.C;f,g,s):C(s). This has exactly the Boolean elimination rule, with 2, tt, and ff substituted for their primitive counterparts. Its computations are judgmental: ind2(z.C;ct,cf;tt)ind+(z.C;f,g,inl())f()ct,ind2(z.C;ct,cf;ff)ind+(z.C;f,g,inr())g()cf. The middle equations are coproduct computation; the final equations are function beta followed by the reflexive computation of the derived unit eliminator. Thus no propositional transport remains in either Boolean computation rule.

Exercise 28.8.

Using the case-analysis notation of definition 28.18, define α:=[[λa.inl(a),λb.inr(inl(b))],λc.inr(inr(c))]:(A+B)+CA+(B+C),β:=[λa.inl(inl(a)),[λb.inl(inr(b)),λc.inr(c)]]:A+(B+C)(A+B)+C. Successive coproduct and function beta rules give the three checks: β(α(inl(inl(a))))β(inl(a))inl(inl(a)),β(α(inl(inr(b))))β(inr(inl(b)))inl(inr(b)),β(α(inr(c)))β(inr(inr(c)))inr(c). Thus βα computes to the identity on each constructor form listed in the exercise. The claim is deliberately constructorwise: no coproduct eta rule is required for a generic variable.

Exercise 28.9.

Parenthesize the source type as ((A+B)C). Define F:=λh.(λa.h(inl(a)),λb.h(inr(b))):((A+B)C)(AC)×(BC),G:=λp.[pr1(p),pr2(p)]:(AC)×(BC)((A+B)C). For a pair of functions, beta and the two projection rules give F(G((f,g)))(λa.f(a),λb.g(b))(f,g), where the last equality uses Π-eta in each component. For a generic h:(A+B)C, constructor computation gives G(F(h))(inl(a))(λa.h(inl(a)))(a)h(inl(a)),G(F(h))(inr(b))(λb.h(inr(b)))(b)h(inr(b)). The first equation uses function eta but not coproduct eta; the latter two hold directly on the two constructors.

Exercise 28.10.

Recur on the second argument and use the multiplication of construction 73.26: exp:=λm.λn.recN(1,λk.λr.mul(r,m),n). The recursive result r has type N, and the predecessor k is unused. Hence the term has type NNN. Its defining equations are immediate: exp(m,0)1,exp(m,suc(n))(λk.λr.mul(r,m))(n,exp(m,n))mul(exp(m,n),m). The equations use only Pi-beta and the two natural-number recursor computations.

Exercise 28.12.

At the constant motive C, define iter(c0,f,n):=recN(c0,λk.λr.f(r),n):C. The step has type NCC; it ignores the predecessor. Therefore iter(c0,f,0)c0,iter(c0,f,suc(n))(λk.λr.f(r))(n,iter(c0,f,n))f(iter(c0,f,n)). Addition can now be defined without mentioning recN: add:=λm.λn.iter(m,λr.suc(r),n). Its equations are add(m,0)m and add(m,suc(n))suc(add(m,n)), exactly as in construction 28.23.

Exercise 28.13.

Put T0:=C(0),S:=k:NC(k)C(suc(k)). Substitution forms T0 and S in Γ. In the context Δ:=Γ,c0:T0,cs:S,n:N we need the four premises of N-elim. They are obtained as follows. First weaken the original family past the two branch declarations: Γ,x:NC typeWkΓ,c0:T0,x:NC typeWkΓ,c0:T0,cs:S,x:NC type. and then weaken it by the scrutinee declaration n:N. Up to exchange of the fresh motive variable, this is Δ,x:NC type. The variable rule and weakening give Δc0:C(0),Δcs:S,Δn:N. If the rule is read with an explicit step lambda, two applications followed by two abstractions derive Δλk.λr.cs(k)(r):S; by Pi-eta this is judgmentally equal to the weakened cs. Hence N-elim gives ΔindN(x.C;c0,λk.λr.cs(k)(r);n):C(n). Abstracting in the reverse order n,cs,c0 produces indC:=λc0.λcs.λn.indN(x.C;c0,λk.λr.cs(k)(r);n):T0Sn:NC(n).

At zero, three Pi-beta steps and N-comp1 give indC(c0,cs,0)indN(x.C;c0,λk.λr.cs(k)(r);0)c0. At a successor, N-comp2 and two further beta steps give indC(c0,cs,suc(k))(λk.λr.cs(k)(r))(k,indC(c0,cs,k))cs(k)(indC(c0,cs,k)):C(suc(k)). The motive is genuinely C(n); replacing it by a constant family would lose the dependent conclusion.

Exercise 28.14.

Let 1:=1, and define the base function and outer step a0:=λn.suc(n):NN,S:=λm.λf.λn.recN(f(1),λk.λr.f(r),n):N(NN)(NN). The requested function is the outer recursion at the higher type NN: ack:=λm.recN(a0,S,m):NNN. Writing Am:=ack(m), the outer computation equations are A0a0,Asuc(m)S(m,Am). Consequently ack(0,n)a0(n)suc(n). For the successor row, substitute the displayed form of S and abbreviate Rm(n):=recN(Am(1),λk.λr.Am(r),n). Then ack(suc(m),0)Rm(0)Am(1)=ack(m,1),ack(suc(m),suc(n))Rm(suc(n))Am(Rm(n))Am(ack(suc(m),n)). By the definition of Am, the last term is ack(m,ack(suc(m),n)). The crucial point is that the outer recursive result Am is itself a function and is used both as the inner base case and as the operation iterated in the inner successor case.

Exercise 28.15.

First define a zero test iszero:=λn.recN(tt,λk.λr.ff,n):N2. It computes to tt at zero and to ff at every successor. Now let the outer recursion return a function N2: eq:=λm.recN(iszero,λk.λe.λn.recN(ff,λj.λr.e(j),n),m). Here e:N2 is the predecessor result: when the first argument is suc(k) and the second is suc(j), the step returns e(j), thereby comparing the two predecessors. Direct computation gives the four characteristic equations eq(0,0)tt,eq(0,suc(n))ff,eq(suc(m),0)ff,eq(suc(m),suc(n))eq(m,n). An induction on m, with a case split on n, now proves that closed numerals compute to tt exactly when their meta-level indices agree: the mixed zero/successor cases are false, and the successor/successor case reduces to the induction hypothesis for the predecessors. In particular, eq(2,2)eq(1,1)eq(0,0)tt.

Exercise 28.16.

The term is λh.h(inr(λa.h(inl(a)))):¬¬(A+¬A). Indeed, assume h:(A+¬A)0. In context a:A, h(inl(a)):0, so k:=λa.h(inl(a)):¬A. Hence inr(k):A+¬A, and applying h gives a term of 0. Abstracting over h proves ((A+¬A)0)0, which is the stated double negation.

Exercise 28.17.

For the first direction define λh.(λa.h(inl(a)),λb.h(inr(b))):¬(A+B)¬A׬B. If h:(A+B)0, its restrictions along the two injections have respectively types A0 and B0, so the pair has the required product type.

For the converse, define λp.[pr1(p),pr2(p)]:¬A׬B¬(A+B). For p:¬A׬B, both projections have codomain 0, so coproduct case analysis yields [pr1(p),pr2(p)]:A+B0. Its constructor computations are [pr1(p),pr2(p)](inl(a))pr1(p)(a),[pr1(p),pr2(p)](inr(b))pr2(p)(b).

Exercise 28.18.

Use clause (ii) of theorem 28.32 at the constant result type C:=N, with cn:=0,cc:=λa.λ.λr.suc(r):ALNN. Let recLcn,cc:LN denote the recursor supplied by that clause, and define length:=recLcn,cc. Its two stipulated W-recursion computations are length(nil)cn0,length(cons(a,))cc(a,,length())suc(length()). The element a and tail are available to the step, although only the recursive result is needed for length.

Exercise 28.19.

In the node case, clause (iii) supplies the step with the four arguments, in order, :T,r:T,u:N(=leaves()),v:N(=leaves(r)). At result type N, choose cl:=1,cn:=λ.λr.λu.λv.u+v:TTNNN. Let recTcl,cn be the recursor furnished by the theorem and put leaves:=recTcl,cn. Then leaves(leaf)cl1,leaves(node(,r))cn(,r,leaves(),leaves(r))leaves()+leaves(r).

Exercise 28.20.

Write W:=Wx:AB. At the constant motive 0, the W-step must have type a:Aα:B(a)W(B(a)0)0. Using the assumed point k(a):B(a), define h:=λa.λα.λq.q(k(a)). The subtree family α is not needed; the inductive-hypothesis family q:B(a)0 is evaluated at the distinguished arity point k(a). Therefore W-elimination gives λt.indW(w.0;h,t):W0, which is a term of ¬W. Conceptually, every purported tree has at least one immediate child, and following the selected child cannot terminate in a well-founded tree.

Exercise 28.21.

Fix ΓA type and abbreviate L:=List(A). The formation and introduction rules generated by definition 28.34 are

ΓA type
ΓL type
List-form
ΓA type
Γnil:L
List-intro_1
Γa:AΓ:L
Γcons(a,):L
List-intro_2

For a motive Γ,w:LC type, the nil case has no arguments, while the cons case receives, in the required order, the element, the recursive argument, and its inductive hypothesis: cn:C(nil),cc:a:A:LC()C(cons(a,)). For the next three displays, abbreviate I(t):=indList(w.C;cn,cc;t). The elimination rule is therefore

Γ,w:LC typeΓcn:C(nil)Γcc:a:A:LC()C(cons(a,))Γt:L
ΓI(t):C(t)
List-elim

Finally, the two generated computation rules are

Γ,w:LC typeΓcn:C(nil)Γcc:a:A:LC()C(cons(a,))
ΓI(nil)cn:C(nil)
List-comp_1

The successor computation is the second rule:

Γ,w:LC typeΓcn:C(nil)Γcc:a:A:LC()C(cons(a,))Γa:AΓ:L
ΓI(cons(a,))cc(a,,I()):C(cons(a,))
List-comp_2

The direct recursive argument has empty arity telescope, so its generated inductive-hypothesis family is simply the single term C().

Exercise 28.22.

Use the constant motive w.N, the nil branch 0, and the cons branch that ignores the element and tail but increments the recursive result: length:=λt.indList(w.N;0,λa.λ.λr.suc(r);t):List(A)N. Function beta followed by the two list computations gives length(nil)0,length(cons(a,))(λa.λ.λr.suc(r))(a,,length())suc(length()). Both are judgmental equations generated by the primitive list rules.

Exercise 28.23.

Work in the hypothetical extension with fold:(D0)D and, for every C, a recursor recD(e):DC,recD(e,fold(u))e(u),e:(D0)C. At C:=D0, the identity step e:=λu:D0.u:(D0)(D0) therefore defines unfold:=recD(e):D(D0),unfold(fold(u))u. The typing of δ is the derivation d:Dunfold:D(D0)d:Dd:Dd:Dunfold(d):D0Πelimd:Dd:Dd:Dunfold(d)(d):0Πelimδ:=λd.unfold(d)(d):D0Πintro. Weakening supplies the closed constant unfold in context d:D, and both occurrences of d are variable-rule instances. Next, the constructor typing rule for fold and application give δ:D0δ:D0fold(δ):Dfoldω:=δ(fold(δ)):0Πelim.

Put d0:=fold(δ). Contextual closure of Pi-beta and of the bad recursor computation gives the nonempty cycle t0:=ω=δ(d0)t1:=unfold(d0)(d0)t2:=((λu.u)(δ))(d0)t3:=δ(d0)=t0. The first step unfolds the definition of δ and contracts its outer beta-redex. In the second, unfold(d0)=recD(e,fold(δ)) contracts to e(δ)=(λu.u)(δ) inside function position. The third contracts that identity beta-redex. Each term has type 0: in t1, unfold(d0):D0; in t2, (λu.u)(δ):D0; and t3=t0 was typed above.

Repeating the three arrows gives an infinite reduction sequence starting at ω, so ω is not strongly normalizing. Moreover, no term on the cycle is a normal form. Term t0=t3 has the outer beta-redex δ(d0); t1 contains the recursor redex unfold(fold(δ)); and t2 contains the beta redex (λu.u)(δ). Thus every node on the exhibited cycle has an outgoing one-step reduction.

Exercise 73.24.

Normalize the two inner operators first. A convenient choice for K×X is the container with shapes K and one position at every shape. A convenient choice for L+X has shapes L+N1, no positions at inl(), and one position at inr(). The product clause of lemma 73.51 therefore gives A=K×(L+N1),B(k,inl())=N1,B(k,inr())=N1+N1. On the two forms of element, the forward isomorphism is νX((k,x),inl())=((k,inl()),λ_.x),νX((k,x),inr(x))=((k,inr()),q), where q(inl())=x and q(inr())=x. The inverse reads the shape tag. It returns ((k,q()),inl()) at a left shape, and ((k,q(inl())),inr(q(inr()))) at a right shape. Sum and unit eta prove the two inverse equations in TD.

Exercise 73.25.

Naturality of ν at folde:WC is the equation νCΦ(folde)=((a,b)(a,foldeb))νW. Applying the equation to x with νW(x)=(a,b) gives νC(Φ(folde)(x))=(a,foldeb). Since ιΦ(x)=sup(a,b), W-computation yields folde(ιΦ(x))=e(νC1(a,foldeb))=e(Φ(folde)(x)), where the second equality applies νC1 to the naturality equation. This is the algebra-morphism square.

Exercise 73.26.

For a variable y, both y and λx.y(x) are beta-normal, as are y and λx.rec0(x) when the domain is empty. Beta reduction therefore cannot establish either function equality. The X case of the container lemma needs uniqueness for maps N1X; the constant K case needs uniqueness for maps N0X.

Pointwise empty elimination gives y(x)=rec0(x) under x:N0. Unit elimination gives y(x)=y() under x:N1. Function extensionality turns these pointwise equalities into y=λ(x:N0).rec0(x)andy=λ(x:N1).y(), respectively. The source calculus includes the corresponding extensional uniqueness laws; the beta-only intensional core does not make either equation judgmental.

Search the book

Type to search the local edition.