Skip to content

Commit 45f4483

Browse files
riccardobrascaScott Morrison
andcommitted
Port/Algebra.Category.Module.FilteredColimits (#4949)
Co-authored-by: Scott Morrison <scott.morrison@anu.edu.au>
1 parent 19ef206 commit 45f4483

File tree

4 files changed

+255
-22
lines changed

4 files changed

+255
-22
lines changed

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import Mathlib.Algebra.Category.ModuleCat.Basic
5252
import Mathlib.Algebra.Category.ModuleCat.Biproducts
5353
import Mathlib.Algebra.Category.ModuleCat.Colimits
5454
import Mathlib.Algebra.Category.ModuleCat.EpiMono
55+
import Mathlib.Algebra.Category.ModuleCat.FilteredColimits
5556
import Mathlib.Algebra.Category.ModuleCat.Images
5657
import Mathlib.Algebra.Category.ModuleCat.Kernels
5758
import Mathlib.Algebra.Category.ModuleCat.Limits

Mathlib/Algebra/Category/GroupCat/FilteredColimits.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ open MonCat.FilteredColimits (colimit_one_eq colimit_mul_mk_eq)
4747

4848
-- We use parameters here, mainly so we can have the abbreviations `G` and `G.mk` below, without
4949
-- passing around `F` all the time.
50-
variable {J : Type v}[SmallCategory J] [IsFiltered J] (F : J ⥤ GroupCat.{max v u})
50+
variable {J : Type v} [SmallCategory J] [IsFiltered J] (F : J ⥤ GroupCat.{max v u})
5151

5252
/-- The colimit of `F ⋙ forget₂ Group Mon` in the category `Mon`.
5353
In the following, we will show that this has the structure of a group.
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/-
2+
Copyright (c) 2021 Justus Springer. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Justus Springer
5+
6+
! This file was ported from Lean 3 source module algebra.category.Module.filtered_colimits
7+
! leanprover-community/mathlib commit 806bbb0132ba63b93d5edbe4789ea226f8329979
8+
! Please do not edit these lines, except to modify the commit id
9+
! if you have ported upstream changes.
10+
-/
11+
import Mathlib.Algebra.Category.GroupCat.FilteredColimits
12+
import Mathlib.Algebra.Category.ModuleCat.Basic
13+
14+
/-!
15+
# The forgetful functor from `R`-modules preserves filtered colimits.
16+
17+
Forgetful functors from algebraic categories usually don't preserve colimits. However, they tend
18+
to preserve _filtered_ colimits.
19+
20+
In this file, we start with a ring `R`, a small filtered category `J` and a functor
21+
`F : J ⥤ Module R`. We show that the colimit of `F ⋙ forget₂ (Module R) AddCommGroup`
22+
(in `AddCommGroup`) carries the structure of an `R`-module, thereby showing that the forgetful
23+
functor `forget₂ (Module R) AddCommGroup` preserves filtered colimits. In particular, this implies
24+
that `forget (Module R)` preserves filtered colimits.
25+
26+
-/
27+
28+
29+
universe v u
30+
31+
noncomputable section
32+
33+
open scoped Classical
34+
35+
open CategoryTheory CategoryTheory.Limits
36+
37+
-- avoid name collision with `_root_.max`.
38+
open CategoryTheory.IsFiltered renaming max → max'
39+
40+
open AddMonCat.FilteredColimits (colimit_zero_eq colimit_add_mk_eq)
41+
42+
namespace ModuleCat.FilteredColimits
43+
44+
section
45+
46+
variable {R : Type u} [Ring R] {J : Type v} [SmallCategory J] [IsFiltered J]
47+
48+
variable (F : J ⥤ ModuleCatMax.{v, u, u} R)
49+
50+
/-- The colimit of `F ⋙ forget₂ (Module R) AddCommGroup` in the category `AddCommGroup`.
51+
In the following, we will show that this has the structure of an `R`-module.
52+
-/
53+
abbrev M : AddCommGroupCat :=
54+
AddCommGroupCat.FilteredColimits.colimit.{v, u}
55+
(F ⋙ forget₂ (ModuleCat R) AddCommGroupCat.{max v u})
56+
set_option linter.uppercaseLean3 false in
57+
#align Module.filtered_colimits.M ModuleCat.FilteredColimits.M
58+
59+
/-- The canonical projection into the colimit, as a quotient type. -/
60+
abbrev M.mk : (Σ j, F.obj j) → M F :=
61+
Quot.mk (Types.Quot.Rel (F ⋙ forget (ModuleCat R)))
62+
set_option linter.uppercaseLean3 false in
63+
#align Module.filtered_colimits.M.mk ModuleCat.FilteredColimits.M.mk
64+
65+
theorem M.mk_eq (x y : Σ j, F.obj j)
66+
(h : ∃ (k : J) (f : x.1 ⟶ k) (g : y.1 ⟶ k), F.map f x.2 = F.map g y.2) : M.mk F x = M.mk F y :=
67+
Quot.EqvGen_sound (Types.FilteredColimit.eqvGen_quot_rel_of_rel (F ⋙ forget (ModuleCat R)) x y h)
68+
set_option linter.uppercaseLean3 false in
69+
#align Module.filtered_colimits.M.mk_eq ModuleCat.FilteredColimits.M.mk_eq
70+
71+
/-- The "unlifted" version of scalar multiplication in the colimit. -/
72+
def colimitSmulAux (r : R) (x : Σ j, F.obj j) : M F :=
73+
M.mk F ⟨x.1, r • x.2
74+
set_option linter.uppercaseLean3 false in
75+
#align Module.filtered_colimits.colimit_smul_aux ModuleCat.FilteredColimits.colimitSmulAux
76+
77+
theorem colimitSmulAux_eq_of_rel (r : R) (x y : Σ j, F.obj j)
78+
(h : Types.FilteredColimit.Rel.{v, u} (F ⋙ forget (ModuleCat R)) x y) :
79+
colimitSmulAux F r x = colimitSmulAux F r y := by
80+
apply M.mk_eq
81+
obtain ⟨k, f, g, hfg⟩ := h
82+
use k, f, g
83+
simp only [Functor.comp_obj, Functor.comp_map, forget_map] at hfg
84+
simp [hfg]
85+
set_option linter.uppercaseLean3 false in
86+
#align Module.filtered_colimits.colimit_smul_aux_eq_of_rel ModuleCat.FilteredColimits.colimitSmulAux_eq_of_rel
87+
88+
/-- Scalar multiplication in the colimit. See also `colimitSmulAux`. -/
89+
instance colimitHasSmul : SMul R (M F) where
90+
smul r x := by
91+
refine' Quot.lift (colimitSmulAux F r) _ x
92+
intro x y h
93+
apply colimitSmulAux_eq_of_rel
94+
apply Types.FilteredColimit.rel_of_quot_rel
95+
exact h
96+
set_option linter.uppercaseLean3 false in
97+
#align Module.filtered_colimits.colimit_has_smul ModuleCat.FilteredColimits.colimitHasSmul
98+
99+
@[simp]
100+
theorem colimit_smul_mk_eq (r : R) (x : Σ j, F.obj j) : r • M.mk F x = M.mk F ⟨x.1, r • x.2⟩ :=
101+
rfl
102+
set_option linter.uppercaseLean3 false in
103+
#align Module.filtered_colimits.colimit_smul_mk_eq ModuleCat.FilteredColimits.colimit_smul_mk_eq
104+
105+
private theorem colimitModule.one_smul (x : (M F)) : (1 : R) • x = x := by
106+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
107+
erw [colimit_smul_mk_eq F 1 ⟨j, x⟩]
108+
simp
109+
rfl
110+
111+
-- Porting note: writing directly the `Module` instance makes things very slow.
112+
instance colimitMulAction : MulAction R (M F) where
113+
one_smul x := by
114+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
115+
erw [colimit_smul_mk_eq F 1 ⟨j, x⟩, one_smul]
116+
rfl
117+
mul_smul r s x := by
118+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
119+
erw [colimit_smul_mk_eq F (r * s) ⟨j, x⟩, colimit_smul_mk_eq F s ⟨j, x⟩,
120+
colimit_smul_mk_eq F r ⟨j, _⟩, mul_smul]
121+
122+
instance colimitSMulWithZero : SMulWithZero R (M F) :=
123+
{ colimitMulAction F with
124+
smul_zero := fun r => by
125+
erw [colimit_zero_eq _ (IsFiltered.Nonempty.some : J), colimit_smul_mk_eq, smul_zero]
126+
rfl
127+
zero_smul := fun x => by
128+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
129+
erw [colimit_smul_mk_eq, zero_smul, colimit_zero_eq _ j]
130+
rfl }
131+
132+
private theorem colimitModule.add_smul (r s : R) (x : (M F)) : (r + s) • x = r • x + s • x := by
133+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
134+
erw [colimit_smul_mk_eq, _root_.add_smul, colimit_smul_mk_eq, colimit_smul_mk_eq,
135+
colimit_add_mk_eq _ ⟨j, _⟩ ⟨j, _⟩ j (𝟙 j) (𝟙 j), CategoryTheory.Functor.map_id, id_apply,
136+
id_apply]
137+
rfl
138+
139+
instance colimitModule : Module R (M F) :=
140+
{ colimitMulAction F,
141+
colimitSMulWithZero F with
142+
smul_add := fun r x y => by
143+
refine' Quot.induction_on₂ x y _; clear x y; intro x y; cases' x with i x; cases' y with j y
144+
erw [colimit_add_mk_eq _ ⟨i, _⟩ ⟨j, _⟩ (max' i j) (IsFiltered.leftToMax i j)
145+
(IsFiltered.rightToMax i j), colimit_smul_mk_eq, smul_add, colimit_smul_mk_eq,
146+
colimit_smul_mk_eq, colimit_add_mk_eq _ ⟨i, _⟩ ⟨j, _⟩ (max' i j) (IsFiltered.leftToMax i j)
147+
(IsFiltered.rightToMax i j), LinearMap.map_smul, LinearMap.map_smul]
148+
rfl
149+
add_smul := colimitModule.add_smul F }
150+
151+
set_option linter.uppercaseLean3 false in
152+
#align Module.filtered_colimits.colimit_module ModuleCat.FilteredColimits.colimitModule
153+
154+
/-- The bundled `R`-module giving the filtered colimit of a diagram. -/
155+
def colimit : ModuleCatMax.{v, u, u} R :=
156+
ModuleCat.of R (M F)
157+
set_option linter.uppercaseLean3 false in
158+
#align Module.filtered_colimits.colimit ModuleCat.FilteredColimits.colimit
159+
160+
/-- The linear map from a given `R`-module in the diagram to the colimit module. -/
161+
def coconeMorphism (j : J) : F.obj j ⟶ colimit F :=
162+
{ (AddCommGroupCat.FilteredColimits.colimitCocone
163+
(F ⋙ forget₂ (ModuleCat R) AddCommGroupCat.{max v u})).ι.app j with
164+
map_smul' := fun r x => by erw [colimit_smul_mk_eq F r ⟨j, x⟩]; rfl }
165+
set_option linter.uppercaseLean3 false in
166+
#align Module.filtered_colimits.cocone_morphism ModuleCat.FilteredColimits.coconeMorphism
167+
168+
/-- The cocone over the proposed colimit module. -/
169+
def colimitCocone : Cocone F where
170+
pt := colimit F
171+
ι :=
172+
{ app := coconeMorphism F
173+
naturality := fun _ _' f =>
174+
LinearMap.coe_injective ((Types.colimitCocone (F ⋙ forget (ModuleCat R))).ι.naturality f) }
175+
set_option linter.uppercaseLean3 false in
176+
#align Module.filtered_colimits.colimit_cocone ModuleCat.FilteredColimits.colimitCocone
177+
178+
/-- Given a cocone `t` of `F`, the induced monoid linear map from the colimit to the cocone point.
179+
We already know that this is a morphism between additive groups. The only thing left to see is that
180+
it is a linear map, i.e. preserves scalar multiplication.
181+
-/
182+
def colimitDesc (t : Cocone F) : colimit F ⟶ t.pt :=
183+
{ (AddCommGroupCat.FilteredColimits.colimitCoconeIsColimit
184+
(F ⋙ forget₂ (ModuleCatMax.{v, u} R) AddCommGroupCat.{max v u})).desc
185+
((forget₂ (ModuleCat R) AddCommGroupCat.{max v u}).mapCocone t) with
186+
map_smul' := fun r x => by
187+
refine' Quot.inductionOn x _; clear x; intro x; cases' x with j x
188+
erw [colimit_smul_mk_eq]
189+
exact LinearMap.map_smul (t.ι.app j) r x }
190+
set_option linter.uppercaseLean3 false in
191+
#align Module.filtered_colimits.colimit_desc ModuleCat.FilteredColimits.colimitDesc
192+
193+
/-- The proposed colimit cocone is a colimit in `Module R`. -/
194+
def colimitCoconeIsColimit : IsColimit (colimitCocone F) where
195+
desc := colimitDesc F
196+
fac t j :=
197+
LinearMap.coe_injective <|
198+
(Types.colimitCoconeIsColimit.{v, u} (F ⋙ forget (ModuleCat R))).fac
199+
((forget (ModuleCat R)).mapCocone t) j
200+
uniq t _ h :=
201+
LinearMap.coe_injective <|
202+
(Types.colimitCoconeIsColimit (F ⋙ forget (ModuleCat R))).uniq
203+
((forget (ModuleCat R)).mapCocone t) _ fun j => funext fun x => LinearMap.congr_fun (h j) x
204+
set_option linter.uppercaseLean3 false in
205+
#align Module.filtered_colimits.colimit_cocone_is_colimit ModuleCat.FilteredColimits.colimitCoconeIsColimit
206+
207+
instance forget₂AddCommGroupPreservesFilteredColimits :
208+
PreservesFilteredColimits (forget₂ (ModuleCat.{u} R) AddCommGroupCat.{u}) where
209+
preserves_filtered_colimits J _ _ :=
210+
{ -- Porting note: without the curly braces for `F`
211+
-- here we get a confusing error message about universes.
212+
preservesColimit := fun {F : J ⥤ ModuleCat.{u} R} =>
213+
preservesColimitOfPreservesColimitCocone (colimitCoconeIsColimit F)
214+
(AddCommGroupCat.FilteredColimits.colimitCoconeIsColimit
215+
(F ⋙ forget₂ (ModuleCat.{u} R) AddCommGroupCat.{u})) }
216+
set_option linter.uppercaseLean3 false in
217+
#align Module.filtered_colimits.forget₂_AddCommGroup_preserves_filtered_colimits ModuleCat.FilteredColimits.forget₂AddCommGroupPreservesFilteredColimits
218+
219+
instance forgetPreservesFilteredColimits : PreservesFilteredColimits (forget (ModuleCat.{u} R)) :=
220+
Limits.compPreservesFilteredColimits (forget₂ (ModuleCat R) AddCommGroupCat)
221+
(forget AddCommGroupCat)
222+
set_option linter.uppercaseLean3 false in
223+
#align Module.filtered_colimits.forget_preserves_filtered_colimits ModuleCat.FilteredColimits.forgetPreservesFilteredColimits
224+
225+
end
226+
227+
end ModuleCat.FilteredColimits

Mathlib/CategoryTheory/ConcreteCategory/Basic.lean

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ related work.
4141
-/
4242

4343

44-
universe w v v' u
44+
universe w w' v v' u
4545

4646
namespace CategoryTheory
4747

@@ -201,8 +201,8 @@ end
201201
/-- `HasForget₂ C D`, where `C` and `D` are both concrete categories, provides a functor
202202
`forget₂ C D : C ⥤ D` and a proof that `forget₂ ⋙ (forget D) = forget C`.
203203
-/
204-
class HasForget₂ (C : Type v) (D : Type v') [Category C] [ConcreteCategory.{u} C] [Category D]
205-
[ConcreteCategory.{u} D] where
204+
class HasForget₂ (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C]
205+
[Category.{v'} D] [ConcreteCategory.{w} D] where
206206
/-- A functor from `C` to `D` -/
207207
forget₂ : C ⥤ D
208208
/-- It covers the `ConcreteCategory.forget` for `C` and `D` -/
@@ -212,61 +212,65 @@ class HasForget₂ (C : Type v) (D : Type v') [Category C] [ConcreteCategory.{u}
212212
/-- The forgetful functor `C ⥤ D` between concrete categories for which we have an instance
213213
`HasForget₂ C `. -/
214214
@[reducible]
215-
def forget₂ (C : Type v) (D : Type v') [Category C] [ConcreteCategory C] [Category D]
216-
[ConcreteCategory D] [HasForget₂ C D] : C ⥤ D :=
215+
def forget₂ (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C]
216+
[Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] : C ⥤ D :=
217217
HasForget₂.forget₂
218218
#align category_theory.forget₂ CategoryTheory.forget₂
219219

220-
instance forget₂_faithful (C : Type v) (D : Type v') [Category C] [ConcreteCategory C] [Category D]
221-
[ConcreteCategory D] [HasForget₂ C D] : Faithful (forget₂ C D) :=
220+
instance forget₂_faithful (C : Type u) (D : Type u') [Category.{v} C] [ConcreteCategory.{w} C]
221+
[Category.{v'} D] [ConcreteCategory.{w} D] [HasForget₂ C D] : Faithful (forget₂ C D) :=
222222
HasForget₂.forget_comp.faithful_of_comp
223223
#align category_theory.forget₂_faithful CategoryTheory.forget₂_faithful
224224

225-
instance forget₂_preservesMonomorphisms (C : Type v) (D : Type v') [Category C] [ConcreteCategory C]
226-
[Category D] [ConcreteCategory D] [HasForget₂ C D] [(forget C).PreservesMonomorphisms] :
225+
instance forget₂_preservesMonomorphisms (C : Type u) (D : Type u')
226+
[Category.{v} C] [ConcreteCategory.{w} C] [Category.{v'} D] [ConcreteCategory.{w} D]
227+
[HasForget₂ C D] [(forget C).PreservesMonomorphisms] :
227228
(forget₂ C D).PreservesMonomorphisms :=
228229
have : (forget₂ C D ⋙ forget D).PreservesMonomorphisms := by
229230
simp only [HasForget₂.forget_comp]
230231
infer_instance
231232
Functor.preservesMonomorphisms_of_preserves_of_reflects _ (forget D)
232233
#align category_theory.forget₂_preserves_monomorphisms CategoryTheory.forget₂_preservesMonomorphisms
233234

234-
instance forget₂_preservesEpimorphisms (C : Type v) (D : Type v') [Category C] [ConcreteCategory C]
235-
[Category D] [ConcreteCategory D] [HasForget₂ C D] [(forget C).PreservesEpimorphisms] :
235+
instance forget₂_preservesEpimorphisms (C : Type u) (D : Type u')
236+
[Category.{v} C] [ConcreteCategory.{w} C] [Category.{v'} D] [ConcreteCategory.{w} D]
237+
[HasForget₂ C D] [(forget C).PreservesEpimorphisms] :
236238
(forget₂ C D).PreservesEpimorphisms :=
237239
have : (forget₂ C D ⋙ forget D).PreservesEpimorphisms := by
238240
simp only [HasForget₂.forget_comp]
239241
infer_instance
240242
Functor.preservesEpimorphisms_of_preserves_of_reflects _ (forget D)
241243
#align category_theory.forget₂_preserves_epimorphisms CategoryTheory.forget₂_preservesEpimorphisms
242244

243-
instance InducedCategory.concreteCategory {C : Type v} {D : Type v'} [Category D]
244-
[ConcreteCategory D] (f : C → D) : ConcreteCategory (InducedCategory D f) where
245+
instance InducedCategory.concreteCategory {C : Type u} {D : Type u'}
246+
[Category.{v'} D] [ConcreteCategory.{w} D] (f : C → D) :
247+
ConcreteCategory (InducedCategory D f) where
245248
forget := inducedFunctor f ⋙ forget D
246249
#align category_theory.induced_category.concrete_category CategoryTheory.InducedCategory.concreteCategory
247250

248-
instance InducedCategory.hasForget₂ {C : Type v} {D : Type v'} [Category D] [ConcreteCategory D]
249-
(f : C → D) : HasForget₂ (InducedCategory D f) D where
251+
instance InducedCategory.hasForget₂ {C : Type u} {D : Type u'} [Category.{v} D]
252+
[ConcreteCategory.{w} D] (f : C → D) : HasForget₂ (InducedCategory D f) D where
250253
forget₂ := inducedFunctor f
251254
forget_comp := rfl
252255
#align category_theory.induced_category.has_forget₂ CategoryTheory.InducedCategory.hasForget₂
253256

254-
instance FullSubcategory.concreteCategory {C : Type v} [Category C] [ConcreteCategory C]
257+
instance FullSubcategory.concreteCategory {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C]
255258
(Z : C → Prop) : ConcreteCategory (FullSubcategory Z) where
256259
forget := fullSubcategoryInclusion Z ⋙ forget C
257260
#align category_theory.full_subcategory.concrete_category CategoryTheory.FullSubcategoryₓ.concreteCategory
258261

259-
instance FullSubcategory.hasForget₂ {C : Type v} [Category C] [ConcreteCategory C] (Z : C → Prop) :
260-
HasForget₂ (FullSubcategory Z) C where
262+
instance FullSubcategory.hasForget₂ {C : Type u} [Category.{v} C] [ConcreteCategory.{w} C]
263+
(Z : C → Prop) : HasForget₂ (FullSubcategory Z) C where
261264
forget₂ := fullSubcategoryInclusion Z
262265
forget_comp := rfl
263266
#align category_theory.full_subcategory.has_forget₂ CategoryTheory.FullSubcategoryₓ.hasForget₂
264267

265268
/-- In order to construct a “partially forgetting” functor, we do not need to verify functor laws;
266269
it suffices to ensure that compositions agree with `forget₂ C D ⋙ forget D = forget C`.
267270
-/
268-
def HasForget₂.mk' {C : Type v} {D : Type v'} [Category C] [ConcreteCategory C] [Category D]
269-
[ConcreteCategory D] (obj : C → D) (h_obj : ∀ X, (forget D).obj (obj X) = (forget C).obj X)
271+
def HasForget₂.mk' {C : Type u} {D : Type u'} [Category.{v} C] [ConcreteCategory.{w} C]
272+
[Category.{v'} D] [ConcreteCategory.{w} D]
273+
(obj : C → D) (h_obj : ∀ X, (forget D).obj (obj X) = (forget C).obj X)
270274
(map : ∀ {X Y}, (X ⟶ Y) → (obj X ⟶ obj Y))
271275
(h_map : ∀ {X Y} {f : X ⟶ Y}, HEq ((forget D).map (map f)) ((forget C).map f)) : HasForget₂ C D
272276
where
@@ -276,7 +280,8 @@ def HasForget₂.mk' {C : Type v} {D : Type v'} [Category C] [ConcreteCategory C
276280

277281
/-- Every forgetful functor factors through the identity functor. This is not a global instance as
278282
it is prone to creating type class resolution loops. -/
279-
def hasForgetToType (C : Type v) [Category C] [ConcreteCategory C] : HasForget₂ C (Type u) where
283+
def hasForgetToType (C : Type u) [Category.{v} C] [ConcreteCategory.{w} C] :
284+
HasForget₂ C (Type w) where
280285
forget₂ := forget C
281286
forget_comp := Functor.comp_id _
282287
#align category_theory.has_forget_to_Type CategoryTheory.hasForgetToType

0 commit comments

Comments
 (0)