Zulip Chat Archive

Stream: lean4

Topic: simp and nat lits


François G. Dorais (Jul 02 2021 at 12:45):

I've been noticing some instances where simp occasionally fails to simplify 0+n to n such as here:

example (n : Nat) : 1 + n = Nat.succ n := by simp [Nat.succ_add] -- fails!

I found this unusual since Nat.zero_add is a simp lemma! I figured that this was because Nat.zero_add uses the notation 0 instead of Nat.zero, as illustrated by

example (n : Nat) : Nat.succ 0 + n = Nat.succ n := by simp [Nat.succ_add] -- works!

So I added this simp lemma:

@[simp] theorem Nat.zero_add' (n : Nat) : Nat.zero + n = n := Nat.zero_add n

Now everything works swimmingly but something about the original issue that still bothers me.

Although, Nat.zero_add only hooks on the notation 0, there is the simp lemma Nat.zero_Eq: Nat.zero = 0 to work around that. For example:

example (n : Nat) : Nat.zero + n = n := by simp only [Nat.zero_add, eqSelf] -- fails (expected)
example (n : Nat) : Nat.zero + n = n := by simp only [Nat.zero_add, Nat.zero_Eq, eqSelf] -- works (expected)

However, Nat.zero_Eq doesn't always trigger as expected as illustrated by these examples:

example (n : Nat) : Nat.succ 0 + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add, eqSelf] -- works (expected)
example (n : Nat) : Nat.succ Nat.zero + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add, eqSelf] -- fails (expected)
example (n : Nat) : Nat.succ Nat.zero + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add, Nat.zero_Eq, eqSelf] -- works (expected)
example (n : Nat) : 1 + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add, Nat.zero_Eq, eqSelf] -- fails (unexpected!)

So it seems that some intermediate form of zero is generated when unifying 1 with Nat.succ _ and that intermediate form doesn't trigger Nat.zero_Eq.

Interestingly, there are no issues at all when using Nat.zero_add' instead of Nat.zero_add (and Nat.zero_Eq is no longer needed anywhere).

example (n : Nat) : 0 + n = n := by simp only [Nat.zero_add', eqSelf] -- works!
example (n : Nat) : Nat.succ Nat.zero + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add', eqSelf] -- works!
example (n : Nat) : Nat.succ 0 + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add', eqSelf] -- works!
example (n : Nat) : 1 + n = Nat.succ n := by simp only [Nat.succ_add, Nat.zero_add', eqSelf] -- works!

What is really going on here?

François G. Dorais (Jul 02 2021 at 12:53):

PS: This also works like the above:

theorem Nat.zero_add' (n : Nat) : no_index 0 + n = n := Nat.zero_add n

François G. Dorais (Jul 02 2021 at 13:06):

Weirdly interesting...

attribute [-simp] Nat.zero_Eq
@[simp] theorem Nat.zero_eq : no_index 0 = 0 := rfl
example (n : Nat) : 1 + n = n.succ := by simp [Nat.succ_add] -- works!

François G. Dorais (Jul 08 2021 at 18:05):

Apparently the intermediate form is a raw nat literal which doesn't match Nat.zero nor 0. I submitted an issue.


Last updated: Dec 20 2023 at 11:08 UTC