Zulip Chat Archive
Stream: mathlib4
Topic: ext tactic intros too few variables
Eric Wieser (Mar 17 2023 at 19:37):
Some weirdness in !4#2960; this works:
import Mathlib.Tactic.Basic
variable (m : Type u) (n : Type u') (α : Type v)
@[ext] structure SMatrix : Type max u u' v := (elem : m → n → α)
-- works
example (m : Type u) (n : Type u') (α : Type v) (M N : SMatrix m n α)
(h : ∀ i j, M.elem i j = N.elem i j) : M = N :=
by
ext i j
exact h i j
but this doesn't
import Mathlib.Tactic.Basic
variable (m : Type u) (n : Type u') (α : Type v)
def Matrix : Type max u u' v := m → n → α
@[ext]
lemma Matrix.ext (M N : Matrix m n α)
(h : ∀ i j, M i j = N i j) : M = N :=
by
funext i j
exact h i j
-- doesn't work
example (m : Type u) (n : Type u') (α : Type v) (M N : Matrix m n α)
(h : ∀ i j, M i j = N i j) : M = N :=
by
ext i j -- `j` wasn't introd!
exact h i j
Eric Wieser (Mar 17 2023 at 19:38):
Presumably ext
is getting confused because Matrix
is defeq to the type of functions
Eric Wieser (Mar 17 2023 at 19:38):
But it feels like a bug, since even on functions it would intro both variable!
Jon Eugster (Mar 23 2023 at 13:42):
This is merely a hack, but it might illustrate well what's wrong with ext
: If you change the ext
-Lemma so that it only
introduces one variable then it works fine:
import Mathlib.Tactic.Basic
variable (m : Type u) (n : Type u') (α : Type v)
def Matrix : Type max u u' v := m → n → α
@[ext]
theorem Matrix.ext' (M N : Matrix m n α) (h : ∀ i, M i = N i) : M = N := by
funext i j
rw [h i]
-- does work!
example (m : Type u) (n : Type u') (α : Type v) (M N : Matrix m n α)
(h : ∀ i j, M i j = N i j) : M = N :=
by
ext i j -- now `j` is introduced as well
exact h i j
Jon Eugster (Mar 23 2023 at 13:42):
I think what's happening is the following:
- Using
Matrix.ext
the tactic turnsM = N
into∀ i j, M i j = N i j
- In
TryIntros
(see source, Std/Tactic/Ext.lean, l.116-119) in the case| p::ps =>
it only introduces the first variable and then tries to apply the nextext
-lemma to∀ j, M i j = N i j
which fails as that's not an equality. (note:p
is the first name andps
is the list of all further names,[j]
in this case.)
I'm not quite confident enough to fix this myself, but I'd hope with that any meta-programmer would be able to help :fingers_crossed:
Eric Wieser (Mar 23 2023 at 13:42):
I think it's more complicated than that, because it works fine above for SMatrix
, the structure
Eric Wieser (Mar 23 2023 at 13:43):
So it's something to do with the fact that Matrix
is being confused for a function type somewhere within ext
Jon Eugster (Mar 23 2023 at 13:58):
That is probably true. I still think the above might not quite be the expected behaviour of ext
. The following fails as well because the bad_ext_lemma
introducing two variables at once takes priority over the correct ext
-Lemma for functions:
import Mathlib.Tactic.Basic
@[ext 1001]
lemma bad_ext_lemma (f g : A → B → C) (h : ∀ i j, f i j = g i j) : f = g := by
ext i j
exact h i j
-- fails
example (f g : A → B → C) (h : ∀ i j, f i j = g i j) : f = g := by
ext i j -- fails to introduce `j` if priority of the `bad_ext_lemma` is `> 1000`.
exact h i j
-- works
example (f g : A → B → C) (h : ∀ i j, f i j = g i j) : f = g := by
ext -- but it works if the variables are not given names
exact h _ _
Jon Eugster (Mar 23 2023 at 14:30):
I realised my suggestion would be a quite simple change: std4#111 . We can discuss over there if it makes sense at all or not.
Eric Wieser (Mar 23 2023 at 14:57):
I think the isForall
test might be to blame
Eric Wieser (Mar 23 2023 at 14:57):
And that its misfiring on matrices
Eric Wieser (Mar 23 2023 at 14:58):
I'm not convinced that allowing custom ext lemmas on functions is really sensible
Last updated: Dec 20 2023 at 11:08 UTC