[Agda] list for termination counter

Sergei Meshveliani mechvel at botik.ru
Mon Aug 22 14:48:25 CEST 2016


Can somebody explain, please,
what may be a simple way to prove termination in the following example?

 
---------------------------------------------------------------
open import Function                   using (case_of_)
open import Algebra.FunctionProperties using (Op₂)
open import Relation.Nullary using (yes; no)
open import Relation.Binary  using (DecTotalOrder)
open import Relation.Binary.PropositionalEquality as PE using(_≡_)
open import Data.Nat  using (ℕ; decTotalOrder)
open import Data.List using (List; []; _∷_)

open DecTotalOrder decTotalOrder using (_≤?_)

record R : Set where
               constructor r
               field  members : List ℕ

add : Op₂ R

add (r [])       g            =  g
add f            (r [])       =  f
add (r (m ∷ ms)) (r (n ∷ ns)) =
    case
        m ≤? n
    of \
    { (yes _) → let (r hMems) = add (r (m ∷ ms)) (r ns)
                in  r (n ∷ hMems)

    ; (no _)  → let (r hMems) = add (r ms) (r (n ∷ ns))
                in  r (m ∷ hMems)
    }
--------------------------------------------------------------------

This is something similar to merging of ordered lists.
Agda does not see termination. I think, this is due to that the lists
are kept under the constructor r.
So, I extract the two lists and use them as counters for termination:

-------------------------------------------------------------------
add f g =  aux f g (R.members f) (R.members g) PE.refl PE.refl
  where
  aux : (f g : R) → (ms ns : List ℕ) → ms ≡ R.members f →
                                       ns ≡ R.members g → R

  aux (r .[]) g        [] _  PE.refl _       =  g
  aux f       (r .[])  _  [] _       PE.refl =  f

  aux (r .(m ∷ ms)) (r .(n ∷ ns)) (m ∷ ms) (n ∷ ns) PE.refl PE.refl =
    case
        m ≤? n
    of \
    { (yes _) → let (r hMems) = aux (r (m ∷ ms)) (r ns) (m ∷ ms) ns
                                                        PE.refl PE.refl
                in  r (n ∷ hMems)

    ; (no _)  → let (r hMems) = aux (r ms) (r (n ∷ ns)) ms (n ∷ ns)
                                                        PE.refl PE.refl
                in  r (m ∷ hMems)
    }
------------------------------------------------------------------------

The 'yes' pattern calls aux with  ns  -- which list expression is
syntactically smaller than   n ∷ ns.
The 'no' pattern calls aux with  ms  -- which list expression is
syntactically smaller than   m ∷ ms.

But Agda still reports : "Termination checking failed".

Why?
How to fix?
What is a simple way to prove termination in this example?

Thanks,

------
Sergei


 




More information about the Agda mailing list