Partiality and General Recursion in Dependent Type Theory
Prerequisites. Direct starred prerequisites: none. No later core chapter depends on this route.
Suppose every type admitted 𝖿𝗂𝗑𝐴:(𝐴→𝐴)→𝐴,𝖿𝗂𝗑𝐴(𝑓)≡𝑓(𝖿𝗂𝗑𝐴(𝑓)). At 𝐴=⊥, choose 𝑓=𝜆𝑥.𝑥. Then 𝖿𝗂𝗑⊥(𝑓):⊥. An unrestricted proof-level fixpoint makes the empty type inhabited before any program is run. General recursion must therefore return a computation that may fail to produce an 𝐴, rather than an inhabitant of 𝐴 itself.
Partial elements record time without promising a result
For each type 𝐴, define the coinductive type 𝐴𝜈 by 𝗋𝖾𝗍𝗎𝗋𝗇:𝐴→𝐴𝜈,𝗌𝗍𝖾𝗉:𝐴𝜈→𝐴𝜈. Write ⟨𝑎⟩ for 𝗋𝖾𝗍𝗎𝗋𝗇𝑎 and ▹𝑥 for 𝗌𝗍𝖾𝗉𝑥. Guarded corecursion defines the divergent computation 𝗇𝖾𝗏𝖾𝗋:=▹𝗇𝖾𝗏𝖾𝗋:𝐴𝜈. The inductive convergence judgment 𝑥⇓𝑎 has rules
⟨𝑎⟩⇓𝑎
Conv-Return
𝑥⇓𝑎
▹𝑥⇓𝑎
Conv-Step
A partial element diverges, written 𝑥⇑, when ∀𝑎:𝐴.¬(𝑥⇓𝑎). A finite observation 𝗈𝖻𝗌𝖾𝗋𝗏𝖾𝑘(𝑥) removes at most 𝑘 leading steps and returns either 𝗅𝖺𝗍𝖾𝗋 or 𝖽𝗈𝗇𝖾(𝑎). It never asserts divergence from a finite prefix.
The type 𝐴𝜈 is not 𝐴+𝟏. Case analysis on 𝐴+𝟏 decides whether a value is present. Constructively, an arbitrary partial element need not satisfy (∃𝑎.𝑥⇓𝑎)∨𝑥⇑. Every finite observation of 𝗇𝖾𝗏𝖾𝗋 returns 𝗅𝖺𝗍𝖾𝗋, but no finite observation proves that all later observations do so.
Two partial elements are equal, written 𝑥=𝜈𝑦, when they have the same convergence behavior: 𝑥=𝜈𝑦:=∀𝑎:𝐴.𝑥⇓𝑎↔𝑦⇓𝑎. This relation identifies 𝑥, ▹𝑥, and every finite delay of 𝑥. It is weaker than syntactic equality and strong bisimilarity.
Proof. First prove determinacy of convergence: if 𝑥⇓𝑎 and 𝑥⇓𝑏, induction on the first derivation and inversion of the second give 𝑎=𝑏. The return case inverts both derivations; the step case removes one Conv-Step from each and applies the induction hypothesis.
For the first formula, inversion of Conv-Step gives ▹𝑥⇓𝑎⇒𝑥⇓𝑎, and Conv-Step gives the converse. For the second, inversion of Conv-Return shows that ⟨𝑎⟩⇓𝑏 exactly when 𝑎=𝑏. If 𝑥⇓𝑎, determinacy gives 𝑥⇓𝑏⟺𝑎=𝑏; substitute both facts in definition 105.2. The reverse implication specializes equality at 𝑎 and uses Conv-Return. The third formula applies the first inversion in both directions. Reflexivity, symmetry, and transitivity hold pointwise because logical equivalence has those three properties. ◻
★☆☆ Compute 𝗈𝖻𝗌𝖾𝗋𝗏𝖾𝑘 for ▹3⟨7⟩ at 𝑘=0,2,3,4. Give the Conv-Step/Conv-Return derivation witnessing convergence and state why none of the first three observations is a proof of divergence.
The input step is retained. A tempting definition 𝑓∗(▹𝑥)=𝑓∗(𝑥) is unguarded: computing its first constructor may require inspecting infinitely many input steps. Guarding the recursive call is forced by productivity.
Proof. For the forward implication, induct on the convergence derivation. If 𝑥=⟨𝑎⟩, choose 𝑎; Conv-Return proves the first conjunct and the premise proves the second. If 𝑥=▹𝑥′, inversion of the bind equation changes the final Conv-Step premise to (𝑥′≫=𝑓)⇓𝑏. The induction hypothesis supplies 𝑎, and Conv-Step gives 𝑥⇓𝑎.
For the reverse implication, induct on the derivation of 𝑥⇓𝑎. The return case reduces bind to 𝑓(𝑎). In the step case, the induction hypothesis gives (𝑥′≫=𝑓)⇓𝑏; one use of Conv-Step and the second bind equation gives (▹𝑥′≫=𝑓)⇓𝑏. ◻
A setoid𝐴=(|𝐴|,Eq𝐴) consists of a type |𝐴| and an equivalence relation Eq𝐴 on it. A map ℎ:𝐴→𝐵 is a function |ℎ|:|𝐴|→|𝐵| satisfying Eq𝐴(𝑎,𝑎′)⟹Eq𝐵(|ℎ|(𝑎),|ℎ|(𝑎′)). Two such maps are equal when their values are Eq𝐵-related at every argument.
Lift 𝐴 to a setoid 𝑇𝐴 as follows. For 𝑥:|𝐴|𝜈 and 𝑎:|𝐴|, put Conv𝐴(𝑥,𝑎):=∃𝑎′:|𝐴|.𝑥⇓𝑎′∧Eq𝐴(𝑎′,𝑎),Eq𝑇𝐴(𝑥,𝑦):=∀𝑎:|𝐴|.Conv𝐴(𝑥,𝑎)↔Conv𝐴(𝑦,𝑎). For the discrete setoid, whose relation is ordinary equality, Eq𝑇𝐴(𝑥,𝑦) is exactly 𝑥=𝜈𝑦.
Define 𝜂𝐴:𝐴→𝑇𝐴 by 𝜂𝐴(𝑎)=⟨𝑎⟩. A Kleisli arrow𝑓:𝐴→𝑇𝐵 is a function |𝐴|→|𝐵|𝜈 satisfying Eq𝐴(𝑎,𝑎′)⟹Eq𝑇𝐵(𝑓(𝑎),𝑓(𝑎′)). Its extension is the guarded function of definition 105.4: 𝑓∗(𝑥):=𝑥≫=𝑓.
Proof of Lemma 105.7 — Extensional return and bind
Proof. Reflexivity, symmetry, and transitivity of Eq𝑇𝐴 hold pointwise because logical equivalence has those properties. Moreover, Conv𝐴(⟨𝑎⟩,𝑐)⟺Eq𝐴(𝑎,𝑐).(𝑅) If Eq𝐴(𝑎,𝑎′), transitivity and symmetry of Eq𝐴 make the right side of (R) equivalent with Eq𝐴(𝑎′,𝑐). Thus 𝜂𝐴 preserves the setoid relations, proving clause 1.
For the forward implication of (K), choose 𝑏0:|𝐵| with 𝑓∗(𝑥)⇓𝑏0,Eq𝐵(𝑏0,𝑏). By lemma 105.5, choose 𝑎0:|𝐴| such that 𝑥⇓𝑎0 and 𝑓(𝑎0)⇓𝑏0. Reflexivity gives Conv𝐴(𝑥,𝑎0), while the second displayed relation gives Conv𝐵(𝑓(𝑎0),𝑏).
Conversely, choose 𝑎:|𝐴| from the right side of (K), then choose 𝑎0:|𝐴| such that 𝑥⇓𝑎0,Eq𝐴(𝑎0,𝑎). Because 𝑓 is a Kleisli arrow, Eq𝑇𝐵(𝑓(𝑎0),𝑓(𝑎)). Hence Conv𝐵(𝑓(𝑎),𝑏) gives Conv𝐵(𝑓(𝑎0),𝑏). Choose 𝑏0:|𝐵| with 𝑓(𝑎0)⇓𝑏0 and Eq𝐵(𝑏0,𝑏). Bind convergence gives 𝑓∗(𝑥)⇓𝑏0, which proves the left side of (K).
If Eq𝑇𝐴(𝑥,𝑦), formula (K) has equivalent right sides for 𝑥 and 𝑦. Thus 𝑓∗ preserves the lifted relation. If also 𝑓(𝑎) and 𝑔(𝑎) are related for every 𝑎, replace both the first conjunct by the equivalence between 𝑥 and 𝑦 and the second by the equivalence between 𝑓(𝑎) and 𝑔(𝑎) in (K). The resulting equivalence for every 𝑏:|𝐵| is clause 3. ◻
On the category of setoids, the object assignment 𝐴↦𝑇𝐴, the setoid maps 𝜂𝐴:𝐴→𝑇𝐴, and extension of Kleisli arrows 𝑓↦𝑓∗ form a Kleisli triple. Thus the following are equalities of setoid maps: 𝜂∗𝐴=𝗂𝖽𝑇𝐴,𝑓∗∘𝜂𝐴=𝑓,𝑔∗∘𝑓∗=(𝜆𝑎.𝑔∗(𝑓(𝑎)))∗. No choice principle is assumed.
Proof of Theorem 105.8 — Partiality Kleisli triple
Proof. All displayed maps are setoid maps by lemma 105.7. For the first law, formula (K) and (R) give, for every 𝑎:|𝐴|, Conv𝐴(𝜂∗𝐴(𝑥),𝑎)(𝐾)⟺∃𝑏:|𝐴|.Conv𝐴(𝑥,𝑏)∧Eq𝐴(𝑏,𝑎)𝑒𝑞𝑢𝑖𝑣𝑎𝑙𝑒𝑛𝑐𝑒⟺Conv𝐴(𝑥,𝑎). The reverse direction of the second step chooses 𝑏=𝑎; the forward direction uses the witness for Conv𝐴(𝑥,𝑏) and transitivity of Eq𝐴. Hence 𝜂∗𝐴 and 𝗂𝖽𝑇𝐴 are pointwise related.
The return equation in definition 105.4 gives 𝑓∗(𝜂𝐴(𝑎))=𝑓(𝑎), so reflexivity of Eq𝑇𝐵 proves the second law. For the third, fix 𝑥:|𝐴|𝜈 and 𝑐:|𝐶|. Repeated use of (K) gives the annotated calculation Conv𝐶(𝑔∗(𝑓∗(𝑥)),𝑐)(𝐾)⟺∃𝑏.Conv𝐵(𝑓∗(𝑥),𝑏)∧Conv𝐶(𝑔(𝑏),𝑐)(𝐾)⟺∃𝑎,𝑏.Conv𝐴(𝑥,𝑎)∧Conv𝐵(𝑓(𝑎),𝑏)∧Conv𝐶(𝑔(𝑏),𝑐)(𝐾)⟺∃𝑎.Conv𝐴(𝑥,𝑎)∧Conv𝐶(𝑔∗(𝑓(𝑎)),𝑐)(𝐾)⟺Conv𝐶((𝜆𝑎.𝑔∗(𝑓(𝑎)))∗(𝑥),𝑐). This is pointwise Eq𝑇𝐶, as required. ◻
The construction acts on setoids, not only on their carrier types. The extensionality lemma and the three calculations above supply the setoid action and all three Kleisli laws. Equality of maps is pointwise setoid equality, so the proof uses neither functional extensionality nor quotient choice.
★★☆ Attempt to prove associativity by syntactic equality. Give an input with one leading step for which the two unfoldings expose different guarded syntax before quotienting. Then complete the convergence calculation proving =𝜈.
Fix a decidable predicate 𝑃:𝖭𝖺𝗍→𝖡𝗈𝗈𝗅. Unbounded search from 𝑛 is defined guardedly by 𝗌𝖾𝖺𝗋𝖼𝗁𝑃(𝑛):={⟨𝑛⟩,𝑃(𝑛)=𝗍𝗋𝗎𝖾,▹𝗌𝖾𝖺𝗋𝖼𝗁𝑃(𝑛+1),𝑃(𝑛)=𝖿𝖺𝗅𝗌𝖾. Each recursive call lies below ▹, so it defines a partial element even when no witness exists.
Proof. For the forward implication, induct on the convergence derivation while unfolding the defining equation at the starting index. If 𝑃(𝑛) is true, the computation is ⟨𝑛⟩; inversion gives 𝑚=𝑛, and the bounded universal has no instance. If 𝑃(𝑛) is false, inversion of Conv-Step gives 𝗌𝖾𝖺𝗋𝖼𝗁𝑃(𝑛+1)⇓𝑚. The induction hypothesis gives 𝑛+1≤𝑚, 𝑃(𝑚)=𝗍𝗋𝗎𝖾, and falsity on [𝑛+1,𝑚); add 𝑃(𝑛)=𝖿𝖺𝗅𝗌𝖾.
For the reverse implication, induct on 𝑚−𝑛. At zero, 𝑚=𝑛 and 𝑃(𝑛)=𝗍𝗋𝗎𝖾, so Conv-Return applies. At a successor difference, the bounded premise gives 𝑃(𝑛)=𝖿𝖺𝗅𝗌𝖾. The induction hypothesis yields convergence from 𝑛+1, and Conv-Step yields convergence from 𝑛. ◻
This theorem is partial correctness plus an exact convergence criterion. A total-correctness theorem additionally needs ∃𝑚≥𝑛.𝑃(𝑚)=𝗍𝗋𝗎𝖾. Without that premise, 𝑃(𝑘)=𝖿𝖺𝗅𝗌𝖾 for all 𝑘 makes every finite observation return 𝗅𝖺𝗍𝖾𝗋.
The construction scales to partial recursive functions. A partial-recursive presentation of arity 𝑘 is generated by zero, successor, projections, composition, primitive recursion, and minimization. Recursion on such a presentation 𝑓:𝖭𝖺𝗍𝑘⇀𝖭𝖺𝗍 defines a term 𝑓𝜈:𝖭𝖺𝗍𝑘→𝖭𝖺𝗍𝜈: total base functions are followed by 𝜂, composition uses the strict tuple followed by Kleisli extension, primitive recursion first recurses on the returned natural number and then extends over its partial argument, and minimization tests successive values by a guarded search.
Proof of Theorem 105.10 — Representability of partial-recursive presentations
Proof. Induct on the partial-recursive presentation. The induction hypothesis for each immediate subpresentation is the displayed equivalence at every input and output.
For zero and successor, 𝑓𝜈(⃗𝑛) is respectively 𝜂(0) and 𝜂(𝑛+1). Inversion of Conv-Return proves both directions. For the 𝑖-th projection, the strict tuple forces all inputs; each input is already a returned natural number, so its only convergence is to 𝑛𝑖.
Suppose 𝑓=ℎ∘⟨𝑔1,…,𝑔𝑗⟩. Repeated use of the Kleisli convergence law (K) gives 𝑓𝜈(⃗𝑛)⇓𝑚⟺∃𝑎1,…,𝑎𝑗.𝑗⋀𝑖=1𝑔𝜈𝑖(⃗𝑛)⇓𝑎𝑖∧ℎ𝜈(⃗𝑎)⇓𝑚. Apply the induction hypotheses for the 𝑔𝑖 and ℎ. The result is exactly the relational clause for composition.
For primitive recursion, write 𝑓(⃗𝑛,0)=𝑔(⃗𝑛),𝑓(⃗𝑛,𝑟+1)=ℎ(⃗𝑛,𝑟,𝑓(⃗𝑛,𝑟)). The translation defines an auxiliary 𝑓′𝜈 by recursion on the returned counter and defines 𝑓𝜈 by Kleisli-extending 𝑓′𝜈 over that counter. A subsidiary induction on 𝑟 proves 𝑓′𝜈(⃗𝑛,𝑟)⇓𝑚⟺𝑓(⃗𝑛,𝑟)=𝑚. The zero case is the induction hypothesis for 𝑔. The successor case uses (K) once; its witness 𝑎 is characterized by the subsidiary induction hypothesis, and the remaining convergence is characterized by the induction hypothesis for ℎ. A final use of (K) accounts for a partial counter and yields the required equivalence.
For minimization, suppose 𝑓(⃗𝑛)=𝜇𝑟.𝑔(⃗𝑛,𝑟)=0. Define the guarded search 𝗅𝖾𝖺𝗌𝗍𝜈𝑔(⃗𝑛,𝑟) by first evaluating 𝑔𝜈(⃗𝑛,𝑟); a returned zero yields 𝜂(𝑟), and a returned successor takes one ▹-step before searching from 𝑟+1. The search lemma 𝗅𝖾𝖺𝗌𝗍𝜈𝑔(⃗𝑛,𝑟)⇓𝑚⟺𝑟≤𝑚∧𝑔(⃗𝑛,𝑚)=0∧∀𝑞.𝑟≤𝑞<𝑚⇒∃𝑠.𝑔(⃗𝑛,𝑞)=𝑠+1 is proved by the two inductions used for theorem 105.9: forward, invert the finite convergence derivation; backward, induct on 𝑚−𝑟. At every test, the induction hypothesis for 𝑔 converts evaluation of 𝑔𝜈 into the graph equation for 𝑔. Taking 𝑟=0 gives the defining least-witness clause for minimization. These six constructor cases exhaust the presentation grammar and complete the outer induction. ◻
The theorem supplies representability of every partial recursive function, not a decision procedure for convergence.
★★☆ Take 𝑃(𝑘) to test whether 𝑘2=2 over natural numbers. Prove that no value satisfies the right side of theorem 105.9. Show that every finite observation returns 𝗅𝖺𝗍𝖾𝗋, without assuming a general law deciding convergence or divergence.
For functions 𝑓,𝑔:𝐴→𝐵𝜈, write 𝑓⊑𝑔 when every convergence of 𝑓(𝑎) is a convergence of 𝑔(𝑎). An operator 𝐹:(𝐴→𝐵𝜈)→(𝐴→𝐵𝜈) is finitary when, for every 𝑓:𝐴→𝐵𝜈, 𝑎:𝐴, and 𝑏:𝐵, a derivation 𝐹(𝑓)(𝑎)⇓𝑏 supplies a finite list (𝑎1,𝑏1),…,(𝑎𝑛,𝑏𝑛) such that 𝑓(𝑎𝑖)⇓𝑏𝑖 for every 𝑖, and every 𝑔:𝐴→𝐵𝜈 satisfying all 𝑔(𝑎𝑖)⇓𝑏𝑖 also satisfies 𝐹(𝑔)(𝑎)⇓𝑏.
The fixed point is built by racing the approximants against one another, and the race has to be written down: it is the only construction in the chapter that a reader could not guess, and the choice-freedom claim below depends on its exact shape.
Define 𝑥⋏𝑦, the first of 𝑥 and 𝑦 to converge, by guarded corecursion on both arguments: ⟨𝑏⟩⋏𝑦:=⟨𝑏⟩,(▹𝑥)⋏⟨𝑏⟩:=⟨𝑏⟩,(▹𝑥)⋏(▹𝑦):=▹(𝑥⋏𝑦). For a sequence ℎ:𝖭𝖺𝗍→𝐵𝜈, define an auxiliary 𝗋𝖺𝖼𝖾:(𝖭𝖺𝗍→𝐵𝜈)→𝖭𝖺𝗍→𝐵𝜈→𝐵𝜈 by 𝗋𝖺𝖼𝖾ℎ𝑛⟨𝑏⟩:=⟨𝑏⟩,𝗋𝖺𝖼𝖾ℎ𝑛(▹𝑥):=▹(𝗋𝖺𝖼𝖾ℎ(𝑛+1)(𝑥⋏ℎ(𝑛))), and put 𝗋𝖺𝖼𝖾∞(ℎ):=𝗋𝖺𝖼𝖾ℎ0𝗇𝖾𝗏𝖾𝗋.
Each recursive call sits under a ▹, so both definitions are productive. At step 𝑛 the accumulated element has been raced against ℎ(0),…,ℎ(𝑛−1), so every member of the sequence is eventually entered; that is the exact sense of “fair”. Two consequences of the definition are used below: 𝗋𝖺𝖼𝖾∞(ℎ)⇓𝑏 implies ℎ(𝑛)⇓𝑏 for some 𝑛, because a convergence derivation is finite and its length bounds the index reached; and if ℎ is increasing for ⊑, the converse holds.
Proof of Theorem 105.12 — Finitary least fixed point
Proof. Let 𝑘0(𝑎)=𝗇𝖾𝗏𝖾𝗋 and 𝑘𝑛+1=𝐹(𝑘𝑛), and define 𝑌(𝐹)(𝑎):=𝗋𝖺𝖼𝖾∞(𝜆𝑛.𝑘𝑛(𝑎)). First, 𝐹 is monotone: if 𝑓⊑𝑔 and 𝐹(𝑓)(𝑎)⇓𝑏, finitarity supplies pairs (𝑎𝑖,𝑏𝑖) with 𝑓(𝑎𝑖)⇓𝑏𝑖; each is then a convergence of 𝑔(𝑎𝑖), so its closure clause gives 𝐹(𝑔)(𝑎)⇓𝑏. Since 𝑘0⊑𝑘1 holds because 𝗇𝖾𝗏𝖾𝗋 converges to nothing, induction gives 𝑘𝑛⊑𝑘𝑛+1, so the sequence is increasing and definition 105.11 gives 𝑌(𝐹)(𝑎)⇓𝑏⟺∃𝑛.𝑘𝑛(𝑎)⇓𝑏.
If 𝐹(𝑌(𝐹))(𝑎)⇓𝑏, finitarity selects finitely many convergences of 𝑌(𝐹). Each appears at some approximant; their maximum index 𝑁 places them all in 𝑘𝑁. Therefore 𝑘𝑁+1(𝑎)=𝐹(𝑘𝑁)(𝑎)⇓𝑏, so 𝑌(𝐹)(𝑎)⇓𝑏. Conversely, induction on 𝑛 shows 𝑘𝑛⊑𝐹(𝑌(𝐹)), using monotonicity and 𝑘𝑛⊑𝑌(𝐹). Thus 𝐹(𝑌(𝐹))=𝜈𝑌(𝐹).
If 𝐹(𝑓)⊑𝑓, induction gives 𝑘𝑛⊑𝑓 for every 𝑛; the displayed convergence characterization yields 𝑌(𝐹)⊑𝑓. Finitarity supplies the finite maximum index, while monotonicity moves the approximation chain through 𝐹.
No countable choice is used, and the reason is now visible. Choice would be needed to turn the family of statements “𝑘𝑛(𝑎) converges for some 𝑛” into a function selecting such an 𝑛. Nothing here does that: 𝗋𝖺𝖼𝖾∞ is a guarded corecursive program that takes the whole sequence as one argument, and the index is not chosen but read off the length of a finite convergence derivation. ◻
Dropping finitarity invalidates the maximum-index step: an output could depend on infinitely many approximants at once. Extensional equality is also substantive; the parallel search need not have the same constructor timing as 𝐹(𝑌(𝐹)).
Two programs, five techniques
Two programs are enough to separate the techniques, provided both are written out. Let 𝗀𝖼𝖽𝗌𝗎𝖻(𝑚,𝑛):=⎧{
{
{
{⎨{
{
{
{⎩𝑚,𝑛=0,𝑛,𝑚=0,𝗀𝖼𝖽𝗌𝗎𝖻(𝑚−𝑛,𝑛),0<𝑛≤𝑚,𝗀𝖼𝖽𝗌𝗎𝖻(𝑚,𝑛−𝑚),0<𝑚<𝑛. It is total, but neither recursive call is on an immediate constructor subterm of either argument, so a structural checker rejects it. 𝗌𝖾𝖺𝗋𝖼𝗁𝑃 of section 105.3 is genuinely partial. Take each program through the two definitional techniques in turn, and write down what is actually accepted.
Accessibility, for the total program.
Well-foundedness is expressed positively by the accessibility predicate 𝖠𝖼𝖼:∀(𝐴:𝖲𝖾𝗍)(≺:𝐴→𝐴→𝖯𝗋𝗈𝗉).𝐴→𝖯𝗋𝗈𝗉,𝖺𝖼𝖼:∀(𝐴:𝖲𝖾𝗍)(≺)(𝑎:𝐴).(∀(𝑥:𝐴).𝑥≺𝑎→𝖠𝖼𝖼𝐴(≺)𝑥)→𝖠𝖼𝖼𝐴(≺)𝑎, with 𝗐𝖿𝐴(≺):=∀𝑎:𝐴.𝖠𝖼𝖼𝐴(≺)𝑎. Its eliminator is the principle of well-founded recursion 𝗐𝖿𝗋:∀(𝑃:𝐴→𝜏)(𝑎:𝐴).𝖠𝖼𝖼𝐴(≺)𝑎→(∀𝑥.𝖠𝖼𝖼𝐴(≺)𝑥→(∀𝑦.𝑦≺𝑥→𝑃𝑦)→𝑃𝑥)→𝑃𝑎, computing by 𝗐𝖿𝗋𝑃𝑎(𝖺𝖼𝖼𝑎ℎ)𝑒=𝑒𝑎(𝖺𝖼𝖼𝑎ℎ)(𝜆𝑦.𝜆𝑞.𝗐𝖿𝗋𝑃𝑦(ℎ𝑦𝑞)𝑒). To accept 𝗀𝖼𝖽𝗌𝗎𝖻, instantiate 𝐴:=𝖭𝖺𝗍×𝖭𝖺𝗍, take (𝑚′,𝑛′)≺(𝑚,𝑛):=𝑚′+𝑛′<𝑚+𝑛, and supply two things: a proof 𝖺𝗅𝗅𝖺𝖼𝖼:𝗐𝖿(𝖭𝖺𝗍×𝖭𝖺𝗍)(≺), which follows from well-foundedness of < on 𝖭𝖺𝗍 by transporting along 𝑚+𝑛; and one obligation per recursive call, 0<𝑛≤𝑚⇒(𝑚−𝑛)+𝑛<𝑚+𝑛,0<𝑚<𝑛⇒𝑚+(𝑛−𝑚)<𝑚+𝑛, both of which reduce to 0<𝑛 and 0<𝑚 respectively. The result is a total function 𝖭𝖺𝗍→𝖭𝖺𝗍→𝖭𝖺𝗍, and it is a genuine value: 𝗀𝖼𝖽𝗌𝗎𝖻(6,4) evaluates to 2 with no residual proof obligation.
The same definition is accepted in the measure form 𝖯𝗋𝗈𝗀𝗋𝖺𝗆𝖥𝗂𝗑𝗉𝗈𝗂𝗇𝗍𝗀𝖼𝖽(𝑚,𝑛:𝖭𝖺𝗍){𝗆𝖾𝖺𝗌𝗎𝗋𝖾(𝑚+𝑛)}, which generates the same two obligations and discharges the accessibility proof internally. The boundary is worth recording: the measure form supplies the definition and nothing else. It provides no induction principle for reasoning about the function afterwards, because the elaborated term is not the one the user wrote; the explicit 𝗐𝖿𝗋 form keeps 𝖠𝖼𝖼 visible and so supports well-founded induction over the same relation.
Accessibility, for the partial program.
The same route fails, and it fails for a stated reason rather than by awkwardness. A well-founded relation for 𝗌𝖾𝖺𝗋𝖼𝗁𝑃 would have to make 𝑛+1≺𝑛 whenever 𝑃(𝑛)=𝖿𝖺𝗅𝗌𝖾. If 𝑃 is false everywhere, that relation has the infinite descending chain 0≻1≻2≻⋯, so no inhabitant of 𝖠𝖼𝖼𝖭𝖺𝗍(≺)0 exists and the first argument of 𝗐𝖿𝗋 cannot be supplied. Restricting the domain to inputs below a witness repairs this, but only by assuming ∃𝑚≥𝑛.𝑃(𝑚)=𝗍𝗋𝗎𝖾—the very statement the search was meant to decide.
Delay, for both programs.
The delay type accepts both without an obligation, because definition 105.1 makes every recursive call guarded. Define 𝗀𝖼𝖽𝜈(𝑚,𝑛):=⎧{
{
{
{⎨{
{
{
{⎩⟨𝑚⟩,𝑛=0,⟨𝑛⟩,𝑚=0,▹𝗀𝖼𝖽𝜈(𝑚−𝑛,𝑛),0<𝑛≤𝑚,▹𝗀𝖼𝖽𝜈(𝑚,𝑛−𝑚),0<𝑚<𝑛, of type 𝖭𝖺𝗍→𝖭𝖺𝗍→𝖭𝖺𝗍𝜈. Both definitions are accepted, and the difference is in what one can then observe. For the total program the observations converge and the measure argument above turns into a convergence proof: 𝗈𝖻𝗌𝖾𝗋𝗏𝖾2(𝗀𝖼𝖽𝜈(6,4))=𝗅𝖺𝗍𝖾𝗋,𝗈𝖻𝗌𝖾𝗋𝗏𝖾3(𝗀𝖼𝖽𝜈(6,4))=𝖽𝗈𝗇𝖾(2), since the arguments pass through (6,4), (2,4), (2,2), and (0,2), whose sums 10>6>4>2 witness the measure, so 𝗀𝖼𝖽𝜈(6,4)=▹3⟨2⟩. For 𝑃(𝑘) testing 𝑘2=2, by contrast, 𝗈𝖻𝗌𝖾𝗋𝗏𝖾𝑘(𝗌𝖾𝖺𝗋𝖼𝗁𝑃(0))=𝗅𝖺𝗍𝖾𝗋forevery𝑘, and exercise 105.3 shows that no finite 𝑘 improves on this. The delay type therefore accepts the partial program at the price that its result is a partial element: extracting 𝖭𝖺𝗍 from 𝖭𝖺𝗍𝜈 needs a convergence proof, which for 𝗀𝖼𝖽𝜈 is available and for 𝗌𝖾𝖺𝗋𝖼𝗁𝑃 is exactly what does not exist.
Inductive domains, for both programs.
The third technique changes the domain instead of the codomain. Read the recursive equations of a function as the clauses of an inductive predicate that holds exactly where the call tree is finite. For 𝗀𝖼𝖽𝗌𝗎𝖻 this is 𝖣𝗈𝗆:𝖭𝖺𝗍→𝖭𝖺𝗍→𝖯𝗋𝗈𝗉,𝖽0:∀𝑚.𝖣𝗈𝗆𝑚0,𝖽1:∀𝑛.𝖣𝗈𝗆0𝑛,𝖽2:∀𝑚𝑛.0<𝑛≤𝑚→𝖣𝗈𝗆(𝑚−𝑛)𝑛→𝖣𝗈𝗆𝑚𝑛,𝖽3:∀𝑚𝑛.0<𝑚<𝑛→𝖣𝗈𝗆𝑚(𝑛−𝑚)→𝖣𝗈𝗆𝑚𝑛, and the function is then defined by structural recursion on the extra proof argument, 𝗀𝖼𝖽𝖽:∀𝑚𝑛.𝖣𝗈𝗆𝑚𝑛→𝖭𝖺𝗍, matching on 𝖽0 through 𝖽3. For the total program one then proves ∀𝑚𝑛.𝖣𝗈𝗆𝑚𝑛—by the same measure 𝑚+𝑛—and recovers the type 𝖭𝖺𝗍→𝖭𝖺𝗍→𝖭𝖺𝗍; evaluation now proceeds by recursion on the domain argument, which costs time the accessibility definition does not. For 𝗌𝖾𝖺𝗋𝖼𝗁𝑃 the same predicate is definable and the same function is definable on it, but ∀𝑛.𝖣𝗈𝗆𝑛 is not provable, so what one obtains is a partial function one can still compute with and reason about—on exactly the arguments where the predicate is inhabited.
Termination casts and general recursion.
The two remaining techniques do not produce a definition inside the total theory at all. A termination cast asserts the missing obligation rather than discharging it: it accepts 𝗀𝖼𝖽𝗌𝗎𝖻 at the total type without the measure argument, and it accepts 𝗌𝖾𝖺𝗋𝖼𝗁𝑃 at that type too, which is precisely why the assertion is a trusted input and not a proof. A language with general recursion runs both programs as written: 𝗀𝖼𝖽𝗌𝗎𝖻(6,4) prints 2 and 𝗌𝖾𝖺𝗋𝖼𝗁𝑃(0) loops. Sjöberg’s calculus makes this respectable by separating the fragment whose terms may appear in types from the fragment that may diverge; the price is that the second fragment’s results are not available as proofs.
Suggested first pass.
None of these problems is a prerequisite for a later chapter. Begin with exercise 105.4, then complete exercise 105.6.
★★★ Define subtraction-based gcd as a delayed computation. Prove that the measure 𝑚+𝑛 decreases in every recursive branch and derive convergence. Then state the total value extracted from the convergence proof. Compare the accepted definition with one using an accessibility argument.
★★★Practical project.partiality-fuel-observer Implement in Kappa a finite observer for return, step, bind, subtraction gcd, and unbounded search represented by a step function. Maintain the invariant that one unit of fuel removes at most one 𝗌𝗍𝖾𝗉. On gcd-6-4-20, search-even-from-3-4, and search-never-12, print done 2, done 4, and later, respectively. A mutation that removes a step without consuming fuel must fail an exact step-count oracle. The observer witnesses finite convergence; printing later is not a proof of divergence.
Sources. Partial elements, convergence, extensional equality, representability, finitary fixed points, and the strong partiality monad follow Capretta [Cap05]. Definition 4.1 and Theorem 4.2 are on printed pp. 15–16, Theorems 6.19–6.20 on printed p. 22, and Definitions 8.1 and Theorem 8.2 on printed pp. 24–25; each proof package is shorter than ten pages and is incorporated above. The comparison of domain predicates, accessibility, and assistant-specific general recursion follows Bove, Krauss, and Sozeau [BKS16]. The nonterminating dependent-language comparison is bounded to Sjöberg’s separate calculus [Sjo15]; it supplies no theorem for the coinductive signature printed here.