Agda - Why is this case required to type check? In a simple proof that $forall m, 1 * m \equiv m$ - agda

After defining the naturals, addition and multiplication as usual, I set to write a proof that 1 is a neutral element.
p : (n : ℕ) -> (1 * n) ≡ n
p zero = refl
p (suc m) = refl
Which is fine!
Since refl appears in both alternatives, I thought this should type-check:
p : (n : ℕ) -> (1 * n) ≡ n
p _ = refl
But this fails with:
1 * n != n of type ℕ
when checking that the expression refl has type (1 * n) ≡ n
What causes type to not check here?

It's hard to diagnose an error without a MRE, no matter how standard you think your definitions are.
Your error presumably comes from the fact _+_ and _*_ are defined like so:
0 + n = n
m + 0 = m
suc m + n = suc (m + n)
0 * n = n
suc m * n = n + m * n
and so 1 * n = (suc 0) * n = n + 0 * n = n + 0 which is not judgmentally
equal to n because _+_ is strict in its first argument and so won't
evaluate until that first argument is constructor-headed.
Matching on n to expose a constructor is enough for _+_ to reduce:
0 + 0 is 0 by the first equation and suc m + 0 is suc m by the second.

Related

Proof about a function that uses rewrite: a "vertical bars in goals" question

I have a function that uses rewrite to satisfy the Agda type checker. I thought that I had a reasonably good grasp of how to deal with the resulting "vertical bars" in proofs about such functions. And yet, I fail completely at dealing with these bars in my seemingly simple case.
Here are the imports and my function, step. The rewrites make Agda see that n is equal to n + 0 and that suc (acc + n) is equal to acc + suc n, respectively.
module Repro where
open import Relation.Binary.PropositionalEquality as P using (_≡_)
open import Data.Nat
open import Data.Nat.DivMod
open import Data.Nat.DivMod.Core
open import Data.Nat.Properties
open import Agda.Builtin.Nat using () renaming (mod-helper to modₕ)
step : (acc d n : ℕ) → modₕ acc (acc + n) d n ≤ acc + n
step zero d n rewrite P.sym (+-identityʳ n) = a[modₕ]n<n n (suc d) 0
step (suc acc) d n rewrite P.sym (+-suc acc n) = a[modₕ]n<n acc (suc d) (suc n)
Now for the proof, which pattern matches on acc, just like the function. Here's the zero case:
step-ok : ∀ (acc d n : ℕ) → step acc d n ≡ a[modₕ]n<n acc d n
step-ok zero d n with n | P.sym (+-identityʳ n)
step-ok zero d n | .(n + 0) | P.refl = ?
At this point, Agda tells me I'm not sure if there should be a case for the constructor P.refl, because I get stuck when trying to solve the following unification problems (inferred index ≟ expected index): w ≟ w + 0 [...]
I am also stuck in the second case, the suc acc case, albeit in a different way:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n)
step-ok (suc acc) d n | .(acc + suc n) | P.refl = ?
Here, Agda says suc (acc + n) != w of type ℕ when checking that the type [...] of the generated with function is well-formed
Update after Sassa NF's response
I followed Sassa NF's advice and reformulated my function with P.subst instead of rewrite. I.e., I changed my right-hand side from being about n + 0 to being about n, instead of conversely changing the goal from being about n to being about n + 0:
step′ : (acc d n : ℕ) → modₕ acc (acc + n) d n ≤ acc + n
step′ zero d n = P.subst (λ # → modₕ 0 # d # ≤ #) (+-identityʳ n) (a[modₕ]n<n n (suc d) 0)
step′ (suc acc) d n = P.subst (λ # → modₕ (suc acc) # d n ≤ #) (+-suc acc n) (a[modₕ]n<n acc (suc d) (suc n))
During the proof, the P.subst in the function definition needs to be eliminated, which can be done with a with construct:
step-ok′ : ∀ (acc d n : ℕ) → step′ acc d n ≡ a[modₕ]n<n acc d n
step-ok′ zero d n with n + 0 | +-identityʳ n
... | .n | P.refl = P.refl
step-ok′ (suc acc) d n with acc + suc n | +-suc acc n
... | .(suc (acc + n)) | P.refl = P.refl
So, yay! I just finished my very first Agda proof involving a with.
Some progress on the original problem
My guess would be that my first issue is a unification issue during dependent pattern matching: there isn't any substitution that makes n identical to n + 0. More generally, in situations where one thing is a strict subterm of the other thing, I suppose that we may run into unification trouble. So, maybe using with to match n with n + 0 was asking for problems.
My second issue seems to be what the Agda language reference calls an ill-typed with-abstraction. According to the reference, this "happens when you abstract over a term that appears in the type of a subterm of the goal or argument types." The culprit seems to be the type of the goal's subterm a[modₕ]n<n (suc acc) d n, which is modₕ [...] ≤ (suc acc) + n, which contains the subterm I abstract over, (suc acc) + n.
It looks like this is usually resolved by additionally abstracting over the part of the goal that has the offending type. And, indeed, the following makes the error message go away:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n
... | .(acc + suc n) | P.refl | rhs = {!!}
So far so good. Let's now introduce P.inspect to capture the rhs substitution:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n | P.inspect (a[modₕ]n<n (suc acc) d) n
... | .(acc + suc n) | P.refl | rhs | P.[ rhs-eq ] = {!!}
Unfortunately, this leads to something like the original error: w != suc (acc + n) of type ℕ when checking that the type [...] of the generated with function is well-formed
One day later
Of course I'd run into the same ill-typed with-abstraction again! After all, the whole point of P.inspect is to preserve a[modₕ]n<n (suc acc) d n, so that it can construct the term a[modₕ]n<n (suc acc) d n ≡ rhs. However, preserved a[modₕ]n<n (suc acc) d n of course still has its preserved original type, modₕ [...] ≤ (suc acc) + n, whereas rhs has the modified type modₕ [...] ≤ acc + suc n. That's what's causing trouble now.
I guess one solution would be to use P.subst to change the type of the term we inspect. And, indeed, the following works, even though it is hilariously convoluted:
step-ok (suc acc) d n with suc (acc + n) | P.sym (+-suc acc n) | a[modₕ]n<n (suc acc) d n | P.inspect (λ n → P.subst (λ # → modₕ (suc acc) # d n ≤ #) (P.sym (+-suc acc n)) (a[modₕ]n<n (suc acc) d n)) n
... | .(acc + suc n) | P.refl | rhs | P.[ rhs-eq ] rewrite +-suc acc n = rhs-eq
So, yay again! I managed to fix my original second issue - basically by using P.subst in the proof instead of in the function definition. It seems, though, that using P.subst in the function definition as per Sassa NF's guidance is preferable, as it leads to much more concise code.
The unification issue is still a little mysterious to me, but on the positive side, I unexpectedly learned about the benefits of irrelevance on top of everything.
I'm accepting Sassa NF's response, as it put me on the right track towards a solution.
Your use of P.refl indicates some misunderstanding about the role of _≡_.
There is no magic in that type. It is just a dependent type with a single constructor. Proving that some x ≡ y resolves to P.refl does not tell Agda anything new about x and y: it only tells Agda that you managed to produce a witness of the type _≡_. This is the reason it cannot tell n and .(n + 0) are the same thing, or that suc (acc + n) is the same as .(acc + suc n). So both of the errors you see are really the same.
Now, what rewrite is for.
You cannot define C x ≡ C y for dependent type C _. C x and C y are different types. Equality is defined only for elements of the same type, so there is no way to even express the idea that an element of type C x is comparable to an element of type C y.
There is, however, an axiom of induction, which allows to produce elements of type C y, if you have an element of type C x and an element of type x ≡ y. Note there is no magic in the type _≡_ - that is, you can define your own type, and construct such a function, and Agda will be satisfied:
induction : {A : Set} {C : (x y : A) -> (x ≡ y) -> Set} (x y : A) (p : x ≡ y) ((x : A) -> C x x refl) -> C x y p
induction x .x refl f = f x
Or a simplified version that follows from the induction axiom:
transport : {A : Set} {C : A -> Set} (x y : A) (x ≡ y) (C x) -> C y
transport x .x refl cx = cx
What this means in practice, is that you get a proof for something - for example, A x ≡ A x, but then transport this proof along the equality x ≡ y to get a proof A x ≡ A y. This usually requires specifying the type explicitly, in this case {C = y -> A x ≡ A y}, and provide the x, the y and the C x. As such, it is a very cumbersome procedure, although the learners will benefit from doing these steps.
rewrite then is a syntactic mechanism that rewrites the types of the terms known before the rewrite, so that such transport is not needed after that. Because it is syntactic, it does interpret the type _≡_ in a special way (so if you define your own type, you need to tell Agda you are using a different type as equality). Rewriting types is not "telling" Agda that some types are equal. It just literally replaces occurrences of x in type signatures with y, so now you only need to construct things with y and refl.
Having said all that, you can see why it works for step. There rewrite P.sym ... literally replaced all occurrences of n with n + 0, including the return type of the function, so now it is modₕ acc (acc + (n + 0)) d (n + 0) ≤ acc + (n + 0). Then constructing a value of that type just works.
Then step-ok didn't work, because you only pattern-matched values. There is nothing to tell that n and (n + 0) are the same thing. But rewrite will. Or you could use a function like this transport.

Could not parse the left-hand side (m + 1) * n

I just started learning Agda reading Programming Language Foundations in Agda. Right in the first chapter there's a definition of multiplication with one of the cases being (suc m) * n = n + (m * n). I assumed it could be nicer expressed as (m + 1) * n = n + (m * n), but apparently this is not the case. The following program:
data ℕ : Set where
zero : ℕ
suc : ℕ → ℕ
_+_ : ℕ → ℕ → ℕ
zero + n = n
(suc m) + n = suc (m + n)
{-# BUILTIN NATURAL ℕ #-}
_*_ : ℕ → ℕ → ℕ
zero * n = zero
-- This is fine:
-- (suc m) * n = n + (m * n)
-- This is not:
(m + 1) * n = n + (m * n)
fails with:
Could not parse the left-hand side (m + 1) * n
Operators used in the grammar:
* (infix operator, level 20) [_*_ (/Users/proxi/Documents/Projekty/Agda/multiply.agda:11,1-4)]
+ (infix operator, level 20) [_+_ (/Users/proxi/Documents/Projekty/Agda/multiply.agda:5,1-4)]
when scope checking the left-hand side (m + 1) * n in the
definition of _*_
I believe in Agda terms one could say that definition using constructor works fine, but definition using operator does not. Why is that so? Is this never possible, or does it depend on how operator (function) is defined?
Using functions in patterns is not supported.
Note also that if functions were allowed in patterns, it would be (1 + m) * n rather than (m + 1) * n, because _+_ is defined by pattern matching on its first argument, so 1 + m reduces to suc m and m + 1 is stuck.
As has been pointed out, you cannot just use a function to pattern-match. However, it is possible to declare pattern-matching extensions that express nearly the same thing:
open import Data.Nat.Base as Nat
using (ℕ; zero) renaming (suc to 1+_)
pattern 2+_ n = 1+ 1+ n
Then you can use (1+ m) * n, and even (2+ m).

Why does `sym` need to be used in this case when using `rewriting`?

Given the Peano definition of natural numbers:
data ℕ : Set where
zero : ℕ
suc : ℕ → ℕ
_+_ : ℕ → ℕ → ℕ
zero + n = n
(suc m) + n = suc (m + n)
We can prove by different methods the property ∀ (m : ℕ) → zero + m ≡ m + zero.
For example:
comm-+₀ : ∀ (m : ℕ) → zero + m ≡ m + zero
comm-+₀ zero = refl
comm-+₀ (suc n) =
begin
zero + suc n
≡⟨⟩
zero + suc (zero + n)
≡⟨⟩
suc (zero + n)
≡⟨ cong suc (comm-+₀ n) ⟩
suc (n + zero)
≡⟨⟩
suc n + zero
∎
And more compactly:
comm-+₀ : ∀ (m : ℕ) → zero + m ≡ m + zero
comm-+₀ zero = refl
comm-+₀ (suc n) = cong suc (comm-+₀ n)
If we want, we can even use rewrite and forgo cong:
comm-+₀ : ∀ (m : ℕ) → zero + m ≡ m + zero
comm-+₀ zero = refl
comm-+₀ (suc n) rewrite comm-+₀ n = refl
But wait! That doesn't work. Agda will tell us that the expression is wrong because it can't prove the following:
suc (n + 0) ≡ suc (n + 0 + 0)
If we present Agda the symmetrical rewrite of the property, sym (comm-+₀ n), it will type check without errors.
So, my question is: why do we need sym in this case? The proof worked perfectly fine without it with the other strategies. Does rewrite work on both sides simultaneously and not just the left side?
In every cases, the goal when m is of the form suc n is:
suc n ≡ suc (n + 0)
To solve this goal by providing a correctly typed term, the right way is, as you noticed:
cong suc (comm-+₀ n)
However, when using rewrite with an equality a ≡ b you modify directly the goal by substituting all occurences of a by b In your case, using rewrite on the quantity comm-+₀ n whose type is n ≡ n + 0 leads to the replacing of every occurence of n by n + 0, thus transforming the goal from
suc n ≡ suc (n + 0)
to
suc (n + 0) ≡ suc (n + 0 + 0)
which is not what you want to do. Since rewriting replaces all occurences of the left side by the right side, reversing the equality using sym will instead replace the only occurence of n + 0 by n thus transforming the goal from
suc n ≡ suc (n + 0)
to
suc n ≡ suc n
which is your expected behaviour and let you conclude using refl direcly. This explains why you need to use sym.
To summarize :
rewrite interacts directly with the type of the goal.
rewrite rewrites from left to right.
rewrite rewrites all occurences it finds in the type of the goal.
More on rewrite can be found here:
https://agda.readthedocs.io/en/v2.6.0.1/language/with-abstraction.html#with-rewrite

How to prove that division is cancellative?

I want to prove that (c * a) / (c * b) = a / b in agda using the division function defined in the standard library. The proofs keep coming back to this thing div-helper that is very difficult to work with and reason about.
open import Data.Nat.DivMod using (_/_)
open import Relation.Binary.PropositionalEquality using (_≡_)
open import Data.Nat using (ℕ; suc; zero)
/-cancelˡ : ∀ c a b {b≢0} {b*c≢0} → ((c * a) / (c * b)) {b*c≢0} ≡ (a / b) {b≢0}
/-cancelˡ (suc c) a (suc b) {b≢0} {b*c≢0} = ?
That hole simplifies to:
div-helper 0 (b + c * suc b) (a + c * a) (b + c * suc b) ≡ div-helper 0 b a b
I could come up with two different proofs.
Proof 1 is completely agnostic of div-helper's structure. It is based on lemmas about division from the standard library. It proves a few additional lemmas about division, which it then uses to prove the property we're after. It's a little involved, but I think that the additional lemmas are useful in their own right.
Proof 2 considers the structure of div-helper and proves two invariants from which the property follows trivially. It's way more concise.
This is the property we're after:
∀ (a b n : ℕ) → divₕ 0 (b + n + b * n) (a + n * a) (b + n + b * n) ≡ divₕ 0 b a b
What makes this look a little weird is that the division helper takes n (as opposed to suc n) for a / suc n. That's where b + n + b * n comes from - suc (b + n + b * n) is equal to suc b * suc n.
Stated in terms of / instead of the division helper, the proof thus says that (a * suc n) / (suc b * suc n) is equal to a / suc b.
This is proof 1:
module Answer where
open import Relation.Binary.PropositionalEquality as P using (_≡_; cong; refl; subst; sym)
open import Data.Nat
open import Data.Nat.DivMod
open import Data.Nat.DivMod.Core
open import Data.Nat.Properties
open import Agda.Builtin.Nat using () renaming (div-helper to divₕ; mod-helper to modₕ)
divₕ′ : ℕ → ℕ → ℕ
divₕ′ a m = divₕ 0 m a m
modₕ′ : ℕ → ℕ → ℕ
modₕ′ a m = modₕ 0 m a m
a<n⇒a[divₕ]n≡0 : ∀ (a n n′ : ℕ) → a ≤ n → divₕ 0 n′ a n ≡ 0
a<n⇒a[divₕ]n≡0 zero _ _ _ = refl
a<n⇒a[divₕ]n≡0 (suc a) (suc n) n′ (s≤s a≤n) = a<n⇒a[divₕ]n≡0 a n n′ a≤n
a*n[modₕ]n≡0 : ∀ (a n : ℕ) → modₕ 0 n (a * suc n) n ≡ 0
a*n[modₕ]n≡0 zero n = refl
a*n[modₕ]n≡0 (suc a) n rewrite +-comm (suc n) (a * suc n) | a+n[modₕ]n≡a[modₕ]n 0 (a * suc n) n = a*n[modₕ]n≡0 a n
a<n⇒a+b*n[divₕ]n≡b : ∀ (a b n : ℕ) → a ≤ n → divₕ 0 n (a + b * suc n) n ≡ b
a<n⇒a+b*n[divₕ]n≡b a b n a≤n =
begin
divₕ′ (a + b * suc n) n
≡⟨ +-distrib-divₕ 0 0 a (b * suc n) n lem₁ ⟩
divₕ′ a n + divₕ′ (b * suc n) n
≡⟨ cong (_+ divₕ′ (b * suc n) n) (a<n⇒a[divₕ]n≡0 a n n a≤n) ⟩
0 + divₕ′ (b * suc n) n
≡⟨ +-identityˡ (divₕ 0 n (b * suc n) n) ⟩
divₕ′ (b * suc n) n
≡⟨ m*n/n≡m b (suc n) ⟩
b
∎
where
open P.≡-Reasoning
≤₁ = a[modₕ]n<n 0 a n
≤₂ = ≤-reflexive (a*n[modₕ]n≡0 b n)
<₃ : n + 0 < suc n
<₃ = s≤s (≤-reflexive (+-identityʳ n))
lem₁ : modₕ′ a n + modₕ′ (b * suc n) n < suc n
lem₁ = <-transʳ (+-mono-≤ ≤₁ ≤₂) <₃
a[divₕ]m*n≡a[divₕ]m[divₕ]n : ∀ (a m n : ℕ) → divₕ 0 (m + n + m * n) a (m + n + m * n) ≡ divₕ 0 n (divₕ 0 m a m) n
a[divₕ]m*n≡a[divₕ]m[divₕ]n a m n =
begin
divₕ′ a mn
≡⟨ cong (λ # → divₕ′ # mn) (div-mod-lemma 0 0 a m) ⟩
divₕ′ (modₕ′ a m + divₕ′ a m * suc m) mn
≡⟨ cong (λ # → divₕ′ (modₕ′ a m + # * suc m) mn) (div-mod-lemma 0 0 (divₕ′ a m) n) ⟩
divₕ′ (modₕ′ a m + (modₕ′ (divₕ′ a m) n + divₕ′ (divₕ′ a m) n * suc n) * suc m) mn
≡⟨ cong (λ # → divₕ′ (modₕ′ a m + #) mn) (*-distribʳ-+ (suc m) (modₕ′ (divₕ′ a m) n) (divₕ′ (divₕ′ a m) n * suc n)) ⟩
divₕ′ (modₕ′ a m + (modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * suc n * suc m)) mn
≡⟨ cong (λ # → divₕ′ # mn) (sym (+-assoc (modₕ′ a m) (modₕ′ (divₕ′ a m) n * suc m) (divₕ′ (divₕ′ a m) n * suc n * suc m))) ⟩
divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * suc n * suc m) mn
≡⟨ cong (λ # → divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + #) mn) (*-assoc (divₕ′ (divₕ′ a m) n) (suc n) (suc m))⟩
divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * (suc n * suc m)) mn
≡⟨ cong (λ # → divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * #) mn) (*-comm (suc n) (suc m)) ⟩
divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * (suc m * suc n)) mn
≡⟨ cong (λ # → divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * #) mn) lem₁ ⟩
divₕ′ (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m + divₕ′ (divₕ′ a m) n * suc mn) mn
≡⟨ a<n⇒a+b*n[divₕ]n≡b (modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m) (divₕ′ (divₕ′ a m) n) mn lem₄ ⟩
divₕ 0 n (divₕ′ a m) n
∎
where
open P.≡-Reasoning
mn = m + n + m * n
lem₁ : suc m * suc n ≡ suc mn
lem₁ rewrite +-comm m n | *-comm m (suc n) | *-comm m n | +-assoc n m (n * m) = refl
lem₂ : m + n * suc m ≡ mn
lem₂ rewrite *-comm n (suc m) | +-assoc m n (m * n) = refl
≤₁ = a[modₕ]n<n 0 a m
≤₂ = a[modₕ]n<n 0 (divₕ 0 m a m) n
≤₃ = ≤-refl {suc m}
lem₃ = +-mono-≤ ≤₁ (*-mono-≤ ≤₂ ≤₃)
lem₄ : modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m ≤ mn
lem₄ = subst (λ # → modₕ′ a m + modₕ′ (divₕ′ a m) n * suc m ≤ #) lem₂ lem₃
a*n[divₕ]b*n≡a[divₕ]b : ∀ (a b n : ℕ) → divₕ 0 (b + n + b * n) (a + n * a) (b + n + b * n) ≡ divₕ 0 b a b
a*n[divₕ]b*n≡a[divₕ]b a b n =
begin
divₕ′ na nb
≡⟨ cong (λ # → divₕ′ na #) nb≡bn ⟩
divₕ′ na bn
≡⟨ a[divₕ]m*n≡a[divₕ]m[divₕ]n na n b ⟩
divₕ′ (divₕ′ na n) b
≡⟨ cong (λ # → divₕ′ (divₕ′ # n) b) lem₁ ⟩
divₕ′ (divₕ′ (a * suc n) n) b
≡⟨ cong (λ # → divₕ′ # b) (a*n[divₕ]n≡a 0 a n) ⟩
divₕ 0 b a b
∎
where
open P.≡-Reasoning
na = a + n * a
nb = b + n + b * n
bn = n + b + n * b
nb≡bn : nb ≡ bn
nb≡bn rewrite +-comm n b | *-comm n b = refl
lem₁ : na ≡ a * suc n
lem₁ rewrite *-comm a (suc n) = refl
Now let's look at proof 2. Simply append it to the above code, so that I don't have to repeat the imports:
a*n[divₕ]b*n≡a[divₕ]b′ : ∀ (a b n : ℕ) → divₕ 0 (b + n + b * n) (a + n * a) (b + n + b * n) ≡ divₕ 0 b a b
a*n[divₕ]b*n≡a[divₕ]b′ a b n rewrite +-comm b n | *-comm b n = lem₂ n 0 b a b
where
lem₁ : ∀ (a k m n j : ℕ) → divₕ k m (a + n) (a + j) ≡ divₕ k m n j
lem₁ zero k m n j = refl
lem₁ (suc a) k m n j = lem₁ a k m n j
lem₂ : ∀ (a k m n j : ℕ) → divₕ k (a + m + a * m) (suc a * n) (a + j + a * j) ≡ divₕ k m n j
lem₂ a k m zero j rewrite *-zeroʳ a = refl
lem₂ a k m (suc n) zero
rewrite *-zeroʳ a
| +-identityʳ a
| *-suc a n
| P.sym (+-assoc n a (a * n))
| +-comm n a
| +-assoc a n (a * n)
| P.sym (+-suc a (n + a * n))
| lem₁ a k (a + m + a * m) (suc (n + a * n)) 0
= lem₂ a (suc k) m n m
lem₂ a k m (suc n) (suc j)
rewrite *-suc a n
| P.sym (+-assoc n a (a * n))
| +-comm n a
| +-assoc a n (a * n)
| P.sym (+-suc a (n + a * n))
| +-assoc a (suc j) (a * suc j)
| lem₁ a k (a + m + a * m) (suc (n + a * n)) (suc j + a * suc j)
| *-suc a j
| P.sym (+-assoc j a (a * j))
| +-comm j a
= lem₂ a k m n j
The first lemma is an invariant that says that we can add an identical value a to the last two arguments of div-helper, n and j. It's used by the second lemma, which is the more interesting one.
The second lemma is an invariant that says that you can multiply the last three arguments, m, n, and j, with an identical value a. Its a proof by induction on the last two arguments, n and j. This makes it closely follow the structure of div-helper.
The proof thus covers the same three different cases that show up in the three defining equations of div-helper:
n is zero
n is non-zero, but j is zero
n and j are both non-zero
The property that we're after then follows directly from the second lemma. This is basically the idea outlined in the other response, where the second lemma is the more general version of the property that we're after.
Note that the invariants div-helper respects are spelt out in the builtin file Agda.Builtin.Nat. You should state a more general version of your lemma satisfied by div-helper.

How to pattern match against absurd / unconstructable Type?

From what I understand these two definitions a̶r̶e̶ ̶e̶q̶u̶i̶v̶a̶l̶e̶n̶t̶ represent the same behaviour:
data _<_ : ℕ → ℕ → Set where
lt-zero : {n : ℕ} → zero < suc n
lt-suc : {m n : ℕ} → m < n → (suc m) < (suc n)
lt : ℕ → ℕ → Bool
lt _ zero = false
lt zero (suc n) = true
lt (suc m) (suc n) = m < n
Except that _<_ can be more easily used to prove things about itself, and lt, from what I have found, is easier to use for programming other behaviours. For example I can see how I can easily define a min function using lt:
min : ℕ → ℕ → ℕ
min x y where lt x y
... | true = x
... | false = y
Is there a way for me to define min and other similar functions using _<_? From what I have found there is no way to pattern match x < y if y is less than x. Is there a different method to use _<_ in these cases?
EDIT: Would adding a not-true case to _<_ be a sensible idea?
̶E̶D̶I̶T̶ ̶2̶:̶ ̶O̶r̶ ̶i̶s̶ ̶t̶h̶i̶s̶ ̶t̶h̶e̶ ̶'̶c̶o̶r̶r̶e̶c̶t̶'̶ ̶w̶a̶y̶ ̶t̶o̶ ̶d̶o̶ ̶i̶t̶?̶
EDIT 3: I have changed the below definition of min, in order to be able to omit proofs for x <? y when using min.
data _<?_ (n m : ℕ) : Set where
isLT : n < m → n <? m
notLT : m ≤ n → n <? m
min : (x y : ℕ) → {p : x <? y} → ℕ
min x y (isLT _) = x
min x y (notLT _) = y
This did not work as expected. If I true to evaluate min 1 2, using C-c C-n, it returns min 1 2. I can get it to return the min, if I give it a proof, however if I evaluate min 2 1 (isLT _) it returns 2, instead of giving me an error message. Is there a way for me to define min using _<_, so that Agda could evaluate min 1 2?
There is a way to eliminate impossible patterns in Agda. Using your definition of _<_
you can try to prove transitivity to illustrate this.
le-trans : ∀ {m n k} → m < n → n < k → m < k
le-trans {k = k} lt-zero b = {!!}
le-trans (lt-suc a) (lt-suc b) = lt-suc (le-trans a b)
Goal: 0 < k
b : suc .n < k
We pattern match on the first argument, the step case is a simple application of the hypothesis. In the base case, we have to pattern match on k since the base constructor of your data type says zero < suc n, but we don't know anything about k yet. Upon pattern matching on k we see two cases
le-trans : ∀ {m n k} → m < n → n < k → m < k
le-trans {k = zero} lt-zero b = {!!}
le-trans {k = suc k} lt-zero b = {!!}
le-trans (lt-suc a) (lt-suc b) = lt-suc (le-trans a b)
In the first one, we see something impossible, i.e, Goal: 0 < zero and we have an element of type b : suc .n < zero, which cannot occur. Then, you can pattern match on b and Agda will see that you cannot construct such thing and will eliminate this case le-trans {k = zero} lt-zero (). Whereas in the other case, you can prove it with the base constructor.
le-trans : ∀ {m n k} → m < n → n < k → m < k
le-trans {k = zero} lt-zero ()
le-trans {k = suc k} lt-zero b = lt-zero
le-trans (lt-suc a) (lt-suc b) = lt-suc (le-trans a b)
Therefore, defining a not-true case in datatypes is not appropriate. You define how elements are constructed. Your last definition of _<?_ makes sense and can be, in fact, used.
Edit on min
Once you have the inductive relation for _<?_, you can work as follows. Define a function that gives you m <? n and then for the min function, do a with abstraction calling that function.
data _≥_ : ℕ → ℕ → Set where
get-z : ∀ {n} → n ≥ zero
get-s : ∀ {m n} → m ≥ n → (suc m) ≥ (suc n)
data _<?_ (n m : ℕ) : Set where
y-< : n < m → n <? m
n-< : n ≥ m → n <? m
f<? : (m n : ℕ) → m <? n
f<? zero zero = n-< get-z
f<? zero (suc n) = y-< lt-zero
f<? (suc m) zero = n-< get-z
f<? (suc m) (suc n) with f<? m n
f<? (suc m) (suc n) | y-< x = y-< (lt-suc x)
f<? (suc m) (suc n) | n-< x = n-< (get-s x)
min : ℕ → ℕ → ℕ
min x y with f<? x y
min x y | y-< _ = x
min x y | n-< _ = y

Resources