Okay, let's talk. I keep seeing people turn off the totality checker with partial in Idris or {-# TERMINATING #-} in Agda like it's some totally normal thing to do, and I'm tired of it. Totality checking is not your enemy. It is one of the best features in dependently typed languages and you are sleeping on it.
Here is the core thing people don't get: in a dependently typed language, type checking is computation. If you allow arbitrary non-terminating definitions, your type checker can loop. Your proofs become meaningless. You break the Curry-Howard correspondence. You are essentially poking a hole in your logic and saying "yeah, this is fine actually."
From the Agda docs: "if arbitrary (i.e. non-terminating) computations were allowed, then the typechecking would become undecidable." This is not a theoretical concern. This is your proof assistant turning into a black hole.
Now, the totality checker is not as restrictive as people think. Agda supports:
-- 1. Primitive recursion (argument shrinks by exactly one constructor) plus : Nat → Nat → Nat plus zero m = m plus (suc n) m = suc (plus n m) -- 2. Structural recursion (strict subexpression of argument) fib : Nat → Nat fib zero = zero fib (suc zero) = suc zero fib (suc (suc n)) = plus (fib n) (fib (suc n)) -- 3. Lexicographic ordering (Ackermann!) ack : Nat → Nat → Nat ack zero m = suc m ack (suc n) zero = ack n (suc zero) ack (suc n) (suc m) = ack n (ack (suc n) m)
That last one—Ackermann—is a famously fast-growing function, and Agda's termination checker is totally fine with it because the first argument decreases OR it stays the same and the second argument decreases—this is lexicographic ordering and it's exactly what the checker looks for.
And that's just the basic stuff. For harder cases you have sized types. For infinite data you have coinduction with productivity checking. There is a whole toolkit here. Stop reaching for TERMINATING as your first move. 🐾