Zulip Chat Archive
Stream: mathlib4
Topic: ext issues
Kevin Buzzard (Apr 22 2023 at 16:01):
There are some (easily worked-around) issues with ext
in !4#3208 (port CategoryTheory.Limits.Presheaf
) and I thought I'd try and understand them rather than just pushing the PR through (which now compiles). Here's the first one:
-- lean 3
import category_theory.types
def foo (A B : Type) (f g : A ⟶ B) : f = g := begin
ext x, -- works
sorry -- `⊢ f x = g x`
end
#print foo -- it's `funext`
In Lean 4 this currently fails:
-- lean 4
import Mathlib.CategoryTheory.Types
example (A B : Type) (f g : A ⟶ B) : f = g := by
--ext x -- fails
funext x -- works
I don't really understand why it works in Lean 3 but not Lean 4. There seem to be no ext lemmas in category_theory.types
. Does Lean 3 see through more stuff than Lean 4 somehow? My instinct was to make an ext lemma for concrete_category
but actually this is not imported in the example. Should I just make an ext lemma for Type u
and dump it in the imported file?
Kyle Miller (Apr 22 2023 at 16:08):
Do you know if you can import Mathlib.CategoryTheory.ConcreteCategory.Basic
into that file? It looks like there's a relevant ext lemma.
Kyle Miller (Apr 22 2023 at 16:09):
Though perhaps it should have a specialized one for Type
still, because this isn't great:
Kyle Miller (Apr 22 2023 at 16:09):
-- lean 4
import Mathlib.CategoryTheory.Types
import Mathlib.CategoryTheory.ConcreteCategory.Basic
example (A B : Type) (f g : A ⟶ B) : f = g := by
ext x -- works
-- ⊢ (CategoryTheory.forget Type).map f x = (CategoryTheory.forget Type).map g x
Adam Topaz (Apr 22 2023 at 16:10):
There was a thread a while ago explaining the issue
Adam Topaz (Apr 22 2023 at 16:10):
I’ll try to dig it up when I get home
Kyle Miller (Apr 22 2023 at 16:13):
Something like this:
-- lean 4
import Mathlib.CategoryTheory.Types
import Mathlib.CategoryTheory.ConcreteCategory.Basic
@[ext 950]
theorem CategoryTheory.ConcreteCategory.type_hom_ext {X Y : Type v} (f g : X ⟶ Y)
(h : ∀ (x : X), f x = g x) : f = g := funext h
example (A B : Type) (f g : A ⟶ B) : f = g := by
ext x -- works
-- ⊢ f x = g x
Kyle Miller (Apr 22 2023 at 16:14):
Adam Topaz said:
There was a thread a while ago explaining the issue
I think it might be this one: https://leanprover.zulipchat.com/#narrow/stream/287929-mathlib4/topic/ext.20debugging/near/348821912
Adam Topaz (Apr 22 2023 at 16:16):
No there was one even before that (I think I initiated it)
Kevin Buzzard (Apr 22 2023 at 16:18):
The second issue is that Lean 3 ext
seems to unfold definitions if necessary, but Lean 4 doesn't. Here's an example:
-- lean 3
import tactic
constant X : Type
@[ext] lemma X.ext (a b : X) : a = b := sorry
example (a b : X) : a = b :=
begin
ext, --works fine
end
noncomputable def Y : Type := X
example (a b : Y) : a = b :=
begin
ext, -- also works fine!
end
The analogous code in Lean 4 doesn't work:
-- lean 4
import Mathlib.Tactic
opaque X : Type
@[ext] lemma X.ext (a b : X) : a = b := sorry
example (a b : X) : a = b := by
ext --works fine
noncomputable def Y : Type := X
example (a b : Y) : a = b := by
ext -- no applicable extensionality lemma found for `Y`
Kyle Miller (Apr 22 2023 at 16:20):
In that thread I linked to, Gabriel mentioned that the Lean 3 ext
tactic would try applying all ext lemmas as a last resort, which might be why the Lean 3 examples work here.
Kevin Buzzard (Apr 22 2023 at 16:20):
This is kind of a big call. We have
theorem extendAlongYoneda_obj (P : Cᵒᵖ ⥤ Type u₁) :
(extendAlongYoneda A).obj P = colimit ((CategoryOfElements.π P).leftOp ⋙ A) :=
rfl
and we have an ext
lemma for colimits, so I could obviously make the corresponding ext
lemma for (extendAlongYoneda A).obj P
but it might be better to have Lean 4 ext
doing the same thing as Lean 3.
Kevin Buzzard (Apr 22 2023 at 16:21):
Kyle Miller said:
In that thread I linked to, Gabriel mentioned that the Lean 3
ext
tactic would try applying all ext lemmas as a last resort, which might be why the Lean 3 examples work here.
Is there a reason that we don't want to do this in Lean 4? I mean, if we change the behaviour of the tactic then things are going to break, and are breaking.
Kevin Buzzard (Apr 22 2023 at 16:24):
In fact this explains a lot!
Kyle Miller (Apr 22 2023 at 16:25):
The old behavior seems really unpredictable to me. It depends on whatever random order the ext lemmas are defined in and what happens to unfold to what. There are probably things that are broken that are things that shouldn't have ever worked (though still some that arguably should).
There should be some way to tell ext
that it should unfold definitions while searching for ext
lemmas... In any case, this breakage/change in behavior is making us fix "bad exts".
Kevin Buzzard (Apr 22 2023 at 16:26):
Oh dear, the linked thread seems to indicate that making ext
try all the ext lemmas as a last resort is not an option any more. So should I just add the "missing" ext
lemmas?
Kyle Miller (Apr 22 2023 at 16:27):
That to me seems like the right thing to do
Kyle Miller (Apr 22 2023 at 16:29):
Maybe we could create an attribute to inherit ext lemmas from another definition, like maybe
@[exts] noncomputable def Y : Type := X
Kyle Miller (Apr 22 2023 at 16:31):
Anyway, I'm not sure what to call it, but this should definitely accompany hom_ext
:
@[ext 950]
theorem CategoryTheory.ConcreteCategory.type_hom_ext {X Y : Type v} (f g : X ⟶ Y)
(h : ∀ (x : X), f x = g x) : f = g := funext h
I don't know what ext
priority it should be either. I just chose that number to be above the priority for hom_ext
.
Adam Topaz (Apr 22 2023 at 16:44):
Another option is to add funext
to aesop_cat’s rule set (maybe scoped to concrete categories)
Adam Topaz (Apr 22 2023 at 16:50):
Actually I think the right solution is to make Homs in the category of types (and also in all the categories arising from bundled, like GroupCat
etc.) into a structure with a single field, similar to docs#category_theory.Sheaf.hom
Kevin Buzzard (Apr 22 2023 at 17:07):
!4#3593 adds the ext lemma for Type u
. This is part of what we need to unblock !4#3208 .
Last updated: Dec 20 2023 at 11:08 UTC