Zulip Chat Archive
Stream: lean4
Topic: 'simp'lifying 'match' expressions
Michael Stoll (Jun 10 2024 at 19:51):
Consider
import Mathlib.Data.ZMod.Defs
def foo (a : ZMod 4) : Nat :=
match a with
| 0 | 2 => 37
| 1 => 389
| 3 => 5077
example : ∃ n : Nat, foo 2 = n := by
simp only [foo]
/- ⊢ ∃ n,
(match 2 with
| 0 => 37
| 2 => 37
| 1 => 389
| 3 => 5077) =
n
-/
sorry
How can I get the (match 2 with ...) simplified to 37? (They are defeq, so change ∃ n,37 = n would work, but I'd like to get this automatically.)
Note:
- Replacing
foo 2byfoo 0orfoo 1works (i.e.,simp only [foo]resolves thematch). - Replacing
ZMod 4byFin 4in the definition offooalso works. dsimpdoes not work.
Of course, one could add simp lemmas lemma foo_two : foo 2 = 37 := rfl etc., but when 4 is a bit larger, that gets tedious...
Michael Stoll (Jun 12 2024 at 12:50):
Any ideas?
Damiano Testa (Jun 12 2024 at 12:53):
On the webserver, simp only [foo, exists_eq'] works: is this not suitable?
Damiano Testa (Jun 12 2024 at 12:54):
Or do you want simp to stop before closing the goal?
Michael Stoll (Jun 12 2024 at 12:55):
This is cheating and an artifact of the MWE :smile:
Maybe this is better:
import Mathlib.Data.ZMod.Defs
def foo (a : ZMod 4) : Nat :=
match a with
| 0 | 2 => 37
| 1 => 389
| 3 => 5077
example : foo 2 = 95 := by
simp [foo]
sorry
The point is that simp does not resolve the match (when the argument is at least 2).
Damiano Testa (Jun 12 2024 at 12:57):
example [Nat.AtLeastTwo 2] : foo 2 = 95 := by
simp [foo]
?
EDIT: this looked correct, but it was probably due to some cached state.
Michael Stoll (Jun 12 2024 at 12:58):
This still doesn't resolve the match.
Adam Topaz (Jun 12 2024 at 13:16):
Does split split the match?
Michael Stoll (Jun 12 2024 at 13:17):
example : foo 2 = 95 := by
simp [foo]
split
all_goals try tauto
sorry
works, but seems a bit clumsy. ( split leaves four goals.)
Adam Topaz (Jun 12 2024 at 13:18):
Yeah I agree. What if you tag foo with simp?
Damiano Testa (Jun 12 2024 at 13:18):
split is also what aesop uses.
Michael Stoll (Jun 12 2024 at 13:19):
Adam Topaz said:
Yeah I agree. What if you tag
foowith simp?
That does not seem to change anything (except that I don't have to give foo explicitly to simp).
Michael Stoll (Jun 12 2024 at 13:34):
I would say resolving match expressions may look like something a simproc could do.
In any case, I find it a bit strange that simp only [foo] does work when foo is defined as Fin 4 → Nat.
Shreyas Srinivas (Jun 12 2024 at 13:50):
I know why. ZMod is a def
Shreyas Srinivas (Jun 12 2024 at 13:50):
See this. I just redefined ZMod as it is in mathlib except it is now reducible:
import Mathlib.Data.ZMod.Defs
namespace Play
abbrev ZMod : ℕ → Type
| 0 => ℤ
| n + 1 => Fin (n + 1)
abbrev foo (a : ZMod 4) : Nat :=
match a with
| 0 | 2 => 37
| 1 => 389
| 3 => 5077
example : ∃ n : Nat, foo 2 = n := by
simp only [foo]
done
/- ⊢ ∃ n,37 =n
-/
end Play
Michael Stoll (Jun 12 2024 at 13:56):
But simp [foo, ZMod] does not work either...
Adam Topaz (Jun 12 2024 at 13:57):
Does it work if you use Fin instead of Zmod?
Michael Stoll (Jun 12 2024 at 13:57):
Yes, as already mentioned.
Adam Topaz (Jun 12 2024 at 13:59):
Sorry, I’m on mobile so I missed it
Adam Topaz (Jun 12 2024 at 14:04):
You can also use change foo (a : Fin _) = _ before the simp and it should (hopefully!) work
Shreyas Srinivas (Jun 12 2024 at 14:04):
simp has no occurrences of ZMod to rewrite I suppose
Shreyas Srinivas (Jun 12 2024 at 14:04):
(deleted)
Shreyas Srinivas (Jun 12 2024 at 14:07):
That was not the case. Once the def of foo was unfolded, even if you had changed 2's type to Fin, it gets rewritten as ZMod.
Matthew Ballard (Jun 12 2024 at 15:47):
Add
instance ZMod.instOfNat: ∀ n m : ℕ, OfNat (ZMod n) m
| 0, m => inferInstanceAs (OfNat ℤ m)
| n + 1, m => inferInstanceAs (OfNat (Fin (n + 1)) m)
to L105 of file#Data/ZMod/Defs
Michael Stoll (Jun 12 2024 at 15:48):
OK, let me make a PR...
Matthew Ballard (Jun 12 2024 at 15:51):
I didn't check the resulting diamond though
Michael Stoll (Jun 12 2024 at 15:51):
I'll see how it goes.
Michael Stoll (Jun 12 2024 at 17:38):
This runs into problems:
import Mathlib.Data.ZMod.Defs
instance ZMod.instOfNat (n m : ℕ) [Nat.AtLeastTwo m] : OfNat (ZMod n) m := inferInstance
shows that there is (of course) another OfNat instance on ZMod n, and having both makes (perhaps among other problems) ring/ring_nf stop working on ZMod n. (And of course it violates the principle that instances should be "morally unique".) But this other instance (which comes from docs#instOfNatAtLeastTwo) does not help with reducing the match.
Eric Wieser (Jun 13 2024 at 01:37):
Matthew Ballard said:
Add
instance ZMod.instOfNat: ∀ n m : ℕ, OfNat (ZMod n) m | 0, m => inferInstanceAs (OfNat ℤ m) | n + 1, m => inferInstanceAs (OfNat (Fin (n + 1)) m)to L105 of file#Data/ZMod/Defs
m should not be part of the match here
Kevin Buzzard (Jun 14 2024 at 10:39):
0 should map to 11, right?
Last updated: May 02 2025 at 03:31 UTC