Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a6d9c65

Browse files
committed
feat(category_theory/extensive): Define extensive categories (#17318)
Co-authored-by: Andrew Yang <36414270+erdOne@users.noreply.github.com>
1 parent 64444a2 commit a6d9c65

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed

docs/references.bib

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,21 @@ @Book{ calugareanu
404404
doi = {10.1007/978-94-015-9588-9}
405405
}
406406

407+
@Article{ CARBONI1993145,
408+
author = {Aurelio Carboni and Stephen Lack and R.F.C. Walters},
409+
doi = {https://doi.org/10.1016/0022-4049(93)90035-R},
410+
issn = {0022-4049},
411+
journal = {Journal of Pure and Applied Algebra},
412+
number = {2},
413+
pages = {145-158},
414+
title = {Introduction to extensive and distributive categories},
415+
url = {https://www.sciencedirect.com/science/article/pii/002240499390035R},
416+
volume = {84},
417+
year = {1993},
418+
bdsk-url-1 = {https://www.sciencedirect.com/science/article/pii/002240499390035R},
419+
bdsk-url-2 = {https://doi.org/10.1016/0022-4049(93)90035-R}
420+
}
421+
407422
@Article{ carneiro2015arithmetic,
408423
title = {Arithmetic in Metamath, Case Study: Bertrand's Postulate},
409424
author = {Carneiro, Mario},

src/category_theory/extensive.lean

Lines changed: 338 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,338 @@
1+
/-
2+
Copyright (c) 2022 Andrew Yang. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Andrew Yang
5+
-/
6+
import category_theory.limits.shapes.comm_sq
7+
import category_theory.limits.shapes.strict_initial
8+
import category_theory.limits.shapes.types
9+
import topology.category.Top.limits
10+
11+
/-!
12+
13+
# Extensive categories
14+
15+
## Main definitions
16+
- `category_theory.is_van_kampen_colimit`: A (colimit) cocone over a diagram `F : J ⥤ C` is van
17+
Kampen if for every cocone `c'` over the pullback of the diagram `F' : J ⥤ C'`,
18+
`c'` is colimiting iff `c'` is the pullback of `c`.
19+
- `category_theory.finitary_extensive`: A category is (finitary) extensive if it has finite
20+
coproducts, and binary coproducts are van Kampen.
21+
22+
## Main Results
23+
- `category_theory.has_strict_initial_objects_of_finitary_extensive`: The initial object
24+
in extensive categories is strict.
25+
- `category_theory.finitary_extensive.mono_inr_of_is_colimit`: Coproduct injections are monic in
26+
extensive categories.
27+
- `category_theory.binary_cofan.is_pullback_initial_to_of_is_van_kampen`: In extensive categories,
28+
sums are disjoint, i.e. the pullback of `X ⟶ X ⨿ Y` and `Y ⟶ X ⨿ Y` is the initial object.
29+
- `category_theory.types.finitary_extensive`: The category of types is extensive.
30+
31+
## TODO
32+
33+
Show that the following are finitary extensive:
34+
- `Top`
35+
- functor categories into extensive categories
36+
- the categories of sheaves over a site
37+
- `Scheme`
38+
- `AffineScheme` (`CommRingᵒᵖ`)
39+
40+
## References
41+
- https://ncatlab.org/nlab/show/extensive+category
42+
- [Carboni et al, Introduction to extensive and distributive categories][CARBONI1993145]
43+
44+
-/
45+
46+
open category_theory.limits
47+
48+
namespace category_theory
49+
50+
universes v' u' v u
51+
52+
variables {J : Type v'} [category.{u'} J] {C : Type u} [category.{v} C]
53+
54+
/-- A natural transformation is equifibered if every commutative square of the following form is
55+
a pullback.
56+
```
57+
F(X) → F(Y)
58+
↓ ↓
59+
G(X) → G(Y)
60+
```
61+
-/
62+
def nat_trans.equifibered {F G : J ⥤ C} (α : F ⟶ G) : Prop :=
63+
∀ ⦃i j : J⦄ (f : i ⟶ j), is_pullback (F.map f) (α.app i) (α.app j) (G.map f)
64+
65+
lemma nat_trans.equifibered_of_is_iso {F G : J ⥤ C} (α : F ⟶ G) [is_iso α] : α.equifibered :=
66+
λ _ _ f, is_pullback.of_vert_is_iso ⟨nat_trans.naturality _ f⟩
67+
68+
lemma nat_trans.equifibered.comp {F G H : J ⥤ C} {α : F ⟶ G} {β : G ⟶ H}
69+
(hα : α.equifibered) (hβ : β.equifibered) : (α ≫ β).equifibered :=
70+
λ i j f, (hα f).paste_vert (hβ f)
71+
72+
/-- A (colimit) cocone over a diagram `F : J ⥤ C` is universal if it is stable under pullbacks. -/
73+
def is_universal_colimit {F : J ⥤ C} (c : cocone F) : Prop :=
74+
∀ ⦃F' : J ⥤ C⦄ (c' : cocone F') (α : F' ⟶ F) (f : c'.X ⟶ c.X)
75+
(h : α ≫ c.ι = c'.ι ≫ (functor.const J).map f) (hα : α.equifibered),
76+
(∀ j : J, is_pullback (c'.ι.app j) (α.app j) f (c.ι.app j)) → nonempty (is_colimit c')
77+
78+
/-- A (colimit) cocone over a diagram `F : J ⥤ C` is van Kampen if for every cocone `c'` over the
79+
pullback of the diagram `F' : J ⥤ C'`, `c'` is colimiting iff `c'` is the pullback of `c`.
80+
81+
TODO: Show that this is iff the functor `C ⥤ Catᵒᵖ` sending `x` to `C/x` preserves it.
82+
TODO: Show that this is iff the inclusion functor `C ⥤ Span(C)` preserves it.
83+
-/
84+
def is_van_kampen_colimit {F : J ⥤ C} (c : cocone F) : Prop :=
85+
∀ ⦃F' : J ⥤ C⦄ (c' : cocone F') (α : F' ⟶ F) (f : c'.X ⟶ c.X)
86+
(h : α ≫ c.ι = c'.ι ≫ (functor.const J).map f) (hα : α.equifibered),
87+
nonempty (is_colimit c') ↔ ∀ j : J, is_pullback (c'.ι.app j) (α.app j) f (c.ι.app j)
88+
89+
lemma is_van_kampen_colimit.is_universal {F : J ⥤ C} {c : cocone F} (H : is_van_kampen_colimit c) :
90+
is_universal_colimit c :=
91+
λ _ c' α f h hα, (H c' α f h hα).mpr
92+
93+
/-- A van Kampen colimit is a colimit. -/
94+
noncomputable
95+
def is_van_kampen_colimit.is_colimit {F : J ⥤ C} {c : cocone F} (h : is_van_kampen_colimit c) :
96+
is_colimit c :=
97+
begin
98+
refine ((h c (𝟙 F) (𝟙 c.X : _) (by rw [functor.map_id, category.comp_id, category.id_comp])
99+
(nat_trans.equifibered_of_is_iso _)).mpr $ λ j, _).some,
100+
haveI : is_iso (𝟙 c.X) := infer_instance,
101+
exact is_pullback.of_vert_is_iso ⟨by erw [nat_trans.id_app, category.comp_id, category.id_comp]⟩,
102+
end
103+
104+
lemma is_initial.is_van_kampen_colimit [has_strict_initial_objects C] {X : C} (h : is_initial X) :
105+
is_van_kampen_colimit (as_empty_cocone X) :=
106+
begin
107+
intros F' c' α f hf hα,
108+
have : F' = functor.empty C := by apply functor.hext; rintro ⟨⟨⟩⟩,
109+
subst this,
110+
haveI := h.is_iso_to f,
111+
refine ⟨by rintro _ ⟨⟨⟩⟩, λ _,
112+
⟨is_colimit.of_iso_colimit h (cocones.ext (as_iso f).symm $ by rintro ⟨⟨⟩⟩)⟩⟩
113+
end
114+
115+
section extensive
116+
117+
variables {X Y : C}
118+
119+
/--
120+
A category is (finitary) extensive if it has finite coproducts,
121+
and binary coproducts are van Kampen.
122+
123+
TODO: Show that this is iff all finite coproducts are van Kampen. -/
124+
class finitary_extensive (C : Type u) [category.{v} C] : Prop :=
125+
[has_finite_coproducts : has_finite_coproducts C]
126+
(van_kampen' : ∀ {X Y : C} (c : binary_cofan X Y), is_colimit c → is_van_kampen_colimit c)
127+
128+
attribute [priority 100, instance] finitary_extensive.has_finite_coproducts
129+
130+
lemma finitary_extensive.van_kampen [finitary_extensive C] {F : discrete walking_pair ⥤ C}
131+
(c : cocone F) (hc : is_colimit c) : is_van_kampen_colimit c :=
132+
begin
133+
let X := F.obj ⟨walking_pair.left⟩, let Y := F.obj ⟨walking_pair.right⟩,
134+
have : F = pair X Y,
135+
{ apply functor.hext, { rintros ⟨⟨⟩⟩; refl }, { rintros ⟨⟨⟩⟩ ⟨j⟩ ⟨⟨rfl : _ = j⟩⟩; simpa } },
136+
clear_value X Y, subst this,
137+
exact finitary_extensive.van_kampen' c hc
138+
end
139+
140+
lemma map_pair_equifibered {F F' : discrete walking_pair ⥤ C} (α : F ⟶ F') : α.equifibered :=
141+
begin
142+
rintros ⟨⟨⟩⟩ ⟨j⟩ ⟨⟨rfl : _ = j⟩⟩,
143+
all_goals { dsimp, simp only [discrete.functor_map_id],
144+
exact is_pullback.of_horiz_is_iso ⟨by simp only [category.comp_id, category.id_comp]⟩ }
145+
end
146+
147+
lemma binary_cofan.is_van_kampen_iff (c : binary_cofan X Y) :
148+
is_van_kampen_colimit c ↔
149+
∀ {X' Y' : C} (c' : binary_cofan X' Y') (αX : X' ⟶ X) (αY : Y' ⟶ Y)
150+
(f : c'.X ⟶ c.X) (hαX : αX ≫ c.inl = c'.inl ≫ f) (hαY : αY ≫ c.inr = c'.inr ≫ f),
151+
nonempty (is_colimit c') ↔ is_pullback c'.inl αX f c.inl ∧ is_pullback c'.inr αY f c.inr :=
152+
begin
153+
split,
154+
{ introv H hαX hαY,
155+
rw H c' (map_pair αX αY) f (by ext ⟨⟨⟩⟩; dsimp; assumption) (map_pair_equifibered _),
156+
split, { intro H, exact ⟨H _, H _⟩ }, { rintros H ⟨⟨⟩⟩, exacts [H.1, H.2] } },
157+
{ introv H F' hα h,
158+
let X' := F'.obj ⟨walking_pair.left⟩, let Y' := F'.obj ⟨walking_pair.right⟩,
159+
have : F' = pair X' Y',
160+
{ apply functor.hext, { rintros ⟨⟨⟩⟩; refl }, { rintros ⟨⟨⟩⟩ ⟨j⟩ ⟨⟨rfl : _ = j⟩⟩; simpa } },
161+
clear_value X' Y', subst this, change binary_cofan X' Y' at c',
162+
rw H c' _ _ _ (nat_trans.congr_app hα ⟨walking_pair.left⟩)
163+
(nat_trans.congr_app hα ⟨walking_pair.right⟩),
164+
split, { rintros H ⟨⟨⟩⟩, exacts [H.1, H.2] }, { intro H, exact ⟨H _, H _⟩ } }
165+
end
166+
167+
lemma binary_cofan.is_van_kampen_mk {X Y : C} (c : binary_cofan X Y)
168+
(cofans : ∀ (X Y : C), binary_cofan X Y) (colimits : ∀ X Y, is_colimit (cofans X Y))
169+
(cones : ∀ {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z), pullback_cone f g)
170+
(limits : ∀ {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z), is_limit (cones f g))
171+
(h₁ : ∀ {X' Y' : C} (αX : X' ⟶ X) (αY : Y' ⟶ Y) (f : (cofans X' Y').X ⟶ c.X)
172+
(hαX : αX ≫ c.inl = (cofans X' Y').inl ≫ f) (hαY : αY ≫ c.inr = (cofans X' Y').inr ≫ f),
173+
is_pullback (cofans X' Y').inl αX f c.inl ∧ is_pullback (cofans X' Y').inr αY f c.inr)
174+
(h₂ : ∀ {Z : C} (f : Z ⟶ c.X),
175+
is_colimit (binary_cofan.mk (cones f c.inl).fst (cones f c.inr).fst)) :
176+
is_van_kampen_colimit c :=
177+
begin
178+
rw binary_cofan.is_van_kampen_iff,
179+
introv hX hY,
180+
split,
181+
{ rintros ⟨h⟩,
182+
let e := h.cocone_point_unique_up_to_iso (colimits _ _),
183+
obtain ⟨hl, hr⟩ := h₁ αX αY (e.inv ≫ f) (by simp [hX]) (by simp [hY]),
184+
split,
185+
{ rw [← category.id_comp αX, ← iso.hom_inv_id_assoc e f],
186+
have : c'.inl ≫ e.hom = 𝟙 X' ≫ (cofans X' Y').inl := by { dsimp, simp },
187+
haveI : is_iso (𝟙 X') := infer_instance,
188+
exact (is_pullback.of_vert_is_iso ⟨this⟩).paste_vert hl },
189+
{ rw [← category.id_comp αY, ← iso.hom_inv_id_assoc e f],
190+
have : c'.inr ≫ e.hom = 𝟙 Y' ≫ (cofans X' Y').inr := by { dsimp, simp },
191+
haveI : is_iso (𝟙 Y') := infer_instance,
192+
exact (is_pullback.of_vert_is_iso ⟨this⟩).paste_vert hr } },
193+
{ rintro ⟨H₁, H₂⟩,
194+
refine ⟨is_colimit.of_iso_colimit _ $ (iso_binary_cofan_mk _).symm⟩,
195+
let e₁ : X' ≅ _ := H₁.is_limit.cone_point_unique_up_to_iso (limits _ _),
196+
let e₂ : Y' ≅ _ := H₂.is_limit.cone_point_unique_up_to_iso (limits _ _),
197+
have he₁ : c'.inl = e₁.hom ≫ (cones f c.inl).fst := by simp,
198+
have he₂ : c'.inr = e₂.hom ≫ (cones f c.inr).fst := by simp,
199+
rw [he₁, he₂],
200+
apply binary_cofan.is_colimit_comp_right_iso (binary_cofan.mk _ _),
201+
apply binary_cofan.is_colimit_comp_left_iso (binary_cofan.mk _ _),
202+
exact h₂ f }
203+
end
204+
.
205+
lemma binary_cofan.mono_inr_of_is_van_kampen [has_initial C] {X Y : C} {c : binary_cofan X Y}
206+
(h : is_van_kampen_colimit c) : mono c.inr :=
207+
begin
208+
refine pullback_cone.mono_of_is_limit_mk_id_id _ (is_pullback.is_limit _),
209+
refine (h (binary_cofan.mk (initial.to Y) (𝟙 Y))
210+
(map_pair (initial.to X) (𝟙 Y)) c.inr _ (map_pair_equifibered _)).mp ⟨_⟩ ⟨walking_pair.right⟩,
211+
{ ext ⟨⟨⟩⟩; dsimp; simp },
212+
{ exact ((binary_cofan.is_colimit_iff_is_iso_inr initial_is_initial _).mpr
213+
(by { dsimp, apply_instance })).some }
214+
end
215+
216+
lemma finitary_extensive.mono_inr_of_is_colimit [finitary_extensive C]
217+
{c : binary_cofan X Y} (hc : is_colimit c) : mono c.inr :=
218+
binary_cofan.mono_inr_of_is_van_kampen (finitary_extensive.van_kampen c hc)
219+
220+
lemma finitary_extensive.mono_inl_of_is_colimit [finitary_extensive C]
221+
{c : binary_cofan X Y} (hc : is_colimit c) : mono c.inl :=
222+
finitary_extensive.mono_inr_of_is_colimit (binary_cofan.is_colimit_flip hc)
223+
224+
instance [finitary_extensive C] (X Y : C) : mono (coprod.inl : X ⟶ X ⨿ Y) :=
225+
(finitary_extensive.mono_inl_of_is_colimit (coprod_is_coprod X Y) : _)
226+
227+
instance [finitary_extensive C] (X Y : C) : mono (coprod.inr : Y ⟶ X ⨿ Y) :=
228+
(finitary_extensive.mono_inr_of_is_colimit (coprod_is_coprod X Y) : _)
229+
230+
lemma binary_cofan.is_pullback_initial_to_of_is_van_kampen [has_initial C]
231+
{c : binary_cofan X Y}
232+
(h : is_van_kampen_colimit c) : is_pullback (initial.to _) (initial.to _) c.inl c.inr :=
233+
begin
234+
refine ((h (binary_cofan.mk (initial.to Y) (𝟙 Y)) (map_pair (initial.to X) (𝟙 Y)) c.inr _
235+
(map_pair_equifibered _)).mp ⟨_⟩ ⟨walking_pair.left⟩).flip,
236+
{ ext ⟨⟨⟩⟩; dsimp; simp },
237+
{ exact ((binary_cofan.is_colimit_iff_is_iso_inr initial_is_initial _).mpr
238+
(by { dsimp, apply_instance })).some }
239+
end
240+
241+
lemma finitary_extensive.is_pullback_initial_to_binary_cofan [finitary_extensive C]
242+
{c : binary_cofan X Y} (hc : is_colimit c) :
243+
is_pullback (initial.to _) (initial.to _) c.inl c.inr :=
244+
binary_cofan.is_pullback_initial_to_of_is_van_kampen (finitary_extensive.van_kampen c hc)
245+
246+
lemma has_strict_initial_of_is_universal [has_initial C]
247+
(H : is_universal_colimit (binary_cofan.mk (𝟙 (⊥_ C)) (𝟙 (⊥_ C)))) :
248+
has_strict_initial_objects C :=
249+
has_strict_initial_objects_of_initial_is_strict
250+
begin
251+
intros A f,
252+
suffices : is_colimit (binary_cofan.mk (𝟙 A) (𝟙 A)),
253+
{ obtain ⟨l, h₁, h₂⟩ := limits.binary_cofan.is_colimit.desc' this (f ≫ initial.to A) (𝟙 A),
254+
rcases (category.id_comp _).symm.trans h₂ with rfl,
255+
exact ⟨⟨_, ((category.id_comp _).symm.trans h₁).symm, initial_is_initial.hom_ext _ _⟩⟩ },
256+
refine (H (binary_cofan.mk (𝟙 _) (𝟙 _)) (map_pair f f) f (by ext ⟨⟨⟩⟩; dsimp; simp)
257+
(map_pair_equifibered _) _).some,
258+
rintro ⟨⟨⟩⟩; dsimp;
259+
exact is_pullback.of_horiz_is_iso ⟨(category.id_comp _).trans (category.comp_id _).symm⟩
260+
end
261+
262+
@[priority 100]
263+
instance has_strict_initial_objects_of_finitary_extensive [finitary_extensive C] :
264+
has_strict_initial_objects C :=
265+
has_strict_initial_of_is_universal (finitary_extensive.van_kampen _
266+
((binary_cofan.is_colimit_iff_is_iso_inr initial_is_initial _).mpr
267+
(by { dsimp, apply_instance })).some).is_universal
268+
269+
lemma finitary_extensive_iff_of_is_terminal (C : Type u) [category.{v} C] [has_finite_coproducts C]
270+
(T : C) (HT : is_terminal T) (c₀ : binary_cofan T T) (hc₀ : is_colimit c₀) :
271+
finitary_extensive C ↔ is_van_kampen_colimit c₀ :=
272+
begin
273+
refine ⟨λ H, H.2 c₀ hc₀, λ H, _⟩,
274+
constructor,
275+
simp_rw binary_cofan.is_van_kampen_iff at H ⊢,
276+
intros X Y c hc X' Y' c' αX αY f hX hY,
277+
obtain ⟨d, hd, hd'⟩ := limits.binary_cofan.is_colimit.desc' hc
278+
(HT.from _ ≫ c₀.inl) (HT.from _ ≫ c₀.inr),
279+
rw H c' (αX ≫ HT.from _) (αY ≫ HT.from _) (f ≫ d)
280+
(by rw [← reassoc_of hX, hd, category.assoc])
281+
(by rw [← reassoc_of hY, hd', category.assoc]),
282+
obtain ⟨hl, hr⟩ := (H c (HT.from _) (HT.from _) d hd.symm hd'.symm).mp ⟨hc⟩,
283+
rw [hl.paste_vert_iff hX.symm, hr.paste_vert_iff hY.symm]
284+
end
285+
286+
instance types.finitary_extensive : finitary_extensive (Type u) :=
287+
begin
288+
rw [finitary_extensive_iff_of_is_terminal (Type u) punit types.is_terminal_punit _
289+
(types.binary_coproduct_colimit _ _)],
290+
apply binary_cofan.is_van_kampen_mk _ _ (λ X Y, types.binary_coproduct_colimit X Y) _
291+
(λ X Y Z f g, (limits.types.pullback_limit_cone f g).2),
292+
{ intros,
293+
split,
294+
{ refine ⟨⟨hαX.symm⟩, ⟨pullback_cone.is_limit_aux' _ _⟩⟩,
295+
intro s,
296+
have : ∀ x, ∃! y, s.fst x = sum.inl y,
297+
{ intro x,
298+
cases h : s.fst x,
299+
{ simp_rw sum.inl_injective.eq_iff, exact exists_unique_eq' },
300+
{ apply_fun f at h,
301+
cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαY val : _).symm } },
302+
delta exists_unique at this,
303+
choose l hl hl',
304+
exact ⟨l, (funext hl).symm, types.is_terminal_punit.hom_ext _ _,
305+
λ l' h₁ h₂, funext $ λ x, hl' x (l' x) (congr_fun h₁ x).symm⟩ },
306+
{ refine ⟨⟨hαY.symm⟩, ⟨pullback_cone.is_limit_aux' _ _⟩⟩,
307+
intro s, dsimp,
308+
have : ∀ x, ∃! y, s.fst x = sum.inr y,
309+
{ intro x,
310+
cases h : s.fst x,
311+
{ apply_fun f at h,
312+
cases ((congr_fun s.condition x).symm.trans h).trans (congr_fun hαX val : _).symm },
313+
{ simp_rw sum.inr_injective.eq_iff, exact exists_unique_eq' } },
314+
delta exists_unique at this,
315+
choose l hl hl',
316+
exact ⟨l, (funext hl).symm, types.is_terminal_punit.hom_ext _ _,
317+
λ l' h₁ h₂, funext $ λ x, hl' x (l' x) (congr_fun h₁ x).symm⟩ } },
318+
{ intros Z f,
319+
dsimp [limits.types.binary_coproduct_cocone],
320+
delta types.pullback_obj,
321+
have : ∀ x, f x = sum.inl punit.star ∨ f x = sum.inr punit.star,
322+
{ intro x, rcases f x with (⟨⟨⟩⟩|⟨⟨⟩⟩), exacts [or.inl rfl, or.inr rfl] },
323+
let eX : {p : Z × punit // f p.fst = sum.inl p.snd} ≃ {x : Z // f x = sum.inl punit.star } :=
324+
⟨λ p, ⟨p.1.1, by convert p.2⟩, λ x, ⟨⟨_, _⟩, x.2⟩, λ _, by ext; refl, λ _, by ext; refl⟩,
325+
let eY : {p : Z × punit // f p.fst = sum.inr p.snd} ≃ {x : Z // f x = sum.inr punit.star } :=
326+
⟨λ p, ⟨p.1.1, p.2.trans (congr_arg sum.inr $ subsingleton.elim _ _)⟩,
327+
λ x, ⟨⟨_, _⟩, x.2⟩, λ _, by ext; refl, λ _, by ext; refl⟩,
328+
fapply binary_cofan.is_colimit_mk,
329+
{ exact λ s x, dite _ (λ h, s.inl $ eX.symm ⟨x, h⟩)
330+
(λ h, s.inr $ eY.symm ⟨x, (this x).resolve_left h⟩) },
331+
{ intro s, ext ⟨⟨x, ⟨⟩⟩, _⟩, dsimp, split_ifs; refl },
332+
{ intro s, ext ⟨⟨x, ⟨⟩⟩, hx⟩, dsimp, split_ifs, { cases h.symm.trans hx }, { refl } },
333+
{ intros s m e₁ e₂, ext x, split_ifs, { rw ← e₁, refl }, { rw ← e₂, refl } } }
334+
end
335+
336+
end extensive
337+
338+
end category_theory

0 commit comments

Comments
 (0)