I'm surprised to see the following function fail the termination check. y ∷ ys
is structurally smaller than x ∷ y ∷ ys
, isn't it?
open import Data.List using (List ; [] ; _∷_)
open import Data.Nat using (ℕ ; zero ; suc)
open import Data.Nat.Properties using (<-cmp)
foo : List ℕ → ℕ
foo [] = 0
foo (x ∷ []) = 1
foo (x ∷ y ∷ ys) with <-cmp x y
... | _ = suc (foo (y ∷ ys))
Doing either (or both) of the following two things seems to make the termination checker see the light:
Removing the
with
-abstraction.Changing the last clause to match with
y ∷ ys
instead ofx ∷ y ∷ ys
and recurse withys
instead ofy ∷ ys
. (And also changing<-cmp x y
to<-cmp y y
for a lack ofx
s.)
Now I am even more confused than I usually am and I'm wondering: What's going on, how does the with
-abstraction (and its helper function) factor into all of this, and what do I do about it?
I've seen the other questions and answers concerning termination, but - unlike those more complicated cases - the case at hand seems to be about basic structural recursion, no?
Update
I just found an answer to the question, but if anybody would like to shed more light on what exactly is going on, e.g., how exactly the with
-abstraction interferes with termination checking, then I'd be more than happy to accept that answer instead.