[ add ] Nat lemmas with _∸_, _⊔_ and _⊓_#2924
Conversation
MatthewDaggitt
left a comment
There was a problem hiding this comment.
Thanks for the PR!
- Naming and placement looks good to me.
- We tend to avoid rewriting in favour of using equational reasoning as its a) less brittle and b) clearer to the user what is going on. Could you switch these to use equational reasoning?
| ------------------------------------------------------------------------ | ||
| -- Properties of _∸_ and _⊓_ and _⊔_ | ||
|
|
||
| m∸n≤m⊔n : ∀ m n → m ∸ n ≤ m ⊔ n |
There was a problem hiding this comment.
This property doesn't feel natural to me, and the definition is short enough I don't really think it needs a name
There was a problem hiding this comment.
It looks kind of similar to the m⊔n≤m+n that is already here.
There was a problem hiding this comment.
I'm okay - lets one do proofs at a higher level with fewer steps.
There was a problem hiding this comment.
Can you provide an example of an "interesting" proof where this lemma is a useful step?
There was a problem hiding this comment.
I don't know if that counts as interesting, but the only place where I used it is down below in the m⊔n∸[m∸n]≡n.
Just to be clear I'm fine with removing that. In this PR I've just included stuff that I've tried to lookup in the stdlib first and written down once I couldn't find it.
There was a problem hiding this comment.
Having pondered this for a while, I'm leaning towards @Taneb 's position more than @JacquesCarette 's.
|
Monus |
| ∣m-n∣≤m⊔n (suc m) zero = ≤-refl | ||
| ∣m-n∣≤m⊔n (suc m) (suc n) = m≤n⇒m≤1+n (∣m-n∣≤m⊔n m n) | ||
|
|
||
| ∣m-n∣≡m⊔n∸m⊓n : ∀ m n → ∣ m - n ∣ ≡ m ⊔ n ∸ m ⊓ n |
There was a problem hiding this comment.
The structure of this proof recalls that of ∣m-n∣≡[m∸n]∨[n∸m] (L1863).
Is there a refactoring which allows you to prove each result from some other, more general lemma?
Separately, you might like to consider refactoring this proof to not use with, but (more) simply via [ branch1 , branch2 ]′ $ ≤-total m n for suitable subproofs branch1, branch2, should you ever need to reason about this operation. cf. 'with (sometimes) considered harmful' #2123
There was a problem hiding this comment.
The structure of this proof recalls that of
∣m-n∣≡[m∸n]∨[n∸m](L1863).
Is there a refactoring which allows you to prove each result from some other, more general lemma?
Is this actual question or more like a teacher question where you know there is and you probing me to look for it? I'm asking as I can't really find it.
I could rewrite it where instead of ≤-total I would match on the result of ∣m-n∣≡m⊔n∸m⊓n but that would only handle lhs, for rhs I would still need to recover the m≤n and n≤m from the result using ∣m-n∣≡m∸n⇒n≤m and ∣m-n∣≡n∸m⇒m≤n*
*) seems this one is missing, let me add it here
There was a problem hiding this comment.
@jkopanski Thanks!
While it possible that I do indeed ask questions in a 'teacher-like' style (as friends and colleagues often point out to me... you can't easily take the teacher out of me ;-)), here I must say that my question was one of curiosity!
I think that there is a general principle for stdlib that we try not to 'over-duplicate' or generate (too much) additional redundancy between lemmas. Here I could see that there is a 'similar' result, so I was hoping there might be a way to exploit the similarity. But if not, then not!
And if there is, then we can always refactor downstream... ;-)
UPDATED: happy to leave this for later, but perhaps this could be refactored using Relation.Binary.Consequences.wlog...
There was a problem hiding this comment.
Something to think about for another day: to try to characterise what's going on here in terms of ∣ m - n ∣ as a symmetric difference operator, and any possible candidate IsBoolean(Semi)Ring structure on Nat...?
JacquesCarette
left a comment
There was a problem hiding this comment.
I'm fine with adding these. We can have later passes of simplification of proofs.
| ------------------------------------------------------------------------ | ||
| -- Properties of _∸_ and _⊓_ and _⊔_ | ||
|
|
||
| m∸n≤m⊔n : ∀ m n → m ∸ n ≤ m ⊔ n |
There was a problem hiding this comment.
I'm okay - lets one do proofs at a higher level with fewer steps.
|
@jkopanski Shall we take this out of draft and try to get it in shape to merge? Or do you still want time to work on it further? |
Some stuff that I've needed. I have no idea if those belong here in stdlib. I don't know if I've put those in the right place, or named them properly. Hence the draft and lack of changlog entry.
yes, I would like to get it going. I've rebased it on recent changes and added changlog entry. There's the case of I've only now noticed your update regarding |
No, as @JacquesCarette observes, we can handle that as a downstream refactoring. And |
| m∸n+o≡m∸[n∸o] : ∀ {m n o} → n ≤ m → o ≤ n → (m ∸ n) + o ≡ m ∸ (n ∸ o) | ||
| m∸n+o≡m∸[n∸o] {m} {zero} {zero} z≤n _ = +-identityʳ m | ||
| m∸n+o≡m∸[n∸o] {suc m} {suc n} {zero} (s≤s n≤m) z≤n = +-identityʳ (m ∸ n) | ||
| m∸n+o≡m∸[n∸o] {suc m} {suc n} {suc o} (s≤s n≤m) (s≤s o≤n) = begin-equality | ||
| suc m ∸ suc n + suc o ≡⟨ +-suc (m ∸ n) o ⟩ | ||
| suc (m ∸ n + o) ≡⟨ cong suc (m∸n+o≡m∸[n∸o] n≤m o≤n) ⟩ | ||
| suc (m ∸ (n ∸ o)) ≡⟨ ∸-suc (≤-trans (m∸n≤m n o) n≤m) ⟨ | ||
| suc m ∸ (n ∸ o) ∎ |
There was a problem hiding this comment.
So... noting that it took me a long time to internalise this idiom, stdlib design tends to favour:
- making at least
mandnexplicit (because not directly inferrable from_∸ _), as in the lemma immediately following this one, but probably alsooas well, for the same reason - making arguments of (proof-irrelevant) propositions
n ≤ mando ≤ ndefinitionally irrelevant where possible
So, here:
| m∸n+o≡m∸[n∸o] : ∀ {m n o} → n ≤ m → o ≤ n → (m ∸ n) + o ≡ m ∸ (n ∸ o) | |
| m∸n+o≡m∸[n∸o] {m} {zero} {zero} z≤n _ = +-identityʳ m | |
| m∸n+o≡m∸[n∸o] {suc m} {suc n} {zero} (s≤s n≤m) z≤n = +-identityʳ (m ∸ n) | |
| m∸n+o≡m∸[n∸o] {suc m} {suc n} {suc o} (s≤s n≤m) (s≤s o≤n) = begin-equality | |
| suc m ∸ suc n + suc o ≡⟨ +-suc (m ∸ n) o ⟩ | |
| suc (m ∸ n + o) ≡⟨ cong suc (m∸n+o≡m∸[n∸o] n≤m o≤n) ⟩ | |
| suc (m ∸ (n ∸ o)) ≡⟨ ∸-suc (≤-trans (m∸n≤m n o) n≤m) ⟨ | |
| suc m ∸ (n ∸ o) ∎ | |
| m∸n+o≡m∸[n∸o] : ∀ m n o → n ≤ m → .(o ≤ n) → (m ∸ n) + o ≡ m ∸ (n ∸ o) | |
| m∸n+o≡m∸[n∸o] m zero zero _ _ = +-identityʳ m | |
| m∸n+o≡m∸[n∸o] (suc m) (suc n) zero sn≤sm _ = +-identityʳ (m ∸ n) | |
| m∸n+o≡m∸[n∸o] (suc m) (suc n) (suc o) sn≤sm so≤sn = begin-equality | |
| suc m ∸ suc n + suc o ≡⟨ +-suc (m ∸ n) o ⟩ | |
| suc (m ∸ n + o) ≡⟨ cong suc (m∸n+o≡m∸[n∸o] m n o (s≤s⁻¹ sn≤sm) (s≤s⁻¹ so≤sn)) ⟩ | |
| suc (m ∸ (n ∸ o)) ≡⟨ ∸-suc (≤-trans (m∸n≤m n o) (s≤s⁻¹ sn≤sm)) ⟨ | |
| suc m ∸ (n ∸ o) ∎ |
And in fact, n ≤ m can also be made irrelevant, after refactoring lemma ∸-suc...
There was a problem hiding this comment.
making at least m and n explicit (because not directly inferrable from _∸ _)
Oh I thought the m n o were inferred from the inequalities passed.
as in the lemma immediately following this one
indeed that seems to be the case in the m≤n+o⇒m∸n≤o, but the lemmas directly above: +-∸-assoc, ∸-+-assoc and +-∸-comm seems to follow the convention I mentioned: variables that are used in the inequalities are implicit, explicit ones are only the ones that aren't used in any arguments to the lemma.
Does making arguments proof irrelevant changes anything with that regard?
There was a problem hiding this comment.
D'oh, yes, you're quite correct, each of m, n, and o, is inferrable from the hypotheses. Apologies!
There was a problem hiding this comment.
But... see also #2790 : if you have an irrelevant (relation) argument, and the values on which it depends are implicit, sometimes Agda can't quite figure them out during inference when used, rather than defined. Puzzling...
|
@MatthewDaggitt are you happy that your review requests have been answered satisfactorily? |
Some stuff that I've needed. I have no idea if those belong here in stdlib. I don't know if I've put those in the right place, or named them properly. Hence the draft and lack of changlog entry.