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 2
byfoo 0
orfoo 1
works (i.e.,simp only [foo]
resolves thematch
). - Replacing
ZMod 4
byFin 4
in the definition offoo
also works. dsimp
does 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
foo
with 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