Lectures onType Theory
Chapter 122
Chapter 122Core route

Datatype Declaration Blocks and Strict Positivity

Consider the mutually recursive declarations Tree(A)leaf(a)node(f),f:Forest(A),Forest(A)emptymore(t,f),t:Tree(A), f:Forest(A). Each recursive argument is data already constructed. Replacing the second constructor of Tree by bad:(Tree(A)N)Tree(A) puts the family to the left of an arrow. The two declarations are equally short, yet only the first supports the induction step that receives hypotheses for every recursive child. A declaration processor must distinguish them before it generates a family or eliminator.

One declaration language

The checker below handles ordinary mutual indexed families. Nested, inductive–recursive, quotient, and higher inductive declarations require different rules and are not silently accepted.

Definition 122.1 — The Timpl-data system card

Timpl-data is a surface declaration layer over the Timpl kernel as restated in convention 111.16. In particular, that signature contains the explicit strict lifts of definition 29.10 in addition to the type formers listed in convention 110.16. A finite block has the form B=data (Δp) {Dr:(Δr)Ur1rq} where  {cs:ΘsDrspus1sm}. The common parameter telescope Δp is copied unchanged into every family and constructor. The family-specific telescope Δr contains indices. Each constructor telescope Θs may contain Timpl types, previous constructor arguments, and applications of a family in the same block. It may not quantify over a universe containing the block as data. The occurrence checker below has an explicit clause for every Timpl type former and every Timpl elimination form that can remain at the head of a type. Identity and primitive vector types are admitted only when all their type and term arguments are free of the block. Type-level eliminators and projections are admitted only when all their immediate subterms are free of the block. Supporting any of these forms over the block would require proof-specific or container-specific hypothesis generation absent from Tfam-block.

The target Tfam-block extends the same Timpl kernel, restated in convention 111.16 and named in convention 110.16. Its only primitive indexed family is the vector family of definition 78.1. Tfam-block adds one simultaneous formation rule for the finite family constants, one introduction rule for each constructor, and one simultaneous eliminator. It adds no equality reflection, quotient rule, large elimination beyond the universe maximum computed below, or nested fixed point. Constructor computation rules reduce only an eliminator whose scrutinee is headed by that constructor.

The target name abbreviates the following rules, rather than an unspecified inductive extension. Write ΣΔ ctx for telescope formation and assume that all displayed universes are accepted by the Timpl level solver.

Definition 122.2 — The Tfam-block rule schema

For one component I={D1,,Dq}, simultaneous family formation and constructor introduction are ΣΔp ctx(Σ,ΔpΔr ctx)1rqΣ(Dr:(Δp)(Δr)Ur)1rq sigBlockF and, for each constructor cs, Σ,I,ΔpΘs ctxIΘs posΣ,I,Δp,Θsus:ΔrsΣ,I,Δp,Θscs(z):DrspusBlockI. The second premise is the strict-positivity judgment of definition 122.4, read on the whole telescope. It belongs to the target schema, not only to the source checker. If that premise were dropped, bad would be admitted. Blindly applying the function clause below to its field type would produce the method hypothesis y:Tree(A)1. That hypothesis quantifies over the family being defined. The construction H is total only on accepted binder types, so the unchecked schema would otherwise be malformed. Theorem 122.15 discharges the premise from acceptance rather than assuming it.

For motives Pr:(p:Δp)(i:Δr)DrpiUkr define the method type Ms(P,Θ) by scanning Θs. Its empty clause is Ms(P,):=Prspus(cs(z)). A binder x:A whose type is family-free contributes Ms(P,(x:A),Θ):=(x:A)Ms(P,Θ). When A mentions a family of I, the recursive clause is Ms(P,(x:A),Θ):=(x:A)HP(A,x)Ms(P,Θ), where the hypothesis type HP(A,x) is the induction hypothesis that A yields for x, defined in definition 122.8 by recursion on the occurrence-check derivation of A. When A contains no family of I, the hypothesis type is 1, but the method’s second binder is omitted; when A=Dtpv it is Ptpvx, the familiar case. The remaining telescope Θ keeps x free.

Writing the clause this way, rather than only for an exposed recursive field, is what makes the eliminator usable on every binder the checker accepts. A field of type NTree(A) or y:Tree(A)N is strictly positive, and a schema whose only recursive clause were the exposed one would hand such a field no hypothesis at all — the generated eliminator would then not support induction over that field, and the block would be accepted on the strength of a rule that does not do its job.

The computation rule needs a term of every nontrivial hypothesis type, not only a type. Once the simultaneous eliminators are in scope, define ihP(A,x):HP(A,x) by the same recursion: ihP(A,x):=if no family of I occurs in A,ihP(Dtpv,x):=indt(p,v,x),ihP(y:BA,x):=λy.ihP(A,xy). For the pair clause, choose a binder wFV(B)FV(A)FV(P){x,y}, and first form the recursive term in the context y:B,w:A. Then ihP(y:BA,x):=(ihP(B,π1x),ihP(A,w)[π1x/y][π2x/w]). The lift clause is ihP(LiftuA,x):=ihP(A,x). The first clause again takes precedence. Hence its term is discarded when the corresponding 1-hypothesis binder is omitted from the method.

With premises bs:Ms(P,Θs) for every constructor, simultaneous elimination and constructor computation are (Pr:(p:Δp)(i:Δr)DrpiUkr)1rq(bs:Ms(P,Θs))1smindr:(p:Δp)(i:Δr)(z:Drpi)PrpizBlockE,indrs(p,us,cs(z))bs(z,zih)(Blockcomp). Here zih contains, immediately after every field z:A whose type mentions the block, the term ihP(A,z). In the exposed recursive case A=Dtpv, this term is indt(p,v,z); the function and pair clauses supply the hypotheses for recursive values nested under those strictly positive type formers.

No-confusion is stated at one index instance, because cs(a) and ct(b) inhabit Drspus[a] and Drtput[b], and an identity type between them is not even well formed until those two types agree. Fix therefore a family Dr, an index vector ı:Δr, and arguments with rs=rt=r, us[a]ıut[b]. Distinct constructor tags then generate a map into the Timpl-definable encoded empty type EmptyTimpl:=X:U0X. Thus the distinct-tag rule is noConfs,t:IdDrpı(cs(a),ct(b))EmptyTimpl(st), while one constructor tag generates an injection into the iterated, transported identity telescope of its arguments. Use the homogeneous telescopic equality aΘb of definition 78.8; its recursive definition is exactly the required iterated transported identity telescope. The equal-tag rule has type injs:IdDrspı(cs(a),cs(b))aΘsb, again under us[a]ıus[b]. The displayed statements are the fiber at ı of the total-space rules of definition 78.11; the fiber form is the one the pattern compiler consumes. These are the only formation, introduction, elimination, computation, and no-confusion rules added by Tfam-block.

Parameters and indices play different roles. In the tree–forest block, A:Ui is a parameter copied into every recursive occurrence. In Vec(A,n), the natural number n is an index selected by each constructor result. Treating n as a parameter would make vcons return the same length that it receives and would destroy the intended family.

Definition 122.3 — Dependency order

The dependency graph of B has a vertex Dr for each family. Put DrDt exactly when an argument type of a constructor for Dr mentions Dt. A strongly connected component (SCC) is a maximal vertex set whose members are mutually reachable. The processor treats each SCC as one mutual block and schedules it after all outside dependencies have passed. During constructor checking, all family constants of the block remain in scope.

For tree and forest the graph has the two edges TreeForest and ForestTree; hence one simultaneous block is forced. A one-family list declaration gives a singleton component with a self-loop.

Variance forces strict positivity

Let I be the set of families in one component. The checker traverses a type with a sign ϵ{+,} and an ancestry flag δ{open,blocked}. A function domain reverses the sign and blocks a recursive occurrence. A codomain preserves both data. Recall that Lift-U and Lift-El of definition 29.10 give LiftiA:Ui+1 and LiftiAA whenever A:Ui.

Definition 122.4 — Occurrence check

The judgment I;ϵ;δA pos is generated by the following clauses.

  1. A universe, a variable, an argument-free constant, 1, 2, and N pass at either sign.

  2. An application Dpu with DI passes exactly at state (+,open), provided no argument in p,u contains a family of I.

  3. A dependent function type x:AB passes at sign ϵ when I;ϵ;blockedA posandI;ϵ;δB pos.

  4. A dependent pair x:AB passes at sign ϵ when both components pass at state (ϵ,δ).

  5. Any other well-formed type-level application Ha, whose head is not a family of I, passes at either sign exactly when H and every argument in a contain no family of I. Thus H may be a local type-family variable or a family accepted in an earlier component.

  6. An identity type IdB(u,v) passes at either sign exactly when B,u,v contain no family of I.

  7. A primitive vector type Vec(B,n) passes at either sign exactly when B,n contain no family of I.

  8. A type-level eliminator or projection headed by ind2, indN, J, vind, pr1, or pr2 passes at either sign exactly when every immediate type and term argument contains no family of I. The checker treats such a type opaquely rather than reducing its head.

  9. A strict lift LiftuA passes at state (ϵ,δ) when I;ϵ;δA pos.

A constructor telescope Θs is strictly positive, written IΘs pos, when each binder type passes at state (+,open). A block passes when its telescopes are well formed, its dependency components are closed, and every constructor in every component is strictly positive.

Definition 122.5 — Datatype-block rejection diagnostic

The declaration processor either returns an accepted Tfam-block signature or one record DataReject(ϕ,Dr,cs,ω,E,O). The phase ϕ is one of header formation, dependency closure, constructor-telescope formation, result-index checking, positivity, universe solving, or generated-rule checking. The family Dr and constructor cs are present exactly when that phase lies inside their declarations. The path ω is the binder position followed by the preorder path in its type. The expected datum E is the missing formation judgment, result telescope, positivity state (ϵ,δ), level inequality, or generated-rule type; O is the observed head, sign and ancestry flag, index tuple, unsolved inequality, or inferred type that failed it.

Phases are tried in the displayed order. Components use topological order, families, constructors, and binders use source order, and a type scan uses left-to-right preorder. The processor returns the first failing record in that order. Thus a positivity failure reports the computed path and state, and a universe failure reports the first unsolved or inconsistent inequality; neither diagnostic is a fixture name or a fixed message.

Lemma 122.6 — Datatype rejection records a failed premise

If the declaration processor returns DataReject(ϕ,Dr,cs,ω,E,O), then the declaration cannot produce a Tfam-block signature through the checked rule instance at that path: the premise named by E has no derivation with observed datum O.

Proof of Lemma 122.6 — Datatype rejection records a failed premise

Proof. Inspect ϕ. Header, telescope, and result-index phases return only after the corresponding Timpl formation or typing procedure has rejected its printed judgment. Dependency closure returns an edge whose target is absent from the scheduled signature. In the positivity phase, induction along ω reconstructs every outer clause of definition 122.4; its final head has no clause at the stored sign and ancestry state. Universe solving returns an inequality with no solution in the accepted level algebra. Generated-rule checking returns a premise of Block-F, Block-I, or Block-E whose inferred type is not convertible to its expected type. These are all phases, and each failed premise is required by definition 122.2. ◻

Clauses 5–8 draw the opaque application-and-elimination boundary of Timpl-data. The generated eliminator, rather than polarity alone, determines this boundary. The lift clause is structural because Lift-El identifies the lifted type with its argument by conversion, without adding a new recursive container. A covariant occurrence such as List(D) is perfectly positive; but the hypothesis for a field of that type is “PD holds of every element of the list”, an All combinator for List that Tfam-block does not have. Excluding it here keeps the method construction below total.

For example, IdN(m,n) and Vec(N,n) pass whenever their terms are well scoped. The near variants IdD(x,y) and Vec(D,n) fail the family-free argument test. The former could be supported by a proof-specific clause and the latter by an All hypothesis; this regular card provides neither construction.

Lemma 122.7 — A nonpositive state is family-free

If I;ϵ;δA pos and (ϵ,δ)(+,open), then no family of I occurs in A.

Proof of Lemma 122.7 — A nonpositive state is family-free

Proof. Induct on the displayed occurrence derivation. The base clause contains no family of I. The family clause has the two side conditions ϵ=+ and δ=open, contradicting the hypothesis. For a function type, a state different from (+,open) sends its domain to either negative sign or blocked ancestry, and sends its codomain the unchanged nonpositive state; apply the two induction hypotheses. The pair clause passes the same state to both components, so its two induction hypotheses apply directly. The lift clause uses its induction hypothesis at the unchanged state. The external-application, identity, vector, and opaque-elimination clauses require all displayed type and term arguments to be family-free. These are all rule families. ◻

Each accepted binder type determines the induction hypothesis its field contributes.

Definition 122.8 — Hypothesis type

Fix motives P. For a type A with I;+;openA pos and a variable x:A, define HP(A,x) by recursion on the occurrence-check derivation. When no family of I occurs in A, put HP(A,x):=1. Otherwise use the following clauses. In the pair clause, suppose the type is y:BA. Choose wFV(B)FV(A)FV(P){x,y}, and define the recursive factor before substitution: HP(Dtpv,x):=Ptpvx,HP(y:BA,x):=y:BHP(A,xy),HP(y:BA,x):=HP(B,π1x)×HP(A,w)[π1x/y][π2x/w],HP(LiftuA,x):=HP(A,x). The first clause takes precedence over the others, so the recursion stops as soon as the block has disappeared from the type. There is no recursive clause for clauses 5–8 of definition 122.4, and none is needed: those clauses admit an external type-level application, identity, vector, opaque eliminator, or projection only when all of its arguments are family-free, so each such type falls under the first clause.

The function clause is the one that uses polarity. It quantifies over the same domain B that the field itself quantifies over, and that is legitimate only because B was checked at negative sign: a family of I there would have been rejected, so the generated hypothesis never quantifies over the block being defined. For node:Forest(A)Tree(A) the hypothesis is PFAf; for a field of type NTree(A) it is (n:N)PTA(xn); and for a field of type y:Tree(A)N it is PTA(π1x)×1, whose second factor is trivial because the N component carries nothing to induct over. For x:Liftu(Tree(A)), Lift-El converts x to Tree(A), so the generated hypothesis is PTAx; the lift creates no extra recursive layer.

The check of the bad constructor reaches its argument type at (+,open), then reaches the domain Tree(A) at (,blocked), and rejects there. For node:Forest(A)Tree(A), the constructor telescope stores an argument of type Forest(A); this is not the domain of a function occurring inside that argument type. The family is therefore visited at sign + and accepted.

Remark 122.9 — Why arguments of recursive occurrences are closed

The second clause excludes a type such as D(D(A)) and an index expression containing D. The exclusion is not implied by polarity. It is the regular, nonnested boundary of Timpl-data. Nested positivity checkers replace that clause by a functorial argument; their theorem does not follow from the checker defined here.

Lemma 122.10 — Termination of the declaration checker

For every finite Timpl-data block, dependency analysis, universe-constraint generation, and the occurrence check terminate.

Proof of Lemma 122.10 — Termination of the declaration checker

Proof. Tarjan’s component procedure removes one unclassified vertex at each outer step and scans each finite edge list once. Universe generation traverses each finite telescope and emits finitely many inequalities between finite level expressions. The positivity procedure recurses on a strict syntactic subterm of the type being checked. In the two application clauses it inspects a finite argument list for occurrences of the block and never unfolds a family in it. The identity, vector, and opaque-elimination clauses likewise inspect finitely many type and term arguments without unfolding them. Lexicographic induction on the number of unclassified vertices and the remaining syntax size proves termination of the combined procedure. ◻

Lemma 122.11 — Accepted blocks are strictly positive

If Timpl-data accepts a block B, then for every component I and every constructor binder type A in that component it returns a derivation I;+;openA pos. Every occurrence headed by a family of I in such a derivation is at state (+,open); none of its arguments contains a family of I; and no such occurrence lies in the domain of a function type or in an argument of an external type-level application, identity, vector, or opaque elimination.

Proof of Lemma 122.11 — Accepted blocks are strictly positive

Proof. Acceptance checks every binder of every constructor telescope and stores the resulting occurrence derivation. Induct on one stored derivation. The base, pair, function, and lift clauses pass the induction hypotheses to their immediate subderivations. External-application, identity, vector, and opaque-elimination clauses contain no block family by their explicit side conditions. The only clause whose head belongs to I has the premises ϵ=+, δ=open, and IFam(p,u)=. Thus every such leaf has the two asserted properties. The outer checker starts each binder at (+,open), which gives the displayed derivation. For the last clause, a function domain is visited at (ϵ,blocked). At sign the family clause is not applicable, and at sign + the flag is blocked, so neither state admits an occurrence. Arguments of external applications, identities, vectors, and opaque eliminations are excluded by clauses 5–8 themselves. ◻

Exercise 122.1

★☆☆ Trace definition 122.4 on (NTree(A))N. State the sign at the occurrence of Tree, and give the exact checker result.

Generating the simultaneous family

Passing positivity is useful only because it constructs the premises needed by the eliminator. For each Dr, fix a motive Pr:(p:Δp)(i:Δr)DrpiUkr. Traverse a constructor telescope from left to right. Every argument is copied. Immediately after an argument z:A whose type mentions the block, insert zih:HP(A,z)with valueihP(A,z). For an exposed recursive argument z:Dtpv, these reduce to Ptpvz and indt(p,v,z). Function and pair fields use the other two recursive clauses displayed in definition 122.2.

For tree and forest the generated methods have types bleaf:(a:A)PT(A,leaf(a)),bnode:(f:Forest(A))PF(A,f)PT(A,node(f)),bempty:PF(A,empty),bmore:(t:Tree(A))PT(A,t)(f:Forest(A))PF(A,f)PF(A,more(t,f)). The simultaneous eliminators indT,indF apply the matching method and recursively supply the displayed hypotheses.

Definition 122.12 — Constructor-by-constructor block translation

After solving levels, translation processes each dependency component once. It emits these target declarations in order.

  1. Each source family header Dr:(Δr)Ur emits the same family constant under the copied parameter telescope by Block-F.

  2. Each source constructor cs:ΘsDrspus emits one Block-I instance with the same name, argument order, result indices, and homomorphic translation of every nonrecursive type former.

  3. Each constructor binder is copied into the method telescope and followed by the hypothesis binder of definition 122.8, which is omitted exactly when that binder does not mention the block.

  4. The source mutual eliminator emits the family (indr)r from Block-E; the equation for constructor cs emits exactly its displayed constructor computation rule.

  5. Each ordered pair of distinct constructor tags emits noConfs,t; each constructor emits its transported argument injection. No other declaration is generated.

The construction Θ(X,P,u) of Coquand and Paulin-Mohring places all source fields before all generated hypotheses. Tfam-block instead places a field’s hypothesis immediately after that field. Repeated dependent exchange transports between the two telescopes: a generated hypothesis does not occur in any later source field type, and a later source field does not occur in the earlier hypothesis type.

Definition 122.13 — Universe output

Define the level of a telescope by lev():=0,lev(x:A,Δ):=max(j,lev(Δ))when A:Uj. For a constructor returning Dr:Ur, every argument type must inhabit a universe accepted by Timpl. For motives Pr:(p:Δp)(i:Δr)DrpiUkr, the declaration processor emits the maximum L:=max(lev(Δp),maxrlev(Δr),maxslev(Θs),maxrr,maxrkr). The maximum of an empty finite list of telescope levels is 0. The generated eliminator package inhabits UL. Thus parameter- and index-telescope levels contribute even when no constructor argument mentions them. The processor sends this maximum and the component inequalities to the level solver; a failed or stuck solve rejects the block. Independently, EmptyTimpl:U1, so each distinct-tag no-confusion map has a fixed, solved codomain level.

Exercise 122.2

★☆☆ Give the tree–forest block the parameter telescope Δp=(A:Ui), no index telescope, family levels T=F=i, and motive levels kT=kF=k. Assume every constructor-field type inhabits Ui. Compute lev(Δp), the maximum L emitted by definition 122.13, and the maximum obtained if the parameter telescope were incorrectly omitted.

Lemma 122.14 — Every accepted binder yields a hypothesis

Let A satisfy I;+;openA pos and let x:A. Then HP(A,x) of definition 122.8 is defined and is a well-formed type. Every function type introduced by the recursive Π-clause of H has a domain containing no family of I. The family-free clause is selected exactly when no family of I occurs in A, and that clause returns 1. Once the simultaneous eliminators (indr)r are in scope, the term ihP(A,x) has type HP(A,x).

Proof of Lemma 122.14 — Every accepted binder yields a hypothesis

Proof. Induct on the occurrence-check derivation of A. If no family of I occurs in A, the first clause gives 1 and there is nothing more to check. This covers the base, external-application, identity, vector, and opaque-elimination clauses, because their side conditions say directly that every displayed type and term argument is family-free.

If A=Dtpv, the family clause of the occurrence check gives ϵ=+, δ=open and family-free p,v, so Ptpvx is well formed. No restriction is imposed on function types chosen inside the motive value itself. The eliminator typing rule gives indt(p,v,x):Ptpvx.

If A=y:BA, the occurrence check derived I;;blockedB pos. By lemma 122.7 no family of I occurs in B, so the induction hypothesis applies to A in the context extended by y:B, and y:BHP(A,xy) is well formed with a family-free domain. This is the step at which polarity is doing the work: without it the generated hypothesis could quantify over the very family being defined. Lambda abstraction over the induction-hypothesis term gives λy.ihP(A,xy) the displayed function type.

If A=y:BA, the stored derivation has a subderivation for B and a subderivation for A in the context extended by y:B. Choose wFV(B)FV(A)FV(P){x,y}. The two induction hypotheses give HP(B,π1x) and, in context y:B,w:A, the type HP(A,w) together with its generated term. First substitute π1x for y; then substitute π2x for w. Pair introduction gives (ihP(B,π1x),ihP(A,w)[π1x/y][π2x/w]):HP(B,π1x)×HP(A,w)[π1x/y][π2x/w]. If A=LiftuA, the occurrence derivation has a strict subderivation for A at the same state. Rule Lift-El gives LiftuAA, so conversion types x:A. The induction hypothesis defines and types HP(A,x) and its generated term. This is exactly the displayed lift clause of H and ihP. Finally, the recursion terminates because each clause recurses on a strict subderivation. ◻

Theorem 122.15 — Generated-rule well-formedness

Let B be accepted by Timpl-data. Every generated family, constructor, mutual eliminator, constructor computation rule, and no-confusion instance is well formed in Tfam-block at the levels solved for B.

Proof of Theorem 122.15 — Generated-rule well-formedness

Proof. Process dependency components in topological order. Simultaneous formation puts precisely the family constants of one component in scope. Constructor typing follows from the accepted telescope and result checks in definition 122.12. The remaining premise of Block-I is IΘs pos, and lemma 122.11 supplies exactly that derivation for every constructor binder; this is the step at which a rejected block such as bad fails to produce a Tfam-block introduction rule. For each constructor method, lemma 122.14 supplies a well-typed hypothesis type after every binder. The family-free clause is selected exactly at binder types that do not mention the block, and every function domain introduced by the hypothesis recursion is family-free. The mutual eliminator is then the simultaneous Tfam-block rule for those methods. Substitution of a constructor into its motive gives the type of the corresponding computation rule.

For no-confusion, distinct constructor heads map to distinct tags. Equal heads reduce constructor equality to equality of their telescope arguments, transported along the result-index equality generated by the constructor typing derivation. Repeat the two case analyses of definition 78.11. In a distinct-tag branch, fix X:U0; the branch gives a map from constructor equality to X. Abstracting X gives the displayed map into EmptyTimpl. In an equal-tag branch, the same construction returns aΘsb. Universe well-formedness follows from the solved maximum constraint and the fixed U1 codomain recorded in definition 122.13. ◻

Theorem 122.16 — Timpl-data elaboration soundness

If the declaration processor accepts B and returns a Tfam-block signature ΣB, then ΣB is a well-formed extension of Timpl. Every source constructor application elaborates to the constructor of the same name and type, and every generated source eliminator equation is a Tfam-block computation rule.

Proof of Theorem 122.16 — Timpl-data elaboration soundness

Proof. Checker termination is lemma 122.10. Acceptance gives well-formed telescopes, solved levels, closed dependency components, and the positivity derivations. Apply theorem 122.15 component by component. Translation is homomorphic on parameters, indices, constructor arguments, and constructor names, so constructor typing is preserved. The translation of an eliminator is the generated simultaneous eliminator; at a constructor its target reduction is the generated computation rule. Thus all three conclusions hold. ◻

The primitive-inductive restriction and the role of strict positivity follow the rule construction of Coquand and Paulin-Mohring, Sections 1.1–1.4 [CPM90]. Their calculus does not prove the checker theorem for Timpl-data; the preceding proofs use the finite grammar fixed in definition 122.1.

Suggested first pass.

None of these problems is a prerequisite for a later chapter. Begin with exercise 122.3, then complete exercise 122.5.

Exercise 122.3

★★☆ For the tree–forest block, write the two motives, all four method types, and the computation of indF on more(leaf(a),empty). Annotate both recursive steps by the constructor computation rule used.

Exercise 122.4

★★☆ Compare (DN)N and ND as constructor argument types for a family D. Give the complete polarity trace and explain why the first is outside the regular Timpl-data card even though its two sign reversals leave the occurrence positive.

Exercise 122.5

★★★ Practical project.datatype-block-positivity-checker Implement in Kappa the five-node grammar of base, function, pair, block-family, and external-family applications. Implement occurrence clauses 1–5 and then definition 122.8. Identity, primitive-vector, and strict-lift clauses, together with the opaque-elimination clause, remain outside the program. The finite program is simply typed: its function and pair nodes bind no variable, so it does not exercise the dependent-pair substitution of definition 122.8. Maintain positive sign, open ancestry, and exclusion from recursive or external-family arguments. Derive the first failing path rather than printing a fixed diagnostic. Accept tree-forest and branching; for the latter, print every generated hypothesis type. Reject negative-bad, nested-bad, double-negative, and former-bad, naming the failing sign, flag, or argument. Replay three oracle-failing mutations: treat a function domain as a codomain; reverse its sign but leave ancestry open; and omit the hypothesis generated for a function field. The second is not exposed by negative-bad, and the third changes no acceptance verdict. The program proves no normalization theorem and does not implement clauses 6–9.

Search the book

Type to search the local edition.