Lectures onType Theory
ch:type-classes: ch:type-classes
appendix sectionsolutions

ch:type-classes: ch:type-classes

Exercise 11.1.

With empty local evidence, the only instance path is pickC0(EqInt)=(,π1ordInt)resolveC0,(EqInt)=π1ordIntEInstanceresolveC0,(Eq(ListInt))=eqList(π1ordInt)EInstanceresolveC0,(Eq(List(ListInt)))=eqList(eqList(π1ordInt))EInstance. If a second effective declaration has a head unifiable with Eq(Listα), both freshened heads can match a common instance of the outer request. The effective-head admission check therefore rejects the table rather than choosing between distinct builders. The same check rejects a primitive EqInt clause in the presence of OrdInt: superclass closure already derives an effective EqInt clause whose builder is π1ordInt. Keeping both would destroy the unique selected evidence needed by functionality and coherence.

Exercise 13.7.

Without superclass closure, nf{Ord(Listα),Eqβ}={Ordα,Eqβ}. Under θ=[Int/α,ListInt/β], the raw set succeeds: construct OrdList(OrdInt), install it, and obtain the required list equality dictionary as EqFromOrd(OrdList(OrdInt)). The canonical set fails because after constructing OrdInt it has no instance for Eq(ListInt). With I, the derived clause OrdaEq(Lista) resolves the latter request from OrdInt, so both sets succeed.

For action composition, put R={Ordγ,Eqβ},S=[Listα/γ],T=[Listα/β]. Without closure, nf(SR)={Ordα,Eqβ}, so the second action rejects at Eq(Listα). Direct normalization of (TS)R first constructs Ord(Listα), installs it, projects the required equality dictionary, and returns {Ordα}. With closure, the sequential second action uses the derived clause and returns that same set. Both routes transport the same evidence: EqFromOrd(OrdList(dOrd)).

Exercise 11.2.

Explicit type application can select A=Int and then receive an explicit dictionary. For example, f[Int]{showDecimal}andf[Int]{showHexadecimal} may return "10" and "0xa" on the value 10. At an implicit use, the visible result type is only String; it contains no occurrence of A. The type therefore determines neither the instantiation nor the dictionary. This is exactly the failure of ftv(Q)ftv(τ).

Exercise 11.3.

Give x the fresh type a. Fresh instantiations of nil:b.Listb and cons:b.bListbListb make both singleton lists have type Lista. Instantiating eq at that type contributes Eq(Lista)ListaListaBool. The application MGUs identify no further type variables. The normalizer one-way-matches the list instance and records eqList:EqD(a)EqD(Lista), so the residual predicate is Eqa. Abstraction and top-level generalization therefore give a.EqaaBool.

For a rejected right-hand side, place show:b.ShowbbString in the environment and use showfalse. W generates the ground request ShowBool. The selected environment contains only ShowInt, so normalization returns reject(ShowBool) before generalization.

Exercise 13.4.

In the constructor context A::Ty and term context d:EqD(A),x:A,y:A,z:A, the application rules give dx:ABoolFTApp,dxy:BoolFTApp,dyz:BoolFTApp,andF(dxy)(dyz):BoolFTApp twice. Discharging z,y,x,d by four uses of T-Lam, and then A by T-TLam, derives allSame3:A::Ty.EqD(A)AAABoolF.

For the displayed run, the outer contractions give allSame3[BoolF]eqBooltrueFtrueFfalseFβandF(eqBooltrueFtrueF)(eqBooltrueFfalseF). Put eT=trueF[BoolF]falseFtrueF. The first comparison reduces completely as follows: eqBooltrueFtrueFβtrueF[BoolF]trueFeTβ(λt:BoolF.λf:BoolF.t)trueFeTβ(λf:BoolF.trueF)eTβtrueF. The second comparison follows the same selected true branch: eqBooltrueFfalseFβtrueF[BoolF]falseF(falseF[BoolF]falseFtrueF)βfalseF. The final conjunction is andFtrueFfalseFβtrueF[BoolF]falseFfalseFβ(λp:BoolF.λq:BoolF.p)falseFfalseFβfalseF. The displayed Church false is itself beta-normal, so no redex remains.

For the three failures, take:

  1. the overlapping table {(Eq,BoolF,eqBool),(Eq,BoolF,λp:BoolF.λq:BoolF.trueF)}; it violates hypothesis 1 of proposition 13.21;

  2. the nested declaration EqA(EqAs), which creates two dictionaries at the same normalized key and violates hypothesis 3;

  3. the two ground entries (Tag,BoolF,0),(Tag,N,suc(0)), with TagD(A)=N. In the scheme A.TagAN, the constrained variable A does not occur in the normalized visible monotype N. This violates the separate ambiguity/admission check that every constraint variable be determined by that visible monotype, not one of the four numbered coherence hypotheses.

Exercise 13.5.

Pair decomposition produces Int=Elemc and a=Bool. The latter has most-general substitution [Bool/a]; the former cannot reduce while c is unknown, so T=[Bool/a],U={Int=Elemc}.

With c=ListInt, the instance equation reduces the right side to Int, and reflexivity discharges U. In the chapter’s local target sketch, the method use is insert[ListInt][Int](collectsList[Int]eqInt). The dictionary has type CollectsD(ListInt,Int).

With c=ListBool, normalization instead produces Int=Bool. Distinct rigid constructors do not unify, so the inference branch fails. The independently well-typed Boolean method would have target form insert[ListBool][Bool](collectsList[Bool]eqBool), but it cannot elaborate the source equality constraint demanding element type Int. A valid dictionary term cannot repair a failed static equality.

Exercise 11.5.

In Δ=?Int:x,α,?α:y, the query ?Int initially skips the nonmatching ?α and selects x. After substituting Int for α, nearest-first lookup selects y. The evidence terms are therefore exactly x and y.

Remove the final assumption ?α:y. Lookup then reaches ?Int:x directly: no implicit candidate lies between the query and that entry. Consequently the no-match rule is never used, the stability side condition is not invoked, and no valid-substitution premise has become trivial.

Exercise 11.6.

The variable β is free in the inferred type and not fixed by the environment; α is fixed by the environment. Therefore the maximal split of lemma 11.3 is P1g={Showβ},P1r={Eqα},σ=β.ShowββBool. If the body call returns substitution S2, its factor T is extended on the variables quantified by σ, while the inherited coordinates obey TS1;S2Γ=RΓ. This equation fixes the meaning of α in the body exactly as it was fixed in the outer environment. The residual requirement becomes Eqα[S2] and is combined with the body’s requirements; by lemma 13.8, final normalization cannot discard an obligation needed by the declarative derivation.

If Eqα were generalized, the let-bound term could be instantiated at a type unrelated to the outer α. That instance would request a dictionary not justified by the outer evidence context, while the residual set would no longer contain Eqα. The displayed environment equation would then fix α on the left but the alleged scheme instance could change it on the right, so the factorization required by theorem 11.5 would fail.

Exercise 11.7.

Choose overlap. Add two premise-free declarations d1:Eq(ListInt),d2:Eq(ListInt) whose Boolean functions disagree on one pair of lists. The closed program eq[0][1] can then elaborate with either dictionary and has two observable results. The precise failed proof step is the unique-instance case of lemma 11.1; canonical evidence and theorem 11.8 consequently fail as well. A repair would need a displayed deterministic priority in both the declarative and algorithmic systems together with a proof that substitution preserves it. Selecting whichever declaration happens to be encountered first supplies no such invariant.

Search the book

Type to search the local edition.