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

Commit 81d3ebf

Browse files
kim-emmergify[bot]jcommelinbryangingechen
authored
feat(algebra): monoidal category of R-modules (#2125)
* feat(algebra): monoidal category of R-modules * docstrings * minor * tweaks * fix import * fixes * reduce use of @ * broken * fixes * Update src/algebra/category/Module/basic.lean Co-Authored-By: Bryan Gin-ge Chen <bryangingechen@gmail.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Johan Commelin <johan@commelin.net> Co-authored-by: Bryan Gin-ge Chen <bryangingechen@gmail.com>
1 parent 3d621b5 commit 81d3ebf

5 files changed

Lines changed: 268 additions & 29 deletions

File tree

src/algebra/category/Module/basic.lean

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ Authors: Robert A. Spencer, Markus Himmel
55
-/
66
import algebra.module
77
import algebra.punit_instances
8+
import algebra.category.Group
89
import category_theory.concrete_category
910
import category_theory.limits.shapes.zero
1011
import category_theory.limits.shapes.kernels
1112
import linear_algebra.basic
13+
1214
open category_theory
1315
open category_theory.limits
1416
open category_theory.limits.walking_parallel_pair
@@ -44,8 +46,13 @@ def of (X : Type u) [add_comm_group X] [module R X] : Module R := ⟨R, X⟩
4446

4547
instance : inhabited (Module R) := ⟨of R punit⟩
4648

49+
@[simp]
4750
lemma of_apply (X : Type u) [add_comm_group X] [module R X] : (of R X : Type u) = X := rfl
4851

52+
/-- Forgetting the underlying type and then building the bundled object returns the original module. -/
53+
def of_self (M : Module R) : Module.of R M ≅ M :=
54+
{ hom := 𝟙 M, inv := 𝟙 M }
55+
4956
instance : subsingleton (of R punit) :=
5057
by { rw of_apply R punit, apply_instance }
5158

@@ -60,18 +67,56 @@ instance : has_zero_object.{u} (Module R) :=
6067
{ default := (0 : X →ₗ[R] punit),
6168
uniq := λ _, linear_map.ext $ λ x, subsingleton.elim _ _ } }
6269

63-
variables (M N U : Module R)
70+
variables {R} {M N U : Module R}
6471

6572
@[simp] lemma id_apply (m : M) : (𝟙 M : M → M) m = m := rfl
6673

6774
@[simp] lemma coe_comp (f : M ⟶ N) (g : N ⟶ U) :
6875
((f ≫ g) : M → U) = g ∘ f := rfl
6976

70-
instance hom_is_module_hom {M₁ M₂ : Module R} (f : M₁ ⟶ M₂) :
71-
is_linear_map R (f : M₁ → M₂) := linear_map.is_linear _
77+
instance hom_is_module_hom (f : M ⟶ N) :
78+
is_linear_map R (f : M → N) := linear_map.is_linear _
79+
80+
end Module
81+
82+
variables {R}
83+
variables {X₁ X₂ : Type u}
84+
85+
/-- Build an isomorphism in the category `Module R` from a `linear_equiv` between `module`s. -/
86+
@[simps]
87+
def linear_equiv.to_Module_iso
88+
{g₁ : add_comm_group X₁} {g₂ : add_comm_group X₂} {m₁ : module R X₁} {m₂ : module R X₂} (e : X₁ ≃ₗ[R] X₂) :
89+
Module.of R X₁ ≅ Module.of R X₂ :=
90+
{ hom := (e : X₁ →ₗ[R] X₂),
91+
inv := (e.symm : X₂ →ₗ[R] X₁),
92+
hom_inv_id' := begin ext, exact e.left_inv x, end,
93+
inv_hom_id' := begin ext, exact e.right_inv x, end, }
94+
95+
namespace category_theory.iso
96+
97+
/-- Build a `linear_equiv` from an isomorphism in the category `Module R`. -/
98+
@[simps]
99+
def to_linear_equiv {X Y : Module.{u} R} (i : X ≅ Y) : X ≃ₗ[R] Y :=
100+
{ to_fun := i.hom,
101+
inv_fun := i.inv,
102+
left_inv := by tidy,
103+
right_inv := by tidy,
104+
add := by tidy,
105+
smul := by tidy, }.
106+
107+
end category_theory.iso
108+
109+
/-- linear equivalences between `module`s are the same as (isomorphic to) isomorphisms in `Module` -/
110+
@[simps]
111+
def linear_equiv_iso_Group_iso {X Y : Type u} [add_comm_group X] [add_comm_group Y] [module R X] [module R Y] :
112+
(X ≃ₗ[R] Y) ≅ (Module.of R X ≅ Module.of R Y) :=
113+
{ hom := λ e, e.to_Module_iso,
114+
inv := λ i, i.to_linear_equiv, }
115+
116+
namespace Module
72117

73118
section kernel
74-
variable (f : M ⟶ N)
119+
variables {R} {M N : Module R} (f : M ⟶ N)
75120

76121
local attribute [instance] has_zero_object.zero_morphisms_of_zero_object
77122

@@ -87,7 +132,7 @@ def kernel_cone : cone (parallel_pair f 0) :=
87132
naturality' := λ j j' g, by { cases j; cases j'; cases g; tidy } } }
88133

89134
/-- The kernel of a linear map is a kernel in the categorical sense -/
90-
def kernel_is_limit : is_limit (kernel_cone _ _ _ f) :=
135+
def kernel_is_limit : is_limit (kernel_cone f) :=
91136
{ lift := λ s, linear_map.cod_restrict f.ker (fork.ι s) (λ c, linear_map.mem_ker.2 $
92137
by { erw [←@function.comp_apply _ _ _ f (fork.ι s) c, ←coe_comp, fork.condition,
93138
has_zero_morphisms.comp_zero _ (fork.ι s) N], refl }),
@@ -99,7 +144,7 @@ def kernel_is_limit : is_limit (kernel_cone _ _ _ f) :=
99144
{ rw [←cone_parallel_pair_right, ←cone_parallel_pair_right], refl }
100145
end,
101146
uniq' := λ s m h, linear_map.ext $ λ x, subtype.ext.2 $
102-
have h₁ : (m ≫ (kernel_cone _ _ _ f).π.app zero).to_fun = (s.π.app zero).to_fun,
147+
have h₁ : (m ≫ (kernel_cone f).π.app zero).to_fun = (s.π.app zero).to_fun,
103148
by { congr, exact h zero },
104149
by convert @congr_fun _ _ _ _ h₁ x }
105150

@@ -108,7 +153,7 @@ end kernel
108153
local attribute [instance] has_zero_object.zero_morphisms_of_zero_object
109154

110155
instance : has_kernels.{u} (Module R) :=
111-
⟨λ _ _ f, ⟨kernel_cone _ _ _ f, kernel_is_limit _ _ _ f⟩⟩
156+
⟨λ _ _ f, ⟨kernel_cone f, kernel_is_limit f⟩⟩
112157

113158
end Module
114159

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import category_theory.monoidal.category
2+
import algebra.category.Module.basic
3+
import linear_algebra.tensor_product
4+
5+
/-!
6+
# The monoidal category structure on R-modules
7+
8+
Mostly this uses existing machinery in `linear_algebra.tensor_product`.
9+
We just need to provide a few small missing pieces to build the
10+
`monoidal_category` instance.
11+
12+
If you're happy using the bundled `Module R`, it may be possible to mostly
13+
use this as an interface and not need to interact much with the implementation details.
14+
-/
15+
16+
universe u
17+
18+
open category_theory
19+
20+
namespace Module
21+
22+
variables {R : Type u} [comm_ring R]
23+
24+
namespace monoidal_category
25+
-- The definitions inside this namespace are essentially private.
26+
-- After we build the `monoidal_category (Module R)` instance,
27+
-- you should use that API.
28+
29+
open_locale tensor_product
30+
31+
/-- (implementation) tensor product of R-modules -/
32+
def tensor_obj (M N : Module R) : Module R := Module.of R (M ⊗[R] N)
33+
/-- (implementation) tensor product of morphisms R-modules -/
34+
def tensor_hom {M N M' N' : Module R} (f : M ⟶ N) (g : M' ⟶ N') : tensor_obj M M' ⟶ tensor_obj N N' :=
35+
tensor_product.map f g
36+
37+
lemma tensor_id (M N : Module R) : tensor_hom (𝟙 M) (𝟙 N) = 𝟙 (Module.of R (↥M ⊗ ↥N)) :=
38+
by tidy
39+
40+
lemma tensor_comp {X₁ Y₁ Z₁ X₂ Y₂ Z₂ : Module R}
41+
(f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (g₁ : Y₁ ⟶ Z₁) (g₂ : Y₂ ⟶ Z₂) :
42+
tensor_hom (f₁ ≫ g₁) (f₂ ≫ g₂) = tensor_hom f₁ f₂ ≫ tensor_hom g₁ g₂ :=
43+
by tidy
44+
45+
/-- (implementation) the associator for R-modules -/
46+
def associator (M N K : Module R) : tensor_obj (tensor_obj M N) K ≅ tensor_obj M (tensor_obj N K) :=
47+
linear_equiv.to_Module_iso (tensor_product.assoc R M N K)
48+
49+
lemma associator_naturality {X₁ X₂ X₃ Y₁ Y₂ Y₃ : Module R}
50+
(f₁ : X₁ ⟶ Y₁) (f₂ : X₂ ⟶ Y₂) (f₃ : X₃ ⟶ Y₃) :
51+
tensor_hom (tensor_hom f₁ f₂) f₃ ≫ (associator Y₁ Y₂ Y₃).hom =
52+
(associator X₁ X₂ X₃).hom ≫ tensor_hom f₁ (tensor_hom f₂ f₃) :=
53+
begin
54+
apply tensor_product.ext_threefold,
55+
intros x y z,
56+
refl
57+
end
58+
59+
lemma pentagon (W X Y Z : Module R) :
60+
tensor_hom (associator W X Y).hom (𝟙 Z) ≫ (associator W (tensor_obj X Y) Z).hom ≫ tensor_hom (𝟙 W) (associator X Y Z).hom =
61+
(associator (tensor_obj W X) Y Z).hom ≫ (associator W X (tensor_obj Y Z)).hom :=
62+
begin
63+
apply tensor_product.ext_fourfold,
64+
intros w x y z,
65+
refl
66+
end
67+
68+
/-- (implementation) the left unitor for R-modules -/
69+
def left_unitor (M : Module R) : Module.of R (R ⊗[R] M) ≅ M :=
70+
(linear_equiv.to_Module_iso (tensor_product.lid R M) : of R (R ⊗ M) ≅ of R M).trans (of_self R M)
71+
72+
lemma left_unitor_naturality {M N : Module R} (f : M ⟶ N) :
73+
tensor_hom (𝟙 (Module.of R R)) f ≫ (left_unitor N).hom = (left_unitor M).hom ≫ f :=
74+
begin
75+
ext x y, simp,
76+
erw [tensor_product.lid_tmul, tensor_product.lid_tmul],
77+
rw linear_map.map_smul,
78+
refl,
79+
end
80+
81+
/-- (implementation) the right unitor for R-modules -/
82+
def right_unitor (M : Module R) : Module.of R (M ⊗[R] R) ≅ M :=
83+
(linear_equiv.to_Module_iso (tensor_product.rid R M) : of R (M ⊗ R) ≅ of R M).trans (of_self R M)
84+
85+
lemma right_unitor_naturality {M N : Module R} (f : M ⟶ N) :
86+
tensor_hom f (𝟙 (Module.of R R)) ≫ (right_unitor N).hom = (right_unitor M).hom ≫ f :=
87+
begin
88+
ext x y, simp,
89+
erw [tensor_product.rid_tmul, tensor_product.rid_tmul],
90+
rw linear_map.map_smul,
91+
refl,
92+
end
93+
94+
lemma triangle (M N : Module R) :
95+
(associator M (Module.of R R) N).hom ≫ tensor_hom (𝟙 M) (left_unitor N).hom =
96+
tensor_hom (right_unitor M).hom (𝟙 N) :=
97+
begin
98+
apply tensor_product.ext_threefold,
99+
intros x y z,
100+
change R at y,
101+
dsimp [tensor_hom, associator],
102+
erw [tensor_product.lid_tmul, tensor_product.rid_tmul],
103+
apply (tensor_product.smul_tmul _ _ _).symm
104+
end
105+
106+
end monoidal_category
107+
108+
open monoidal_category
109+
110+
instance : monoidal_category (Module.{u} R) :=
111+
{ -- data
112+
tensor_obj := tensor_obj,
113+
tensor_hom := @tensor_hom _ _,
114+
tensor_unit := Module.of R R,
115+
associator := associator,
116+
left_unitor := left_unitor,
117+
right_unitor := right_unitor,
118+
-- properties
119+
tensor_id' := λ M N, tensor_id M N,
120+
tensor_comp' := λ M N K M' N' K' f g h, tensor_comp f g h,
121+
associator_naturality' := λ M N K M' N' K' f g h, associator_naturality f g h,
122+
left_unitor_naturality' := λ M N f, left_unitor_naturality f,
123+
right_unitor_naturality' := λ M N f, right_unitor_naturality f,
124+
pentagon' := λ M N K L, pentagon M N K L,
125+
triangle' := λ M N, triangle M N, }
126+
127+
end Module

src/category_theory/limits/types.lean

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@ namespace category_theory.limits.types
1414

1515
variables {J : Type u} [small_category J]
1616

17-
def limit (F : J ⥤ Type u) : cone F :=
17+
/-- (implementation) the limit cone of a functor to Type -/
18+
def limit_ (F : J ⥤ Type u) : cone F :=
1819
{ X := F.sections,
1920
π := { app := λ j u, u.val j } }
2021

2122
local attribute [elab_simple] congr_fun
22-
def limit_is_limit (F : J ⥤ Type u) : is_limit (limit F) :=
23+
/-- (implementation) the fact that the proposed limit cone is the limit -/
24+
def limit_is_limit_ (F : J ⥤ Type u) : is_limit (limit_ F) :=
2325
{ lift := λ s v, ⟨λ j, s.π.app j v, λ j j' f, congr_fun (cone.w s f) _⟩,
2426
uniq' :=
2527
begin
@@ -29,51 +31,53 @@ def limit_is_limit (F : J ⥤ Type u) : is_limit (limit F) :=
2931

3032
instance : has_limits.{u} (Type u) :=
3133
{ has_limits_of_shape := λ J 𝒥,
32-
{ has_limit := λ F, by exactI { cone := limit F, is_limit := limit_is_limit F } } }
34+
{ has_limit := λ F, by exactI { cone := limit_ F, is_limit := limit_is_limit_ F } } }
3335

3436
@[simp] lemma types_limit (F : J ⥤ Type u) :
3537
limits.limit F = {u : Π j, F.obj j // ∀ {j j'} f, F.map f (u j) = u j'} := rfl
36-
@[simp] lemma types_limit_π (F : J ⥤ Type u) (j : J) (g : (limit F).X) :
38+
@[simp] lemma types_limit_π (F : J ⥤ Type u) (j : J) (g : limit F) :
3739
limit.π F j g = g.val j := rfl
3840
@[simp] lemma types_limit_pre
39-
(F : J ⥤ Type u) {K : Type u} [𝒦 : small_category K] (E : K ⥤ J) (g : (limit F).X) :
40-
limit.pre F E g = (⟨λ k, g.val (E.obj k), by obviously⟩ : (limit (E ⋙ F)).X) := rfl
41-
@[simp] lemma types_limit_map {F G : J ⥤ Type u} (α : F ⟶ G) (g : (limit F).X) :
42-
(lim.map α : (limit F).X(limit G).X) g =
41+
(F : J ⥤ Type u) {K : Type u} [𝒦 : small_category K] (E : K ⥤ J) (g : limit F) :
42+
limit.pre F E g = (⟨λ k, g.val (E.obj k), by obviously⟩ : limit (E ⋙ F)) := rfl
43+
@[simp] lemma types_limit_map {F G : J ⥤ Type u} (α : F ⟶ G) (g : limit F) :
44+
(lim.map α : limit F → limit G) g =
4345
(⟨λ j, (α.app j) (g.val j), λ j j' f,
44-
by {rw ←functor_to_types.naturality, dsimp, rw ←(g.property f)}⟩ : (limit G).X) := rfl
46+
by {rw ←functor_to_types.naturality, dsimp, rw ←(g.property f)}⟩ : limit G) := rfl
4547

4648
@[simp] lemma types_limit_lift (F : J ⥤ Type u) (c : cone F) (x : c.X) :
47-
limit.lift F c x = (⟨λ j, c.π.app j x, λ j j' f, congr_fun (cone.w c f) x⟩ : (limit F).X) :=
49+
limit.lift F c x = (⟨λ j, c.π.app j x, λ j j' f, congr_fun (cone.w c f) x⟩ : limit F) :=
4850
rfl
4951

5052

51-
def colimit (F : J ⥤ Type u) : cocone F :=
53+
/-- (implementation) the colimit cocone of a functor to Type -/
54+
def colimit_ (F : J ⥤ Type u) : cocone F :=
5255
{ X := @quot (Σ j, F.obj j) (λ p p', ∃ f : p.1 ⟶ p'.1, p'.2 = F.map f p.2),
5356
ι :=
5457
{ app := λ j x, quot.mk _ ⟨j, x⟩,
5558
naturality' := λ j j' f, funext $ λ x, eq.symm (quot.sound ⟨f, rfl⟩) } }
5659

5760
local attribute [elab_with_expected_type] quot.lift
5861

59-
def colimit_is_colimit (F : J ⥤ Type u) : is_colimit (colimit F) :=
62+
/-- (implementation) the fact that the proposed colimit cocone is the colimit -/
63+
def colimit_is_colimit_ (F : J ⥤ Type u) : is_colimit (colimit_ F) :=
6064
{ desc := λ s, quot.lift (λ (p : Σ j, F.obj j), s.ι.app p.1 p.2)
6165
(assume ⟨j, x⟩ ⟨j', x'⟩ ⟨f, hf⟩, by rw hf; exact (congr_fun (cocone.w s f) x).symm) }
6266

6367
instance : has_colimits.{u} (Type u) :=
6468
{ has_colimits_of_shape := λ J 𝒥,
65-
{ has_colimit := λ F, by exactI { cocone := colimit F, is_colimit := colimit_is_colimit F } } }
69+
{ has_colimit := λ F, by exactI { cocone := colimit_ F, is_colimit := colimit_is_colimit_ F } } }
6670

6771
@[simp] lemma types_colimit (F : J ⥤ Type u) :
6872
limits.colimit F = @quot (Σ j, F.obj j) (λ p p', ∃ f : p.1 ⟶ p'.1, p'.2 = F.map f p.2) := rfl
6973
@[simp] lemma types_colimit_ι (F : J ⥤ Type u) (j : J) :
7074
colimit.ι F j = λ x, quot.mk _ ⟨j, x⟩ := rfl
7175
@[simp] lemma types_colimit_pre
72-
(F : J ⥤ Type u) {K : Type u} [𝒦 : small_category K] (E : K ⥤ J) (g : (colimit (E ⋙ F)).X) :
76+
(F : J ⥤ Type u) {K : Type u} [𝒦 : small_category K] (E : K ⥤ J) :
7377
colimit.pre F E =
7478
quot.lift (λ p, quot.mk _ ⟨E.obj p.1, p.2⟩) (λ p p' ⟨f, h⟩, quot.sound ⟨E.map f, h⟩) := rfl
7579
@[simp] lemma types_colimit_map {F G : J ⥤ Type u} (α : F ⟶ G) :
76-
(colim.map α : (colimit F).X(colimit G).X) =
80+
(colim.map α : colimit F → colimit G) =
7781
quot.lift
7882
(λ p, quot.mk _ ⟨p.1, (α.app p.1) p.2⟩)
7983
(λ p p' ⟨f, h⟩, quot.sound ⟨f, by rw h; exact functor_to_types.naturality _ _ α f _⟩) := rfl

src/linear_algebra/basic.lean

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,22 +1331,26 @@ section
13311331
variable (M)
13321332

13331333
/-- The identity map is a linear equivalence. -/
1334-
@[refl] def refl : M ≃ₗ[R] M := { .. linear_map.id, .. equiv.refl M }
1334+
@[refl]
1335+
def refl : M ≃ₗ[R] M := { .. linear_map.id, .. equiv.refl M }
13351336
end
13361337

13371338
/-- Linear equivalences are symmetric. -/
1338-
@[symm] def symm (e : M ≃ₗ[R] M₂) : M₂ ≃ₗ[R] M :=
1339+
@[symm]
1340+
def symm (e : M ≃ₗ[R] M₂) : M₂ ≃ₗ[R] M :=
13391341
{ .. e.to_linear_map.inverse e.inv_fun e.left_inv e.right_inv,
13401342
.. e.to_equiv.symm }
13411343

13421344
/-- Linear equivalences are transitive. -/
1343-
@[trans] def trans (e₁ : M ≃ₗ[R] M₂) (e₂ : M₂ ≃ₗ[R] M₃) : M ≃ₗ[R] M₃ :=
1345+
@[trans]
1346+
def trans (e₁ : M ≃ₗ[R] M₂) (e₂ : M₂ ≃ₗ[R] M₃) : M ≃ₗ[R] M₃ :=
13441347
{ .. e₂.to_linear_map.comp e₁.to_linear_map,
13451348
.. e₁.to_equiv.trans e₂.to_equiv }
13461349

13471350
/-- A linear equivalence is an additive equivalence. -/
13481351
def to_add_equiv (e : M ≃ₗ[R] M₂) : M ≃+ M₂ := { map_add' := e.add, .. e }
13491352

1353+
@[simp] theorem trans_apply (e₁ : M ≃ₗ[R] M₂) (e₂ : M₂ ≃ₗ[R] M₃) (c : M) : (e₁.trans e₂) c = e₂ (e₁ c) := rfl
13501354
@[simp] theorem apply_symm_apply (e : M ≃ₗ[R] M₂) (c : M₂) : e (e.symm c) = c := e.6 c
13511355
@[simp] theorem symm_apply_apply (e : M ≃ₗ[R] M₂) (b : M) : e.symm (e b) = b := e.5 b
13521356

0 commit comments

Comments
 (0)