Zulip Chat Archive
Stream: lean4
Topic: Why can simp prove '0 = Nat.zero', but not '0 = MyNat.zero'?
Adam Dingle (Jan 30 2024 at 10:06):
I'm using Lean 4.5.0-rc1.
simp can prove 0 = Nat.zero
, in fact without using any identities at all:
example : 0 = Nat.zero := by simp only []
However now let's try it with my own definition MyNat of natural numbers:
inductive MyNat where
| zero
| succ : MyNat → MyNat
deriving Repr
open MyNat (zero succ)
instance : OfNat MyNat 0 where
ofNat := zero
example : 0 = MyNat.zero := by simp only []
I get
simp made no progress
Why is this?
This may seem like a technicality, but actually it makes proving some theorems less convenient. Consider this example from the chapter "Inductive Types" in "Theorem Proving in Lean 4":
theorem zero_add (n : Nat) : 0 + n = n := by
induction n <;> simp [*, add_zero, add_succ]
It works with the builtin Nat type, but fails with MyNat, precisely because simp can't resolve the base case which is similar to 0 = Nat.zero
.
Damiano Testa (Jan 30 2024 at 10:16):
Does it work if you add an instance : Zero MyNat
instead?
Adam Dingle (Jan 30 2024 at 12:34):
OK, I just tried that:
instance : Zero MyNat where
zero := zero
The result is the same: "simp made no progress". (Actually I would have slightly surprised if this made a difference, since Zero is in MathLib and simp is outside it.)
Matthew Ballard (Jan 30 2024 at 12:38):
set_option trace.Meta.Tactic.simp true in
before your declaration will tell what simp
is thinking
Adam Dingle (Jan 30 2024 at 13:05):
Matthew Ballard said:
set_option trace.Meta.Tactic.simp true in
before your declaration will tell whatsimp
is thinking
That's a useful hint. I just enabled this option. When simp proves that 0 = Nat.zero
, it reports
[Meta.Tactic.simp.rewrite] @eq_self:1000, 0 = Nat.zero ==> True
I'm a bit surprised that it's using eq_self, since I thought that the only
option tells it to use no identities at all, but perhaps eq_self is special.
When it fails to prove that 0 = MyNat.zero
, it reports
[Meta.Tactic.simp.unify] @eq_self:1000, failed to unify
?a = ?a
with
0 = MyNat.zero
Eric Rodriguez (Jan 30 2024 at 13:16):
I do think Nat
has quite a lot of specific support written into the Lean tooling
Damiano Testa (Jan 30 2024 at 14:30):
Also, simp only
really means that you ask simp
to only use the simpOnlyBuiltins
:
import Lean.Elab.Tactic.Simp
#eval Lean.Elab.Tactic.simpOnlyBuiltins
-- [`eq_self, `iff_self]
Adam Dingle (Jan 30 2024 at 14:54):
Damiano Testa said:
Also,
simp only
really means that you asksimp
to only use thesimpOnlyBuiltins
Aha. Thanks, that's helpful.
Last updated: May 02 2025 at 03:31 UTC