Zulip Chat Archive
Stream: general
Topic: simp messes up names
Patrick Massot (Mar 18 2019 at 22:05):
In
import logic.basic example (P : ℕ → Prop) (h : ¬ ∃ n, P n) : ¬ P 0 := begin simp only [not_exists] at h, exact h 0 end
The goal after the simp line is ∀ (x : ℕ), ¬P x
, whereas I'm expecting ∀ (n : ℕ), ¬P n
. Is there any way to prevent simp from messing up names like this? In a more complicated proof it becomes very confusing for students
Patrick Massot (Mar 18 2019 at 22:06):
I'm blaming simp
but rw
does the same
Patrick Massot (Mar 18 2019 at 22:09):
Is it possible to write a tactic that fixes the names after invoking simp only [not_exists]
or simp only [not_forall]
? It looks non trivial because the structure of the expr
is not the same, but it still sounds feasible by de Bruijn indices gurus.
Simon Hudon (Mar 18 2019 at 22:12):
I think simp
and rw
use the same names used in the lemma. In your situation, there seems to be a different obviously correct behavior but if you look at a lemma like (∀ a, _) ∧ (∀ b, _) ↔ (∀ c, _) ∨ (∀ d, _) ∨ (∀ e, _)
, it's not obvious what names to use after rewrite
Patrick Massot (Mar 18 2019 at 22:14):
I understand why there is no good general solution. I'm looking for a solution specific to these not_*
lemmas (including not_le
and not_lt
) where a tactic both calls simp only
and fixes names
Simon Hudon (Mar 18 2019 at 22:27):
Now that I think of it, I may have an idea on how to do it in general. I'm not overly enthusiastic about doing it for specific lemmas because when the wheels fall off, people get even more confused.
Kevin Buzzard (Mar 18 2019 at 22:53):
I guess you could always teach the students that ∀ (x : ℕ), ¬P x
and ∀ (n : ℕ), ¬P n
are syntactically equal...
Chris Hughes (Mar 18 2019 at 23:42):
Is it really that confusing?
Mario Carneiro (Mar 18 2019 at 23:43):
I think it's best to just not worry about the names of binders that are not open. Lean control over this is limited
Mario Carneiro (Mar 18 2019 at 23:44):
you can always name it when you use it in intros
or anything else that actually puts a name in your context
Mario Carneiro (Mar 18 2019 at 23:45):
(incidentally, Metamath has great support for this - since the variables are named the same in the original lemma, they get renamed in tandem when you apply the theorem)
Patrick Massot (Mar 25 2019 at 20:33):
Since nobody else seemed interested, I wrote a tactic doing that at https://gist.github.com/PatrickMassot/58b2c3e557e7010db0fb8ab5057dfd47 (you can put that file in mathlib or any project using it). Remember the goal is to push negations through quantifiers and logical connective without renaming variables. This tactic is based on @Jeremy Avigad 's finish
code, and help from Simon who told me about eta-reduction messing up with my Exists
. The two test cases at the end show the tactic in action. The first one goes from
h : ∃ (p : ℕ), ¬∀ (n : ℕ), n > p, h' : ∃ (p : ℕ), ¬∃ (n : ℕ), n < p ⊢ ¬∀ (n : ℕ), n = 0
to
h : ∃ (p n : ℕ), n ≤ p, h' : ∃ (p : ℕ), ∀ (n : ℕ), p ≤ n ⊢ ∃ (n : ℕ), n ≠ 0
The second transforms
h : ¬∀ (ε : ℤ), ε > 0 → (∃ (N : ℕ), ∀ (n : ℕ), n ≥ N → |a n - l| < ε)
into
h : ∃ (ε : ℤ), ε > 0 ∧ ∀ (N : ℕ), ∃ (n : ℕ), n ≥ N ∧ ε ≤ |a n - l|
(I used integers instead of real numbers to avoid importing real numbers)
Patrick Massot (Mar 25 2019 at 20:34):
I'm inordinately proud of this tactic. I think it's really relevant to teaching, but actually I also think it should be in mathlib
Patrick Massot (Mar 26 2019 at 21:15):
https://github.com/leanprover-community/mathlib/pull/853
Last updated: Dec 20 2023 at 11:08 UTC