I'm currently writing the following incomplete function for this project:
extend : ∀ o asc (s : CSet (suc k) o) → SC asc → SC (add s asc)
extend 0 asc s rewrite l≡0 s Eq.refl =
restrict (add (empty _) asc) asc (add-∈ asc (empty∈asc asc))
extend 1 asc s = restrict (add s asc) asc (add-∈ asc (asc .hasAllPoints s))
extend {k} (suc (suc o)) asc s with has asc (_ , s) in eq
... | true = restrict (add s asc) asc (add-∈ asc (pser T eq tt))
... | false = result
module Extend where
extendAll : ∀ bsc (ss : Fin m → CSet (suc k) (suc o)) → SC bsc → SC (addAll ss bsc)
extendAll {zero} _ _ sc = sc
extendAll {suc _} bsc ss sc =
let head-ss = ss zero
tail-ss i = ss (suc i)
in extendAll (add head-ss bsc) tail-ss (extend (suc o) bsc head-ss sc)
faces : SC asc → SC (addAll (except s) asc)
faces = extendAll asc (except s)
cycl : SC asc → Cycle P o
cycl sc .face i = faces sc .for (∈-addAll (except s) asc i)
cycl sc .compatible i j =
P.proj (punchIn i) (cycl sc .face j) ≈˘⟨ P.map-cong (embed-except (except s j) Eq.refl _) _ ⟩
P.proj (embed (except⊂s (except s j) i)) (cycl sc .face j) ≡⟨⟩
P.proj (embed (except⊂s (except s j) i)) (faces sc .for (∈-addAll (except s) asc j)) ≈˘⟨ faces sc .compat (∈-addAll (except s) asc _) _ ⟩
faces sc .for (Has-⊆ (addAll (except s) asc) (except⊂s (except s j) i) (∈-addAll (except s) asc j)) ≡˘⟨ for-resp (faces sc) _ _ ⟩
faces sc .for (resp (_∈ addAll (except s) asc) (except-except s Eq.refl j i) (Has-⊆ (addAll (except s) asc) (except⊂s (except s j) i) (∈-addAll (except s) asc j))) ≡⟨ faces sc .for =$= T-irrel ⟩
faces sc .for (Has-⊆ (addAll (except s) asc) (except⊂s (except s (punchIn j i)) (pinch i j)) (∈-addAll (except s) asc (punchIn j i))) ≈⟨ faces sc .compat _ _ ⟩
P.proj (embed (except⊂s (except s (punchIn j i)) (pinch i j))) (faces sc .for (∈-addAll (except s) asc (punchIn j i))) ≡⟨⟩
P.proj (embed (except⊂s (except s (punchIn j i)) (pinch i j))) (cycl sc .face (punchIn j i)) ≈⟨ P.map-cong (embed-except (except s (punchIn j i)) Eq.refl _) _ ⟩
P.proj (punchIn (pinch i j)) (cycl sc .face (punchIn j i)) ∎
where open Relation.Reasoning (P._≃_)
open Equiv (refl (P.Space _)) (trig (P.Space _))
result : SC asc → SC (add s asc)
result sc .for {s = t} t∈added with add-⊂ {s = t} {s} {asc} t∈added
... | inj₂ t∈asc = sc .for t∈asc
... | inj₁ t⊂s with ⊂-except t⊂s Eq.refl
... | inj₂ (i , t⊂except) = faces sc .for (Has-⊆ (addAll (except s) asc) t⊂except (∈-addAll (except s) asc i))
... | inj₁ (Eq.refl , Eq.refl) = ?
result sc .compat = ?
As we can see, the only recursive call of extend to itself is in the final branch, where the first explicit argument o (which is a natural number) is pattern matched against suc (suc o), and the recursive call itself passes suc o as the first explicit argument, so it is strictly smaller than the one pattern matched against.
Yet, Agda 2.6.4.1 rejects this definition and complains about failed termination checking. Am I missing something here or is this possibly a bug?
Btw, sorry for not including all the definitions used in this function, as there are simply too many. If you want to experiment with it yourself, a slightly modified version of this function can be found in the aforementioned project under here, where the decreasing argument (named l there instead of o) is implicit instead of explicit (as originally intended), and extendAll is moved outside of extend.
I have no idea whether this will help, and in any case your code fragment is much too complicated for me to think about digging into the details... but what happens if you change the pattern
suc (suc o), with subsequent use ofsuc obelow, instead tosuc o@(suc _), and all subsequent occurrences ofsuc onow simply tooitself?As far as I can tell, you make no use of the additional sub-term
oofsuc (suc o)in any call, so use of the@-pattern would both be more precise, and simplify the subsequent code. One might hope...... but having said that, the termination checker is notoriously sensitive to recursive calls in the scope of an intermediate
with, and that may be the real reason for your troubles. Is such behaviour a 'bug'? Surely not, except that we might hope for better. The 'usual' solution here is to write the auxiliary function by hand, mutually with the main one, but in your case, that looks... challenging!Mind you, the
withconcerned is doing case analysis on a boolean... which for me at least, falls under the code smell of 'redundant uses ofwith', so I would consider refactoring to avoid that... which again in your case, would also involve refactoring away the use of the equationeq, but equations of the formb ≡ trueetc. aren't really working hard enough to earn their place to begin with, are they?