πŸ“₯ Download raw
module Padova2025.ProvingBasics.Termination.BoveCapretta.Intricate0 where

An intricate zero function

open import Padova2025.ProgrammingBasics.Naturals.Base
open import Padova2025.ProvingBasics.Equality.Base
open import Padova2025.ProvingBasics.Equality.General

Let us consider the following recursive function definition.

f : β„• β†’ β„•
f zero     = zero
f (succ x) = f (f x)

Agda rejects this definition with the comment β€œTermination checking failed”. Agda’s termination checker does not have any insight on what the value of f x in the recursive call f (f x) will turn out to be. But even though this fact is not obvious to Agda, the recursive call terminates and the function f is constantly zero.

Representing the function

To represent this function in Agda, we first introduce by induction-recursion a predicate Def and a function fβ‚€. For a number n, Def n expresses that n belongs to the domain, i.e.Β that the recursion terminates on input n. The function fβ‚€ takes two inputs, a number n and a witness that the recursion terminates on input n, and computes the result of the recursion.

data Def : β„• β†’ Set
fβ‚€ : (n : β„•) β†’ Def n β†’ β„•

data Def where
  base : Def zero
  step : {x : β„•} β†’ (p : Def x) β†’ Def (fβ‚€ x p) β†’ Def (succ x)

fβ‚€ zero     _          = zero
fβ‚€ (succ x) (step p q) = fβ‚€ (fβ‚€ x p) q

As a warmup, we can prove that the numbers zero, one, two and three indeed belong to the domain:

defined-on-input-zero : Def zero
defined-on-input-zero = {!!}
defined-on-input-one : Def one
defined-on-input-one = step {!!} {!!}
defined-on-input-two : Def two
defined-on-input-two = {!!}
defined-on-input-three : Def three
defined-on-input-three = {!!}

Conditionally evaluating the function

Under the assumption that n belongs to the function’s domain, we can show that the value on input n is zero:

all0 : (n : β„•) β†’ (p : Def n) β†’ fβ‚€ n p ≑ zero
all0 = {!!}

Verifying totality

The insight expressed by all0 is enough to conclude that the function is defined on all inputs.

total : (n : β„•) β†’ Def n
total = {!!}

With totality in place, we can finally define f as follows.

f : β„• β†’ β„•
f n = fβ‚€ n (total n)

Verifying the definition equation

We can also verify that the defining equation holds:

Def-prop : {x : β„•} β†’ (p q : Def x) β†’ p ≑ q
Def-prop = {!!}
fβ‚€-extensional : (x : β„•) (p q : Def x) β†’ fβ‚€ x p ≑ fβ‚€ x q
fβ‚€-extensional = {!!}
f-eq : (x : β„•) β†’ f (succ x) ≑ f (f x)
f-eq x = fβ‚€-extensional (f x) _ _