Lectures onType Theory
Chapter 126
Chapter 126Core route

Erasure and Execution of Dependent Definitions

The checked vector append declaration carries an element type, two lengths, and the vectors themselves. At run time only the constructor blocks and elements determine the result. Keeping the indices makes execution carry proof data; deleting every marked argument without a proof can change which substitution a function body receives. Erasure therefore needs a relevance judgment, a target representation, and an operational theorem.

An exact untyped target

Definition 126.1 — The Timpl-erasure system card

The source is the full Timpl signature of convention 110.16, extended by the accepted datatype and recursive declarations of chapter 122, chapter 123 together with the relevance annotation of definition 126.9. Neither definition 122.1 nor definition 123.1 carries relevance marks, so the annotation is extra data supplied with an already accepted declaration; it is checked by the judgment in definition 126.3, and no QTT grade or starred modality is assumed. Accepted source annotations are rechecked by the kernel-soundness theorem theorem 48.19; erasure does not replace that source judgment.

The target Texec is the untyped call-by-value calculus t::=xλx.tttCk(t1,,tn)case t of {Ck(x)tk}clos(f,t)call(t,t). A constructor tag records its runtime arity. A closure records a recursive function tag and the runtime part of its environment. Values are w::=λx.tCk(w1,,wn)clos(f,w). Every target case has pairwise distinct branch tags. Erasure obtains one branch per constructor from an accepted source case; raw case lists with a duplicate tag are not Texec phrases. This side condition makes branch selection functional. Write δt(f)=(y;x;tf) for the compiled recursive tag f, with captured environment y and formal parameters x. Each occurrence of a primitive natural-number or vector eliminator also receives a fresh recursive tag. The tag records the occurrence, its ordered runtime free variables, and the relevance marks on its branch binders. Thus primitive eliminators add no target syntax: they compile to the same clos/call forms as user declarations. Their exact tag bodies are given with the erasure equations in definition 126.10. Evaluation is the deterministic left-to-right call-by-value relation tw generated by XwwEValt1λx.tt2w2t[w2/x]wt1t2wEApp (tiwi)1inCk(t1,,tn)Ck(w1,,wn)ECon(tiwi)iclos(f,t)clos(f,w)EClos tCk(w)tk[w/xk]wcase t of {Cj(xj)tj}jwECase δt(f)=(y;x;tf)tclos(f,w)(tiwi)1intf[w/y][wi/x]wcall(t,t1,,tn)wECall There is no rule for a case whose scrutinee is a lambda or a closure, none for an application whose head is a constructor block, and none for a call whose head is not a closure or whose argument count differs from |x|; a term that reaches such a configuration is stuck. Representation well-formedness rules out malformed stored arities, but it does not by itself prove that an arbitrary target application reaches a lambda or that an arbitrary case reaches a block. For a source term equipped with an evaluation derivation, theorem 126.14 constructs the matching target derivation and thereby rules out those dynamic failures.

The observation on closed terminating Timpl data is the constructor tree with erased fields removed. The theorem below proves target well-formedness, a constructor/closure representation invariant, and forward simulation. Since Texec is untyped, no target type-preservation claim is made.

Lemma 126.2 — Texec values and evaluation are functional

Assume that δt contains at most one entry for each closure tag and that every Texec case has pairwise distinct branch tags.

  1. If w is a Texec value and wu, then u=w.

  2. If tw and tw, then w=w.

Proof of Lemma 126.2 — Texec values and evaluation are functional

Proof. For item 1, induct on the structure of w. A lambda has only E-Val. A constructor block can use E-Val or E-Con; in the latter derivation the induction hypotheses make every field evaluate to itself, so the conclusion is the original block. For a closure, replace the constructor tag and its fields by the fixed closure tag and environment, and replace E-Con by E-Clos; the componentwise induction hypotheses are unchanged. These are all value forms.

For item 2, induct on the first evaluation derivation and invert the second derivation on the outer syntax of t. The E-Val case is item 1. Two E-App derivations have equal function results by the induction hypothesis, hence the same lambda binder and body; their argument results and then their substituted-body results are equal by the corresponding induction hypotheses. Two E-Con derivations and two E-Clos derivations agree componentwise by the induction hypotheses. The possible overlap of E-Val with either rule is item 1.

For E-Case, the scrutinee induction hypothesis gives the same constructor block. Pairwise distinct tags select one common branch, simultaneous substitution installs the same field values, and the branch induction hypothesis gives the same result. For E-Call, the head induction hypothesis gives one closure tag and environment, functionality of δt gives one body and two formal telescopes, and the argument induction hypotheses give one argument vector. Both final premises therefore evaluate the same instantiated body, so their results agree by the body induction hypothesis. No other top rule applies to an application, constructor, closure, case, or call. This treats every evaluation-rule family. ◻

Definition 126.3 — Runtime relevance

Fix an environment marking each source variable xϱ:A, with ϱ{runtime,erased}. The runtime source phrases used by this chapter are e::=xλϵ,ϱ(x:A).eeϵ,ϱe(e,e)pr1(e)pr2(e)c(e)refleind2(x.C;et,ef,e)IC(e0;nϱn.rϱr.es;e)J(x.y.p.C;zϱz.er;eq)vind(P;e0;nϱn.aϱa.xs.rϱr.es;m,e)case e of {ck(xk)ek}kfy(e). Here IC is the raw natural-number eliminator of definition 28.21. Its displayed branch is a checked eta-long branch; the successor branch of vind is treated the same way. Eta expansion preserves source typing and judgmental equality by Timpl’s Π-eta rule. This erasure card chooses the checked eta-long representative, and the source term e in the simulation theorem below is that representative; no operational equation for a different surface spelling is assumed. The grammar therefore covers every term former in convention 110.16: universes, lifts, and type expressions occur in annotations, motives, and opaque erased argument slots and are static premises, while the remaining term constructors occur explicitly above. The generic constructor and case forms cover accepted user datatypes. The primitive constructors of 1,2,N, and Vec use the fixed annotations below; their primitive eliminators use the four displayed forms. Formally, let as range over any checked raw Timpl term. An application argument, constructor field, call capture, or call input whose declaration mark is erased is an opaque as slot rather than a recursive e slot. In particular, a type argument may occupy an erased application or call slot without becoming a runtime phrase. Other premises concluded by Rel-Erased remain the explicit syntax shown in their rule: for example, S-J evaluates its proof to expose reflexivity even though the target deletes that proof. Thus target deletion does not by itself mean that every erased source premise is unevaluated.

The last form is a saturated call to a declaration in an accepted first-order Timpl-rec group; y is its captured environment. Unsaturated or first-class uses of a recursive declaration are outside this erasure card.

There are two judgments Γe runtime and Γe erased. The second means that the whole phrase occupies a static position and is deleted. It is generated by source typing: Γe:AΓe erasedRelErased. The runtime rules are xruntime:AΓΓx runtimeRelVarΓ,xruntime:Ab runtimeΓλϵ,runtime(x:A).b runtimeRelLamR Γf runtimeΓa runtimeΓfϵ,runtimea runtimeRelAppR. Γ,xerased:Ab runtimeΓa erasedΓλϵ,erased(x:A).bϵ,eraseda runtimeRelAppE. Thus this exact fragment accepts erased application only as an administrative redex with its erased abstraction visible. A surface elaborator may expose such a redex when a closed head normalizes to an erased abstraction, but that preprocessing theorem is not part of Timpl-erasure; an application of a variable at an erased domain is rejected by this card. Dependent pairs and their projections retain both components: Γa runtimeΓb runtimeΓ(a,b) runtimeRelPair. Γs runtimeΓpr1(s) runtimeRelFstΓs runtimeΓpr2(s) runtimeRelSnd. The proof constructor has a target tag when a proof is retained inside a runtime pair or user constructor: Γa:AΓrefla runtimeRelRefl. If the accepted constructor annotation is c:(x1κ1:A1)(xnκn:An)Dpı, where κi is the constructor-field retention mark, then (Γai κi)1inΓc(a) runtimeRelCon. For a constructor case, give the variables of branch k independent branch-use marks ϱk, and write xkϱk for the resulting branch context. If the field-retention vector of ck is κk, admissibility requires ϱk,i=runtimeκk,i=runtime. The converse is not required: a retained constructor field may be ignored by the branch body. Then Γe runtime(Γ,xkϱkek runtime)kΓcase e of {ck(xk)ek}k runtimeRelCase. Motives, index equations, and inaccessible patterns belong to the Rel-Erased premises of the source typing derivation and produce no target phrase. Finally, if the checked source declaration record is δs(f)=(yσ;xϱ;bf), then (Γyj σj)j(Γai ϱi)iyσ,xϱbf runtimeΓfy(a) runtimeRelCall.

The four primitive eliminators have separate rules. Their omitted formation premises are exactly their Timpl typing rules and are not replaced by the relevance judgment: Γb runtimeΓet runtimeΓef runtimeΓind2(x.C;et,ef,b) runtimeRelBoolElim. Γe0 runtimeΓ,nϱn:N,rϱr:C(n)es runtimeΓm runtimeΓIC(e0;nϱn.rϱr.es;m) runtimeRelNatElim. The predecessor stored by Csuc is runtime even when the branch mark ϱn is erased: the recursive closure needs it to make its next call. The branch mark controls only whether es may use that predecessor. For identity elimination, the proof and motive are static, but the reflexive endpoint is retained exactly when the reflexive branch uses it: Γ,zϱz:Aer runtimeΓa ϱzΓeq erasedΓJA;a;b(x.y.p.C;zϱz.er;eq) runtimeRelJ. The annotations A,a,b,C are the raw annotations of definition 30.1; in particular, a is not guessed from the proof. Finally, abbreviate the successor-branch context by Δs:=Γ,nϱn:N,aϱa:A,xsruntime:Vec(A,n),rϱr:P(n,xs). Then Γe0 runtimeΔses runtimeΓm ϱmΓys runtimeΓvind(P;e0;nϱn.aϱa.xs.rϱr.es;m,ys) runtimeRelVecElim. If ϱm=runtime, admissibility also requires the predecessor field of vcons to be runtime, because the recursive target call then receives that predecessor as its runtime index. The structural field xs is runtime in every admissible annotation. More generally, a runtime-marked branch variable may name only a runtime constructor field; an erased branch variable may name a retained field and simply leave it unused.

Thus an erased variable can occur only below a premise concluded by Rel-Erased; recursive closures capture exactly the runtime variables listed in y. An accepted source declaration is erasable when its checked Timpl term satisfies this judgment.

Exercise 126.1

★☆☆ Let Γ=(yruntime:2,xerased:2). Give the complete relevance derivation for λexplicit,runtime(z:2).zexplicit,runtimey. Then prove by inversion that ind2(u.N;0,suc0,x) has no runtime-relevance derivation in Γ. Name the missing premise. (Eight lines.)

Lemma 126.4 — Relevance is stable under marked substitution

Suppose Γa:A.

  1. If Γa runtime and Γ,xruntime:Ae runtime, then Γe[a/x] runtime.

  2. If Γa erased and Γ,xerased:Ae runtime, then Γe[a/x] runtime.

Both clauses extend componentwise to a well-typed simultaneous substitution that respects the marks of a telescope.

Proof of Lemma 126.4 — Relevance is stable under marked substitution

Proof. Induct on the relevance derivation for e, renaming every traversed binder away from the free variables of a. In Rel-Var, a runtime variable is either x, in which case item 1 uses its premise, or a different runtime variable retained by substitution; item 2 cannot meet x in a runtime variable rule. Rule Rel-Erased is reconstructed from ordinary Timpl substitution. Every congruence rule applies the induction hypotheses to its runtime premises and ordinary typing substitution to its erased premises. For Rel-Con and Rel-Case, use the stored field and branch marks one component at a time. The four eliminator rules apply the hypotheses to the retained scrutinee and branch premises; Rel-J uses item 1 or item 2 according to ϱz. Rule Rel-Call treats the capture and input telescopes componentwise and reuses its checked body premise. These are all rule families of definition 126.3. Induction on a telescope gives the simultaneous form. ◻

Definition 126.5 — Source call-by-value evaluation

Write ev for the source evaluation relation used by this chapter. Texec uses the same evaluation glyph in definition 126.1; the disjoint source and target grammars determine which rule card applies, and no derivation mixes their rules. Source values are lambdas under either relevance mark, pairs of values, reflexivity values, and primitive or declared constructors whose runtime fields are values and whose erased fields remain as checked static source terms. Call the pairs, reflexivity values, and primitive or declared constructor values the source data values. An erased abstraction may be an intermediate source value, but Rel-App-E admits it in a runtime term only at a visible administrative redex; hence it has no final target value-representation clause. If a source argument ai has mark ϱi, write a^i for the runtime value vi when ϱi=runtime and aivi, and write a^i=ai without an evaluation premise when ϱi=erased. Thus erased type arguments are well-typed static syntax, not source runtime phrases. If δs(f)=(yσ;xϱ;bf) is a checked source declaration, the rules are as follows.

On values, annotated applications, pairs, projections, constructors, cases, and the four primitive eliminators, this card is exactly the optional implementation relation T,cbv of definition 124.2, after the uniform renaming TS and T,cbv. The only rule added here is S-Call for a checked recursive declaration record δs. Thus the two cards do not choose different call-by-value orders on their common grammar.

Values and functions use XvvSVal fλϵ,runtime(x:A).bavab[va/x]vfϵ,runtimeavSAppR fλϵ,erased(x:A).bb[a/x]vfϵ,erasedavSAppE. The erased rule substitutes its checked static argument but does not evaluate it. Pairing and projection use avabvb(a,b)(va,vb)SPairs(va,vb)pr1(s)vaSFsts(va,vb)pr2(s)vbSSnd. For every primitive or declared constructor and every accepted datatype case, (aivi)κi=runtimec(a1,,an)c(a^1,,a^n)SCon eck(a^)ek[a^/xk]vcase e of {cj(xj)ej}jvSCase. The Boolean rules are the two instances bttetvind2(x.C;et,ef,b)vSBoolTbffefvind2(x.C;et,ef,b)vSBoolF. For the next two rules, abbreviate NC(e0,es;m):=IC(e0;nϱn.rϱr.es;m). Natural-number elimination is generated by m0e0vNC(e0,es;m)vSNatZ msuc(vn)NC(e0,es;vn)vres[vn/n,vr/r]vNC(e0,es;m)vSNatS. The identity rule evaluates the proof to the only constructor that exposes a root computation: eqreflvqer[a/z]vJA;a;b(x.y.p.C;zϱz.er;eq)vSJ. Vector elimination has its two indexed rules: m0ysvnile0vvind(P;e0;nϱn.aϱa.xs.rϱr.es;m,ys)vSVecNil msuc(vn)ysvcons(vn,va,vxs)vind(P;e0;nϱn.aϱa.xs.rϱr.es;vn,vxs)vres[vn/n,va/a,vxs/xs,vr/r]vvind(P;e0;nϱn.aϱa.xs.rϱr.es;m,ys)vSVecCons. Finally, saturated user recursion evaluates only its runtime captures and inputs; erased captures and inputs are substituted as checked static syntax: (yjuj)σj=runtime(aivi)ϱi=runtimebf[y^/y,a^/x]vδs(f)=(yσ;xϱ;bf)fy(a)vSCall. There is no rule for a neutral scrutinee, a mismatched constructor, or a call with the wrong arity. Hence the relation is partial on raw closed syntax; the theorem below assumes an evaluation derivation rather than inferring termination from typing.

Lemma 126.6 — Source evaluation is sound for judgmental equality

If Γe:A and ev, then Γev:A.

Proof of Lemma 126.6 — Source evaluation is sound for judgmental equality

Proof. Induct on the displayed evaluation derivation, retaining its source typing derivation. Rule S-Val uses reflexivity. For S-App-R, inversion gives f:x:A0ϵ,runtimeB and a:A0. The first two induction hypotheses give fλx.b and ava. Application congruence, Π-computation, and the body induction hypothesis form the annotated chain facongruence(λx.b)vaΠβb[va/x]IHv. The middle equality has type B[va/x]; substitution congruence for ava gives B[a/x]B[va/x], and conversion puts the entire chain at the required B[a/x]. The erased-binder case uses the same chain with the unchanged checked argument a, so its middle term is b[a/x].

For S-Pair, congruence combines the two induction hypotheses; the second one is converted from B[a] to B[va] using the first component equality. For S-Fst, compose scrutinee congruence with Σ-first computation. For S-Snd, compose it with Σ-second computation and convert the result from the fibre over the evaluated first component to the fibre over pr1(s), using congruence of first projection.

Rule S-Con uses constructor congruence on each runtime field, with its induction hypothesis, and reflexivity on every retained static field. In S-Case, scrutinee congruence reaches the selected constructor; the generated Block-comp equation reduces the case to the selected branch, and simultaneous substitution congruence followed by the branch induction hypothesis reaches v. The motive instance is converted along the scrutinee equality. Rules S-Bool-T and S-Bool-F instantiate this case argument with the primitive tt and ff computation equations, respectively.

For S-Nat-Z, combine scrutinee congruence, Nat-comp1, and the base induction hypothesis. For S-Nat-S, scrutinee congruence and Nat-comp2 expose the step body. The induction hypotheses for the predecessor and recursive result justify its simultaneous substitution; the step-body induction hypothesis reaches v. Substitution congruence along msuc(vn) converts the final motive from C(suc(vn)) to C(m).

For S-J, the proof induction hypothesis gives eqreflvq. Identity-value inversion supplies the endpoint equalities, so vqab. After these conversions, Id-comp exposes er[a/z], and the branch induction hypothesis reaches v at the original motive instance. Rule S-Vec-Nil uses the index and vector induction hypotheses, Vec-comp1, and conversion along m0 and ysvnil. Rule S-Vec-Cons uses Vec-comp2; simultaneous congruence substitutes the equal predecessor, head, tail, and recursive result, while conversion along msuc(vn) and ysvcons(vn,va,vxs) restores the declared indexed motive.

Finally, S-Call applies congruence to every evaluated runtime capture and input and reflexivity to the static ones. The defining equation committed for the accepted saturated Timpl-rec declaration exposes bf[y^,a^]; simultaneous substitution congruence and the body induction hypothesis reach v. These are all rule families of definition 126.5. ◻

Lemma 126.7 — Source evaluation preserves typing

If Γe:A and ev, then Γv:A.

Proof of Lemma 126.7 — Source evaluation preserves typing

Proof. By lemma 126.6, Γev:A. Formation of a judgmental-equality derivation includes typing of both endpoints at its displayed type, hence Γv:A. The dependent conversions needed to obtain that single equality are the application, pair, projection, motive, index, endpoint, and call cases printed in the preceding proof. ◻

Lemma 126.8 — Source evaluation preserves runtime relevance

Suppose Γe runtimeandev. Then Γv runtime in the unchanged marked context.

Proof of Lemma 126.8 — Source evaluation preserves runtime relevance

Proof. Induct on the evaluation derivation while inverting the runtime-relevance derivation for its conclusion. Rule S-Val retains that derivation. In S-App-R, the induction hypotheses make the resulting runtime-binder lambda and argument value runtime; inversion of Rel-Lam-R, followed by the runtime clause of lemma 126.4, makes the substituted body runtime, and the third induction hypothesis gives the result. For S-App-E, inversion of Rel-App-E supplies the runtime body under an erased binder and the erased argument. The erased substitution clause makes b[a/x] runtime, so the body induction hypothesis applies.

Rule S-Pair reconstructs Rel-Pair from its two induction hypotheses. Projection inversion supplies runtime relevance for the selected pair component. In S-Con, apply the induction hypotheses to precisely the runtime fields and retain the original Rel-Erased premises for the static fields; Rel-Con then reconstructs the value judgment. For S-Case, the constructor induction hypothesis and relevance inversion recover the marked fields. Apply the simultaneous form of lemma 126.4 to the selected branch and then its evaluation induction hypothesis.

The two Boolean cases reuse the selected branch judgment. In S-Nat-S and S-Vec-Cons, the induction hypotheses make the retained predecessor, structural child, element, and recursive result runtime exactly when their branch marks demand them. Marked simultaneous substitution makes the successor body runtime; its induction hypothesis concludes. The zero and nil cases use their base judgments. In S-J, the proof remains erased; substitute the annotated endpoint a into the reflexive branch according to ϱz, then apply the branch induction hypothesis. Finally, S-Call uses the induction hypotheses for runtime captures and inputs, the unchanged erased premises for the other components, and marked simultaneous substitution in the Rel-Call body before applying the body induction hypothesis. These cases exhaust definition 126.5. ◻

Definition 126.9 — Relevance annotation of an accepted declaration

Let B be a block accepted by definition 122.1 and G a group accepted by definition 123.1. A relevance annotation of the pair assigns one ϱ{runtime,erased} to every constructor field of every Θs, to every binder of every input telescope Δi, to every binder introduced by a clause split of G, and to the branch binders of each primitive natural-number, identity, or vector eliminator occurrence. The primitive constructors use the same convention: suc’s predecessor and vcons’s recursive vector field are runtime. Write κn,κa for the chosen constructor-field marks on vcons’s predecessor and element fields, respectively; these are distinct from the branch-use marks ϱn,ϱa. It is admissible when

  1. every type-valued binder—a binder whose declared type is judgmentally a universe—is marked erased;

  2. every position at which the accepted clause matrices split is marked runtime;

  3. every argument named by an accepted structural or lexicographic certificate of definition 123.1 is marked runtime; and

  4. for a primitive vector branch, ϱn=runtime implies κn=runtime, and ϱa=runtime implies κa=runtime; and

  5. for every user-constructor branch binder, ϱk,i=runtime implies κk,i=runtime; and

  6. the runtime arity recorded for a target constructor tag Cc is the number of runtime fields of c, taken in source order.

For a vector eliminator whose index m is runtime, κn=runtime as well. Every type-valued argument is erased: Texec has no representation for a universe or a source type expression. A data-valued index, such as a natural-number length, may instead be marked runtime when the source runtime grammar and the target representation contain its value forms. Subject to these constraints, the remaining annotation is a choice, and definition 126.3 is the judgment that decides whether that choice survives deletion; the counterexample after it is the choice that does not.

The first clause of the relevance judgment is load bearing. Suppose xerased:2. Allowing the term if x then 0 else 1 would leave the target with no branch selector after deleting x.

Definition 126.10 — Erasure

For an erasable term e, write |e| for its Texec erasure. The decisive clauses are |x|=x,|λϵ,runtime(x:A).b|=λx.|b|,|fϵ,runtimea|=|f||a|,|λϵ,erased(x:A).b|=|b|,|fϵ,eraseda|=|f|. Dependent pairs, projections, reflexivity, and the nonrecursive Boolean eliminator erase by |(a,b)|=Cpair(|a|,|b|),|pr1(s)|=case |s| of {Cpair(x,y)x},|pr2(s)|=case |s| of {Cpair(x,y)y},|refla|=Crefl,|ind2(x.C;et,ef,b)|=case |b| of {Ctt|et|,Cff|ef|}. Let run(c)=(j1<<jr) list the runtime fields of a constructor. For a recursive input telescope (x1ϱ1:A1),,(xnϱn:An), define run(f)=(j1<<jr) by ϱjk=runtime, in source order. The remaining clauses are |c(a1,,an)|=Cc(|aj1|,,|ajr|),|fy(a1,,an)|=call(clos(f,|y|),|aj1|,,|ajr|),|case e of {ck(xk)ek}k|=case |e| of {Cck(xk|κk=runtime)|ek|}k. Here |y| contains exactly those captures whose source marks are runtime, in declaration order, and the target pattern retains xk,i exactly when the corresponding constructor field has κk,i=runtime. A retained field whose branch-use mark is erased therefore still contributes an unused target pattern binder; this is what makes the pattern arity equal to the target constructor arity. Types, motives, the proof argument of Rel-J, and every entire premise concluded by Rel-Erased produce no target phrase. A proof retained in a pair or a constructor is represented by Crefl; erasure does not silently delete an unmarked Σ-component.

It remains to give the exact recursive tags promised above. Erasure is defined on the checked annotated derivation, whose eliminator nodes carry stable occurrence identifiers and lexical capture slots. Substitution fills a slot with a target expression; it does not regenerate the tag or flatten that expression’s free variables. This convention is the one needed for the literal substitution equation below.

For an ordinary checked recursive declaration δs(f)=(yσ;xϱ;bf)withyσ,xϱbf runtime, the compiler creates the target entry δt(f)=(y|σ=runtime;x|ϱ=runtime;|bf|). The relevance derivation proves that the free variables of |bf| are among precisely those two retained lists. Thus the closure emitted at a call stores the first list, the call supplies the second list, and E-Call substitutes the target values in source declaration order. This construction is applied simultaneously to every declaration of an accepted recursive group; a recursive occurrence in |bf| names the corresponding compiled tag rather than unfolding its body.

For a natural-number eliminator at occurrence o, put t0=|e0|, ts=|es|, let y be its lexical runtime capture slots in source-context order, and choose the tag νN(o). Set δt(νN(o))=(y;m;case m of{C0t0,Csuc(n)ts.) When ϱr=runtime, define ts:=(λr.ts)call(clos(νN(o),y),n); when ϱr=erased, put ts=ts. The explicit beta-redex is load bearing: target call-by-value evaluates the recursive call to a value before substituting that value for r, just as S-Nat-S does. A direct occurrence of n in ts requires ϱn=runtime; the administrative recursive call also uses the retained successor field n whenever ϱr=runtime. Then |IC(e0;nϱn.rϱr.es;m)|=call(clos(νN(o),y),|m|).

For a vector eliminator, define u0=|e0|, us=|es|, take the ordered lexical runtime capture slots z, and choose the occurrence tag νV(o). Its one scrutinee input follows an optional runtime index input: δt(νV(o))=(z;[m]ϱm,ys;case ys of{Cvnilu0,Cvcons([n]κn,[a]κa,xs)us.) The pattern retains the predecessor and element exactly under their constructor-field marks, and xs is the retained structural child. The admissibility implications above ensure that every runtime occurrence of a branch variable has a corresponding target binder. When ϱr=runtime, put us:=(λr.us)call(clos(νV(o),z),[n]ϱm,xs). For ϱr=erased, put us=us. As in the natural-number tag, the beta-redex forces the recursive call before installing its value in the step body.

Erased branch variables do not occur in us by the relevance derivation. Consequently |vind(P;e0;nϱn.aϱa.xs.rϱr.es;m,ys)|=call(clos(νV(o),z),[|m|]ϱm,|ys|). Square brackets mean that the listed target argument is present exactly for the runtime mark. Freshness of νN(o),νV(o) includes the source eliminator occurrence, so two syntactically equal branch bodies at different scopes cannot capture one another’s variables.

Finally, identity elimination has no recursive tag: |JA;a;b(x.y.p.C;zϱz.er;eq)|={|er|[|a|/z],ϱz=runtime,|er|,ϱz=erased. This structural clause recurses only on the displayed branch subderivation. By lemma 126.11 it agrees with |er[a/z]|, but that larger substituted phrase is not used to define erasure. The clause is safe only with the three premises of Rel-J; in particular it is not a rule saying that an arbitrary proof may be inspected or that equality reflection holds. These equations exhaust the source grammar of definition 126.3.

For vector append, mark A,m,n erased and xs,ys runtime. Erasure emits the closure |append|=clos(append,) with an empty captured environment. Its compiled entry is δt(append)=(;xs,ys;bappend), where rappend(a,zs,ys):=Cvcons(a,call(clos(append,),zs,ys)) and bappend:=case xs of {Cvnilys,Cvcons(a,zs)rappend(a,zs,ys). This is a target body definition, not a small-step equation. A run is a big-step derivation using E-Call, E-Case, and E-Con. The target constructor stores neither the predecessor length nor the result index. The recursive runtime argument remains the direct child xs.

Exercise 126.2

★☆☆ Fix an accepted constructor pack:(ierased:N)(bruntime:2)D whose target tag has runtime arity one. Calculate the erasure of pack(suc0,tt). Then calculate the target pattern for a source case branch pack(ierased,berased)0. State why the target pattern must retain b, even though the branch body does not use it. (Six lines.)

Lemma 126.11 — Relevance and erasure under substitution

Let Γv:A be an erasable source term with Γv runtime. If Γ,xruntime:Ae runtime, then Γe[v/x] runtime,|e[v/x]|=|e|[|v|/x]. If instead Γa:A is any checked source term and Γ,xerased:Ae runtime, then Γe[a/x] runtime,|e[a/x]|=|e|.

Proof of Lemma 126.11 — Relevance and erasure under substitution

Proof. Induct on the relevance derivation. Ordinary source substitution gives the relevance conclusion in every rule; the following induction simultaneously proves the erasure equation. The variable case is the displayed substitution in the runtime branch; the erased-variable case cannot occur in a runtime position. At a binder, rename its variable away from the free variables of the substituend and apply the induction hypothesis to the body. Runtime application preserves both subterms. Erased application deletes the argument, so substitution in that argument also disappears. Pair and projection cases apply the induction hypotheses to their retained subterms; reflexivity emits a nullary tag, so either substitution equation is immediate there. Constructor, Boolean case, and user-datatype case clauses apply the induction hypotheses exactly to retained fields and runtime-used branch variables. The target pattern also binds retained-but-unused fields; because those names do not occur in |ek|, substitution for them leaves the target branch body unchanged.

For Rel-Nat-Elim and Rel-Vec-Elim, the stable occurrence tag is unchanged. A runtime substitution fills the corresponding lexical capture slot with |v|, while an erased substitution has no slot. Applying the induction hypotheses to the base and step bodies therefore gives the same δ-record on both sides, up to the binder renaming fixed before the induction. In Rel-J, apply the induction hypothesis to er and use associativity of capture-avoiding substitution after renaming z away from the free variables of v; the erased proof premise produces no target subterm. A user recursive call substitutes in its explicit capture vector and retained inputs. These cases exhaust the relevance rules and prove both formulas. ◻

Exercise 126.3

★☆☆ In the marked context xruntime:2, let e=(x,reflx), with type z:2Id2(z,z). For v=tt, compute both sides of |e[v/x]|=|e|[|v|/x] and identify the erasure clause that prevents the proof annotation from creating a target free variable. (Five lines.)

Representation replaces target typing

Definition 126.12 — Value representation

The relation vRw between a closed source value and a closed Texec value is generated by

  1. a source lambda with a runtime binder relates to the target lambda that erasure emits. Erased abstractions occur only inside the administrative redex of Rel-App-E, so they have no standalone clause in this value relation. The administrative closure clos(f,w) occurring inside a translated saturated call is well formed when its tag is the compiled tag and its stored values are related to the runtime captures. It has no standalone source-value case, because definition 126.3 excludes first-class recursive declarations;

  2. a source constructor relates to the target block with the same tag and runtime arity when corresponding retained fields are related; and

  3. (v1,v2) relates to Cpair(w1,w2) when viRwi for i=1,2, and every reflexivity value relates to the nullary tag Crefl; and

  4. the canonical Timpl constants 0, tt, ff, relate to their fixed nullary target tags, and suc(v) relates to Csuc(w) whenever vRw.

A target term is representation well formed for a declaration environment when every constructor has the declared runtime arity, every case has pairwise distinct tags, every branch for a constructor tag binds that same runtime arity, every closure tag names an erased body, every captured environment has the stored runtime length, and every generated call supplies the target entry’s runtime input arity. The property is inherited by subterms under their displayed binders. It is a syntactic representation invariant, not a progress theorem: it does not assert that an arbitrary application head evaluates to a lambda or that an arbitrary case scrutinee evaluates to a constructor.

Lemma 126.13 — Erasure produces well-formed target syntax

If e is an erasable closed Timpl term, then |e| is a closed, representation-well-formed Texec term. If v is a source data value or a source lambda with a runtime binder, and v runtime, then there is a target value w with vRw and |v|=w.

Proof of Lemma 126.13 — Erasure produces well-formed target syntax

Proof. Induct on the relevance derivation. Runtime binders account for all target free variables, while erased binders introduce none. Constructor acceptance fixes the retained-field order and arity. Pairing fixes arity two; reflexivity fixes arity zero; and either projection emits a one-branch case over the pair tag. A runtime abstraction erases to a target lambda. The Rel-Call case emits a closure only as the head of a saturated target call. The recursive declaration compiler records the function tag, runtime environment length, and runtime input arity used by that clause. The two primitive recursive eliminators record the same data in their occurrence tags. Case erasure binds exactly the fields present in the target tag, including a retained field unused by its source branch body, and Rel-J emits the checked reflexive branch after the displayed capture-avoiding substitution. For a data value or runtime-binder lambda, the same induction ends in the corresponding clause of R. The Rel-App-E case is not a value. The Rel-Call case produces an administrative closure but cannot be the final source-value case. ◻

Theorem 126.14 — Forward execution simulation

Let e be a closed Timpl term with e:A and e runtime. If source call-by-value evaluation derives ev, then v is either a source data value or a lambda with a runtime binder, and Texec evaluation derives |e|w for a unique value w satisfying vRw.

Proof of Theorem 126.14 — Forward execution simulation

Proof. By lemma 126.7, lemma 126.8, the result v is typed at A and runtime relevant. Inversion of its value grammar therefore yields a source data value or a lambda with a runtime binder. To construct the target derivation, induct on the source evaluation derivation while carrying its typing and runtime-relevance derivations. In the value case, relevance inversion excludes an erased-binder lambda and leaves exactly a data value or runtime-binder lambda; apply lemma 126.13. In the runtime beta case, use the induction hypotheses for the function and argument. Target beta substitutes their erasures. Source typing preservation and source relevance preservation make the evaluated argument both typed and runtime; by lemma 126.11, the result is the erasure of the substituted source body. In the erased beta case the target term is the erasure of the visible abstraction, hence |b|, immediately. Typing of S-App-E supplies the checked static argument a:A, and the erased equation of lemma 126.11 identifies |b| with |b[a/x]|, the source reduct used by that rule. Neither source nor target evaluates the erased argument. The syntactic visibility needed for this step is exactly the premise shape of Rel-App-E: its erased-lambda head is a source value and needs no simulation hypothesis. Apply the induction hypothesis to the strict derivation of b[a/x]v; its target term is |b[a/x]|=|b|, which completes the erased beta case.

A pair evaluates both components by the two induction hypotheses and then uses E-Con at Cpair. Either projection first obtains that pair block and then uses E-Case to select the corresponding target component. Reflexivity is a value and emits Crefl. A primitive or declared constructor evaluates precisely its retained fields by the induction hypotheses, leaves the erased fields as static syntax on the source side, and uses E-Con at its declared target arity.

For a user-datatype case, source typing preservation and source relevance preservation make every retained selected field a typed runtime term. The simultaneous form of lemma 126.11 identifies the erased source branch with the target branch after runtime substitution; its erased clause deletes the static-field substitutions. The branch induction hypothesis then finishes. Target pattern matching also binds every retained-but-unused field, so its arity agrees with the constructor block.

For Boolean elimination, the induction hypothesis for the scrutinee yields either Ctt or Cff; E-Case selects the same branch as the source computation rule, and the branch induction hypothesis finishes. For natural-number elimination, distinguish the source zero and successor rules. The zero rule enters the C0 branch of δt(νN(o)). The successor rule enters its Csuc branch; the recursive source subderivation is strictly smaller than the displayed eliminator derivation, so its induction hypothesis evaluates the recursive target call to the erasure of vr when r is runtime. Rule E-App then contracts the displayed administrative beta-redex, installing that value in ts before the branch-body induction hypothesis is used. Source typing preservation and source relevance preservation make the predecessor and recursive result admissible for the simultaneous runtime substitutions. When r is erased that call is absent, and the erased-substitution half of lemma 126.11 identifies the target body. Runtime or erased use of the predecessor is handled by the other half of the same lemma.

For S-Vec-Nil, replace the natural tag νN(o) in the preceding zero-case construction by the vector tag νV(o), replace branch C0 by Cvnil, and use the base method t0; these renamings preserve the empty capture telescope and the base-result typing premise. For S-Vec-Cons, replace Csuc by Cvcons, its predecessor binder by the four binders n,a,xs,r, and νN(o) by νV(o). In that rule the structural child xs is retained, so the target recursive call is on exactly the child used by the source eliminator. If the index input is runtime, admissibility also retains its predecessor and the recursive target call receives it. The recursive induction hypothesis and E-App evaluate the displayed administrative beta-redex before substituting the recursive value for r. The induction hypotheses for the retained element and branch body, followed by simultaneous erasure substitution for n,a,xs,r, establish the successor equation. The premises of that substitution are supplied by source typing preservation and source relevance preservation for the evaluated predecessor, element, structural child, and recursive result.

In the identity rule, the source derivation evaluates eq to some reflvq and then evaluates er[a/z], where a is the printed annotation rather than the evaluated endpoint. Source typing preservation and source relevance preservation, together with the marked premise for a, justify the appropriate clause of lemma 126.11. The target has already deleted the proof evaluation and is exactly |er[a/z]|; the induction hypothesis for the reflexive branch finishes. This use neither inspects a neutral proof nor requires equality reflection. At a user recursive call, the source and target evaluate the same runtime captures and inputs. The source additionally substitutes the unchanged erased syntax, which disappears by the erased substitution lemma. Source typing preservation and source relevance preservation make each evaluated runtime capture and input admissible for the runtime clauses of that lemma; the Rel-Call body premise supplies the remaining marked substitutions. Closure well-formedness supplies the compiled body and the induction hypothesis applies to the strict body-evaluation subderivation. These cases cover every runtime form in definition 126.3. Uniqueness of w is lemma 126.2. ◻

Removing runtime relevance makes the theorem false. The Boolean counterexample after definition 126.3 evaluates to two different numerals for its two erased inputs, while both source applications have the same target erasure.

Exercise 126.4

★☆☆ Erase and evaluate append(A,1,1,vcons(0,a,vnil),vcons(0,b,vnil)). Display the target constructor tree and annotate each case selection.

Coinductive execution has a separate theorem

Definition 126.15 — The Timpl-co-erasure card

Timpl-co-erasure instantiates the stream type and head/tail definitions of definition 124.1 at one fixed closed accepted Timpl data type A:Ui, with accepted retention annotations for every constructor of A. Function-valued and otherwise non-data stream elements remain outside this card. For a compiled group with the generated state datatype S=StateG of definition 124.11, that helper block must be an accepted Timpl data type with explicit admissible retention annotations, and its generated maps h:SA and t:SS must satisfy runtime relevance under those annotations.

There is one further execution restriction. Call a closed data type runtime first order when every retained constructor or pair field is again runtime-first-order data and no retained field has a Π-type; erased fields may have arbitrary accepted Timpl types. A first-order map body is built from variables of runtime-first-order data type, ,tt,ff,0,suc, reflexivity, pairs, and accepted data constructors, together with datatype cases and the Boolean, natural, identity, and vector eliminators when every runtime premise and branch is again a first-order map body. Constructor arguments at erased fields are arbitrary checked static terms. There is no lambda or application inside a body and no named call; the only permitted lambda and application are the outer λs.r defining h or t and its saturated call at the state. Acceptance requires A, S, the initial state expression, and both generated map bodies to satisfy these conditions. This finite grammar is exactly the boundary at which weak source CBV and the normalizer of lemma 124.3 have the same retained constructor result.

Write Γr;Γefor:B for the least formation judgment generated by those clauses. The context Γr contains data variables at runtime-first-order types. The context Γe contains variables that may occur only in checked static arguments. A branch extends the appropriate context by each field according to its relevance annotation; the recursive-result binder of a natural or vector eliminator extends Γr. Thus the judgment records a finite syntax derivation. It is not the extensional relation T of definition 124.2.

Thus the card covers neither an arbitrary unannotated state telescope nor a head or transition rejected by Timpl-erasure, and it excludes a generated map with a retained higher-order field or an internal helper application. The target signature fixes Cstream as an arity-two tag whose fields are nullary closures: h is a nullary head thunk and k a nullary tail closure. Erasure of the coiterator elaboration of definition 124.11 is |coiter(h,t,s)|:=Cstream(clos(h,|s|),clos(t,|s|)), where h and t are fresh nullary closure tags, not the ordinary compiled tags of h and t. For a fresh target variable s, their entries are δt(h)=(s;;|h(s)|) and δt(t)=(s;;(λs.Cstream(clos(h,s),clos(t,s)))|t(s)|). The beta-redex in the second body computes the next state once and stores the result in both closures of the next stream block. In particular, compiling t:SS as an ordinary tag would be wrong: that tag returns a state, whereas a tail observation must return a Cstream block. The target observer is a separate inductive judgment rather than an extra Texec term former. Write Obs(q,o,w) when the target stream block q produces value w after observation word o. It is generated by call(h)wObs(Cstream(h,k),head,w)ObsHead and call(k)Cstream(h,k)Obs(Cstream(h,k),o,w)Obs(Cstream(h,k),tailo,w)ObsTail. Thus exactly one of the two closures is forced per observation symbol, and the tail premise requires the forced closure to return the next Cstream block. This card inherits the source productivity theorem only for accepted stream groups and proves no normalization or generic coinductive simulation.

Lemma 126.16 — Target observation is functional

Assume that the target signature and case tables satisfy the hypotheses of lemma 126.2. If Obs(q,o,w) and Obs(q,o,w), then w=w.

Proof of Lemma 126.16 — Target observation is functional

Proof. Induct on the first observation derivation and invert the second derivation on the common observation word. In the head case, both premises evaluate call(h); target determinism gives equal results. In the tail case, target determinism makes the two evaluations of call(k) return the same stream block Cstream(h,k). The induction hypothesis applied to the two remaining derivations at that block gives equal final values. These are the two observation rules. ◻

For from(0), the target head closure returns zero. Forcing the tail closure constructs the state one; forcing the resulting head closure returns one. No finite target value contains all future naturals.

Exercise 126.5

★☆☆ Let q0=|coiter(h,t,0)| for h(n)=n and t(n)=sucn. Derive Obs(q0,head,C0) and Obs(q0,tailhead,Csuc(C0)). Name the closure forced at each premise and the stream block returned by the tail closure.

Lemma 126.17 — First-order source and normalizer agreement

Let Σ be the accepted group-free Timpl signature determined by definition 126.15. Let Γr;Γefor:B, where B is runtime first order. Let θ be a well-typed closing substitution that maps every variable of Γr to a closed source data value and every variable of Γe to a closed checked static term. Put nr,θ:=nfΣ,B[θ](r[θ]). There is a unique source data value u:B[θ], among the results of source evaluation of r[θ], such that r[θ]u,nf(u)=nr,θ,|u|=|nr,θ|. Moreover, for every target value w, uRwnr,θRw.

Proof of Lemma 126.17 — First-order source and normalizer agreement

Proof. The induction is on the displayed first-order formation derivation and is strengthened over all closing substitutions θ. The simultaneous invariant consists of source existence, uniqueness of its data result, the normalizer equation, the erasure equation, and both directions of the representation equivalence.

For a runtime variable x, the value θ(x) is the required result by S-Val. Unit, Booleans, zero, and reflexivity use the corresponding value rule. The successor case applies the induction hypothesis to its predecessor and then S-Con. A pair applies the two induction hypotheses in source evaluation order and concludes with S-Pair. An accepted data constructor does the same for precisely its runtime fields and leaves each erased field at the checked term supplied by θ; S-Con constructs the source value. In each of these cases, NbE evaluates the same components, readback preserves the outer data tag, and erasure drops exactly the fields marked erased. Disjoint data tags and the component uniqueness hypotheses give uniqueness. The definition of R then gives its two directions field by field.

Consider a datatype case. The scrutinee induction hypothesis returns one constructor value c(v;a), with runtime fields v and checked erased fields a. NbE sees the same constructor tag because the simultaneous normalizer equation preserves that tag. Extend θ by the fields according to their relevance marks and apply the induction hypothesis for the selected branch body. Rule S-Case gives the source evaluation. Any second source derivation must select the same constructor by scrutinee uniqueness and disjointness of tags, after which branch-result uniqueness applies. The Boolean cases are the two nullary instances, using S-Bool-T and S-Bool-F.

For a natural eliminator, first apply the structural induction hypothesis to its scrutinee. Perform a subsidiary induction on the resulting canonical natural value. At zero, apply the structural hypothesis for the base body and S-Nat-Z. At sucv, the subsidiary hypothesis supplies the unique result of the recursive eliminator at v; extend θ by v and that result, apply the structural hypothesis for the step body, and conclude with S-Nat-S. NbE recursion follows the identical finite canonical numeral, so the subsidiary induction also proves the normalizer, erasure, and representation clauses. Inversion of a second source derivation exposes the same predecessor, recursive result, and step instance, giving uniqueness in that order.

The vector eliminator uses a separate subsidiary induction on the canonical vector returned by the scrutinee hypothesis. The nil case uses S-Vec-Nil. In the cons case, the structural hypotheses identify the index, head, and tail; the subsidiary hypothesis supplies the recursive result on the tail; and the branch-body hypothesis concludes with S-Vec-Cons. The branch-body derivation is a strict subderivation of the first-order grammar derivation, whereas the recursive call decreases the canonical vector.

For identity elimination, the proof hypothesis returns a reflexivity value. After endpoint conversion, extend θ by its witness, apply the structural hypothesis to the reflexive branch, and use S-J. NbE selects the same reflexive branch. Proof-value inversion and branch uniqueness give the uniqueness clause. These cases exhaust the grammar: it contains no retained lambda, internal application, or named call. Hence the simultaneous structural and subsidiary inductions establish all assertions. ◻

Lemma 126.18 — Generated-map evaluation agreement

Let g be either generated map h:SA or t:SS of definition 124.11, equipped with the runtime-relevance derivation and first-order body required by definition 126.15. Let σ:S be a closed runtime-first-order expression satisfying that card. If g(σ)Tn, then there is a unique source data value v such that g(σ)v,nf(v)=n,|v|=|n|. Moreover, for every target value w, vRw if and only if nRw.

Proof of Lemma 126.18 — Generated-map evaluation agreement

Proof. Apply lemma 126.17 to the closed state expression with the empty substitution. It gives a unique source data value vσ with σvσ,nf(σ)=nf(vσ). By lemma 126.6, σvσ.

Write the generated map as g=λs.b. Its card supplies the formation derivation s:S;fob:B, where B=A for h and B=S for t. Apply the fundamental lemma again with the closing substitution svσ. It gives a unique source data value v such that b[vσ/s]v,nf(v)=nf(b[vσ/s]),|v|=|nf(b[vσ/s])|, and the corresponding representation equivalence.

It remains to identify the displayed normal form with n. Beta equality gives g(σ)b[σ/s]. Substitution congruence applied to σvσ gives b[σ/s]b[vσ/s]. Completeness in lemma 124.3 therefore yields nf(g(σ))=nf(b[vσ/s]). The premise g(σ)Tn is, by definition, the equation n=nf(g(σ)). Hence n=nf(b[vσ/s]), so the equations and representation equivalence supplied for v have exactly the form stated in the lemma. Rule S-App-R, using S-Val for the outer lambda, now derives g(σ)v.

For uniqueness, invert any second source evaluation of g(σ). Its argument premise evaluates σ; the first use of the fundamental lemma identifies that result with vσ. The remaining premise therefore evaluates b[vσ/s], and the second use identifies its result with v. Thus no other source data value can be the result. ◻

Theorem 126.19 — Coiterator erasure simulation

Let A, the generated state datatype S, and the maps h:SA, t:SS satisfy the premises of definition 126.15. Let σ:S be a closed source state term with σ:S and σ runtime, and assume that σ is in the runtime-first-order expression grammar of that card. For every observation word o, if coiter(h,t,σ)ov, then there is a unique target value w such that Obs(|coiter(h,t,σ)|,o,w)andvRw.

Proof of Theorem 126.19 — Coiterator erasure simulation

Proof. Generalize over the closed state term σ and induct on o. In the head case, inversion of the source observation and Coiter-Head from definition 124.11 give a state normal form σ0:S, σTσ0, and h(σ0)Tv. Soundness of the first judgment and substitution invariance in lemma 124.3 give h(σ)Tv. Apply lemma 126.18 to obtain the unique source-CBV value v0 with h(σ)v0, nf(v0)=v, and |v0|=|v|. Typing and runtime relevance of h(σ) permit theorem 126.14; its target derivation is precisely the body forced by call(clos(h,|σ|)), using lemma 126.11 for the stored state. Conclude with Obs-Head; the representation equivalence in lemma 126.18 converts v0Rw to vRw.

For tailo, inversion of the observation rule and Coiter-Tail gives closed source state normal forms σ0,σ:S, subevaluations σTσ0 and t(σ0)Tσ, and the strictly shorter observation derivation coiter(h,t,σ)ov. Normalizer substitution invariance gives t(σ)Tσ. Apply lemma 126.18 to obtain a unique source-CBV state σv with t(σ)σv, nf(σv)=σ, and |σv|=|σ|, and then apply forward simulation to that source evaluation. The target tail wrapper evaluates the displayed beta-redex, installs |σv|=|σ| in both closures, and therefore returns Cstream(clos(h,|σ|),clos(t,|σ|)). The generalized induction hypothesis at σ applies because normal forms in the accepted first-order grammar remain first order, and supplies the remaining observation premise; conclude with Obs-Tail. In both cases, lemma 126.16 gives uniqueness. ◻

Corollary 126.20 — Accepted stream-call erasure

Let c=dia be a closed Timpl-co call accepted by the guardedness checker, and let σc:=ini(a):StateG,c:=coiter(h,t,σc). Assume the element type, state datatype, arguments, and generated maps satisfy definition 126.15; in particular, σc:StateG and σc runtime, and σc is a runtime-first-order expression. Define the co-erasure of the source call by |c|co:=|c|. If cov, then there is a unique w with Obs(|c|co,o,w) and vRw.

Proof of Corollary 126.20 — Accepted stream-call erasure

Proof. By theorem 124.15, the source premise is equivalent to cov. Apply theorem 126.19 at the generated state σc. ◻

This theorem is not an instance of normalization: both source and target streams denote computations with arbitrarily long observation paths. It is also not a new productivity proof; acceptance and theorem 124.10 supply the finite source derivation used by the corollary’s premise.

Typed-target erasure through System Fi.

Definition 126.21 — The System Fi-to-F_ω card

System Fi has type-level contexts Δ::=Δ,XκΔ,iA, term contexts Γ::=Γ,x:A, and Curry-style terms t::=xλx.ttt. Its kinds and type constructors are κ::=κκAκ,F::=XABλXκ.FFGXκ.BλiA.FF{s}iA.B. The index domain A in Aκ is closed and has kind . The source writes this index arrow as Aκ; the card uses only to distinguish it visually from the ordinary kind arrow κκ. An index application F{s} requires Δ;s:A. Index generalization requires iFV(t)FV(Γ). The judgments are well-sorted kinds, well-formed Δ, kinding and constructor equality, well-formed Γ, and typing Δ;Γt:A.

The target is Curry-style Fω with the same term grammar and without index-arrow kinds, index bindings, index abstractions, index applications, or index-polymorphic types. Index erasure is the homomorphism on the shared constructors together with (Aκ)=κ,(λiA.F)=F,(F{s})=F,(iA.B)=B,(Δ,iA)=Δ,(Γ,x:A)=Γ,x:A. Terms are unchanged. The auxiliary context Δ drops type variables and moves every index binding iA to the term binding i:A.

Theorem 126.22 — System Fi index-erasure interface

For the exact card of definition 126.21, index erasure has these seven properties.

  1. κ: implies κ:.

  2. Δ implies Δ.

  3. κ=κ: implies κ=κ:.

  4. Δ and ΔF:κ imply ΔF:κ.

  5. ΔF=G:κ implies ΔF=G:κ.

  6. ΔΓ implies Δ(Δ,Γ).

  7. If ΔΓ and Δ;Γt:A, then Δ;(Δ,Γ)Fωt:A.

If dom(Δ)FV(t)=, item 7 sharpens to Δ;ΓFωt:A.

Proof of Theorem 126.22 — System Fi index-erasure interface

Proof. Prove the seven claims simultaneously. The induction hypotheses are the corresponding erasure claims for every premise derivation; mutual induction is needed because kinding invokes kind sorting, constructor equality invokes kinding, and typing invokes all the preceding judgments.

For kind sorting, is unchanged and ordinary kind arrows use the two induction hypotheses. An index arrow Aκ erases to κ, whose sorting derivation is the induction hypothesis for the codomain. Context formation is then immediate: an ordinary type-variable declaration is rebuilt from the erased sorting premise, while an index declaration disappears. These are items 1 and 2.

For kind equality, reflexivity, symmetry, and transitivity are rebuilt in the target. Congruence for an ordinary arrow uses both induction hypotheses. Congruence for an index arrow has conclusion κ=κ, so its domain-equality premise disappears and the codomain induction hypothesis closes the case. Beta and eta equations for ordinary type abstraction erase to the corresponding Fω equations; the index-beta and index-eta equations erase to reflexivity because both index abstraction and index application disappear. This proves item 3.

For kinding, variables, ordinary arrows, ordinary abstraction and application, and ordinary universal quantification are reconstructed with the target rules and the induction hypotheses. Weakening across an erased index declaration is admissible because that declaration contributes no free target variable. In the three index-specific cases one calculates (λiA.F)=F,(F{s})=F,(iA.B)=B. The induction hypothesis for F or B therefore already has the required target conclusion; the closed index term s has no target occurrence. Conversion uses item 3. This proves item 4.

The constructor-equality induction follows the same rule partition. The ordinary congruence, beta, eta, symmetry, transitivity, and conversion cases are rebuilt in Fω. Index congruence retains only the induction hypothesis for the constructor. Index beta uses (F[s/i])=F, proved by structural induction on F: the variable and ordinary-binder cases commute with substitution, and every occurrence of i lies in an index position deleted by erasure. Ordinary type beta uses the companion structural equation (F[G/X])=F[G/X]. Both equations are stable under binders after alpha-renaming the binder away from the substituted variable. These calculations prove item 5.

For item 6, induct on term-context formation. The empty context is unchanged. An ordinary term declaration x:A is rebuilt using item 4. Extending Δ by iA deletes that type-level declaration but adds i:A to Δ; item 4 gives the required formation of A. Extending Δ by Xκ keeps the erased type-level declaration and adds nothing to Δ.

Finally, induct on typing. A term variable is found either in Γ or in the moved index context (Δ). Term abstraction and application are homomorphic and use the induction hypotheses. Ordinary type generalization and instantiation use items 1–5. Index generalization erases its quantifier; its freshness premise iFV(t)FV(Γ) permits strengthening away the moved term declaration. Index instantiation leaves the Curry term unchanged and replaces its type using (B[s/i])=B. The conversion case uses item 5. These cases exhaust the typing rules and prove item 7.

If dom(Δ)FV(t)=, repeated strengthening removes every declaration contributed by Δ, which gives the sharpened conclusion. ◻

Corollary 126.23 — Normalization and consistency of System Fi

Every well-typed System Fi term is strongly normalizing for its displayed beta reduction. There is no closed System Fi term of type X.X.

Proof of Corollary 126.23 — Normalization and consistency of System Fi

Proof. By item 7 of theorem 126.22, the unchanged Curry term is well typed in Fω at its erased type. Source and target have the same term reduction, so an infinite System Fi reduction would be an infinite well-typed Fω reduction, contradicting theorem 60.23. The void type erases to itself. If a closed Fi term had type X.X, normalization and subject reduction in the Fω vertex would give a closed beta-normal term of that type. Its head must be a type abstraction ΛX.u, with X:;u:X. A beta-normal term of atomic type is neutral, and a neutral term has a free term-variable head. The empty term context has no such head, a contradiction. ◻

The source Church encoding is Vec:=λA.λiN.XN.(jN.AX{j}X{sucj})X{0}X{i}. Applying the four erasure clauses gives Vec=λA.X.(AXX)XX:=List.

Exercise 126.6

★☆☆ Erase the System Fi type iN.VecA{i}N, using the Church encoding displayed above. State which binder and applications disappear.

The source discusses safeTail later under a different encoding: the equality-constraint encoding of its Section 6, not the preceding Church encoding. Write Leibniz index equality as i=Nj:=XN.X{i}X{j}, and put Vec=:=λA.λiN.XN.(jN.(sucj=Ni)×A×X{j})+(0=Ni). Fix an index n:N. The index theory used by the example supplies the two no-confusion consequences sucInjj,n:(sucj=Nsucn)(j=Nn),zeroNeSucn,B:(0=Nsucn)B. With the usual impredicative sum, product, and existential eliminators, the source witness is the following Curry term; the displayed type/index instantiations are typing annotations, not term constructors: sn(j,e,a,xs):=trk.Vec=A{k}(sucInjj,n(e),xs),zn(e0):=zeroNeSucn,Vec=A{n}(e0),safeTailn:=λv.case+(v[Vec=A/X];p.unpack(p;sn),zn). Here unpack(p;sn) eliminates the existential package into its four components (j,e,a,xs) and applies sn to them. Here the first branch transports the stored tail xs:Vec=A{j} along j=Nn; the second branch uses the impossible equality 0=Nsucn. Thus every branch has exactly the claimed result type.

Let P:=Y.YY, the erasure of index equality, and let Ex(B):=Z.(BZ)Z, the erasure of an index existential. Direct application of the four erasure clauses gives (Vec=A{i})=X.Ex(P×A×X)+P:=List=(A), independently of i. Erasing the witness removes the type instantiation and every index component: [Vec=A/X],j,all index arguments. It retains term-level equality evidence: sn(e,a,xs):=sucInj(e)xs,zn(e0):=zeroNeSuc(e0),(safeTailn):=λv.case+(v;p.unpack(p;sn),zn). In the target unpacking, the erased index j is absent and the remaining package components are (e,a,xs). Its target type is List=(A)List=(A). The calculation therefore does not conflate the paper’s Church and equality-constraint encodings, and it does not claim that term-level evidence vanishes under index erasure.

The System Fi theorem is typed-target preservation. It supplies neither the constructor/closure invariant of Texec nor an operational simulation for Timpl. Conversely, theorem 126.14 proves no Fω kinding or strong-normalization result.

Sources. The System Fi syntax, erasure equations, and seven theorem signatures are from Ahn, Sheard, Fiore, and Pitts, Section 5.2, Definitions 1–2 and Theorems 1–7 [ASFP13]; their short proof span on physical pp. 10–12 is incorporated in theorem 126.22. The separation between an untyped erasure relation and its execution theorem follows the verified architecture of the PCUIC erasure development, especially its target calculus, structural lemmas, and erasure-correctness theorem . Those results concern PCUIC; all Timpl and Texec cases were proved locally above.

Suggested first pass.

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

Exercise 126.7

★★☆ State the representation relation for the two source values vnil and vcons(n,a,xs). Prove the constructor case of theorem 126.14, including the runtime substitution for the recursive branch.

Exercise 126.8

★★☆ Give two closed substitutions for the erased Boolean counterexample that produce different source numerals. Calculate their identical erasures and show that no deterministic target can forward-simulate both results.

Exercise 126.9

★★★ Practical project.dependent-definition-erasure-runner Build a Kappa runner for the finite executable slice of definition 126.3, definition 126.10 containing variables, annotated lambdas and applications, pairs and projections, reflexivity, Boolean and identity elimination, user constructors and cases, and ordinary compiled closures and saturated calls. The runner has three parts: an environment-directed relevance check followed by erasure for that slice; a Texec evaluator implementing E-Val, E-App, E-Con, E-Clos, E-Case and E-Call with real substitution and closure environments; and the observer of definition 126.15. Preserve target arities through one global constructor-signature table, require pairwise distinct case tags, preserve closure sizes, and make fuel a checked budget so that exhaustion is reported and is distinct from a stuck configuration. Execute append rather than simulating it: require append-two-singletons=vcons(a,vcons(b,vnil)), print its runtime arity, and require from-0=0,1,2,3 from the two stream closures. Reject erased-boolean-branch, naming the erased scrutinee, and print the erasure of the visible administrative redex λexplicit,erased(x:A).fexplicit,erasedi, which is f. Also reject an erased application whose head is a variable, naming it non-administrative erased application. Also check a retained-but-unused case field, rejection of an erased branch variable used at runtime, and capture avoidance for open identity-branch substitution. Replay mutations that retain erased declaration binders, allow an erased scrutinee, derive target branch arity from branch use, bypass branch admissibility, omit freshening, ignore the binder environment, bypass the constructor-signature comparison, and accept duplicate branch tags. Primitive natural and vector eliminator occurrence-tag generation is outside this finite runner; the ordinary append record exercises the same target closure/call evaluator but is not an implementation of those two primitive compilers. This execution illustrates both simulations for the listed slice and proves neither.

Search the book

Type to search the local edition.