[Agda] list for termination counter

G. Allais guillaume.allais at ens-lyon.org
Tue Aug 23 13:59:08 CEST 2016


Hi Sergei,

The issue comes from the pattern-matching lambda: it is quite often
the case that it hides a termination argument from Agda. Using an
equivalent `with` clause solves the issue:

---------------------------------------------------------------
add : Op₂ R
add (r [])       g            =  g
add f            (r [])       =  f
add (r (m ∷ ms)) (r (n ∷ ns)) with m ≤? n
... | 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)
---------------------------------------------------------------

Alternatively you can lift the recursive calls outside of the pattern
matching lambda (if your target language is lazy, the complexity should
be the same):

---------------------------------------------------------------
add' : Op₂ R
add' (r [])       g            =  g
add' f            (r [])       =  f
add' (r (m ∷ ms)) (r (n ∷ ns)) =
   let yesIH = add' (r ms) (r (n ∷ ns))
       noIH  = add' (r ms) (r (n ∷ ns))
   in case
         m ≤? n
     of \
     { (yes _) → let (r hMems) = yesIH
                 in  r (n ∷ hMems)

     ; (no _)  → let (r hMems) = noIH
                 in  r (m ∷ hMems)
     }	
---------------------------------------------------------------

Cheers,

On 22/08/16 14:48, Sergei Meshveliani wrote:
> 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
>
>
>
>
>
> _______________________________________________
> Agda mailing list
> Agda at lists.chalmers.se
> https://lists.chalmers.se/mailman/listinfo/agda
>


More information about the Agda mailing list