|
| 1 | +/- |
| 2 | +Copyright (c) 2018 Reid Barton. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Reid Barton, Scott Morrison |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module category_theory.eq_to_hom |
| 7 | +! leanprover-community/mathlib commit dc6c365e751e34d100e80fe6e314c3c3e0fd2988 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.CategoryTheory.Opposites |
| 12 | + |
| 13 | +/-! |
| 14 | +# Morphisms from equations between objects. |
| 15 | +
|
| 16 | +When working categorically, sometimes one encounters an equation `h : X = Y` between objects. |
| 17 | +
|
| 18 | +Your initial aversion to this is natural and appropriate: |
| 19 | +you're in for some trouble, and if there is another way to approach the problem that won't |
| 20 | +rely on this equality, it may be worth pursuing. |
| 21 | +
|
| 22 | +You have two options: |
| 23 | +1. Use the equality `h` as one normally would in Lean (e.g. using `rw` and `subst`). |
| 24 | + This may immediately cause difficulties, because in category theory everything is dependently |
| 25 | + typed, and equations between objects quickly lead to nasty goals with `eq.rec`. |
| 26 | +2. Promote `h` to a morphism using `eqToHom h : X ⟶ Y`, or `eqToIso h : X ≅ Y`. |
| 27 | +
|
| 28 | +This file introduces various `simp` lemmas which in favourable circumstances |
| 29 | +result in the various `eqToHom` morphisms to drop out at the appropriate moment! |
| 30 | +-/ |
| 31 | + |
| 32 | + |
| 33 | +universe v₁ v₂ v₃ u₁ u₂ u₃ |
| 34 | + |
| 35 | +-- morphism levels before object levels. See note [category_theory universes]. |
| 36 | +namespace CategoryTheory |
| 37 | + |
| 38 | +open Opposite |
| 39 | + |
| 40 | +variable {C : Type u₁} [Category.{v₁} C] |
| 41 | + |
| 42 | +/-- An equality `X = Y` gives us a morphism `X ⟶ Y`. |
| 43 | +
|
| 44 | +It is typically better to use this, rather than rewriting by the equality then using `𝟙 _` |
| 45 | +which usually leads to dependent type theory hell. |
| 46 | +-/ |
| 47 | +def eqToHom {X Y : C} (p : X = Y) : X ⟶ Y := by rw [p]; exact 𝟙 _ |
| 48 | +#align category_theory.eq_to_hom CategoryTheory.eqToHom |
| 49 | + |
| 50 | +@[simp] |
| 51 | +theorem eqToHom_refl (X : C) (p : X = X) : eqToHom p = 𝟙 X := |
| 52 | + rfl |
| 53 | +#align category_theory.eq_to_hom_refl CategoryTheory.eqToHom_refl |
| 54 | + |
| 55 | +@[reassoc (attr := simp)] |
| 56 | +theorem eqToHom_trans {X Y Z : C} (p : X = Y) (q : Y = Z) : |
| 57 | + eqToHom p ≫ eqToHom q = eqToHom (p.trans q) := |
| 58 | + by |
| 59 | + cases p |
| 60 | + cases q |
| 61 | + simp |
| 62 | +#align category_theory.eq_to_hom_trans CategoryTheory.eqToHom_trans |
| 63 | + |
| 64 | +theorem comp_eqToHom_iff {X Y Y' : C} (p : Y = Y') (f : X ⟶ Y) (g : X ⟶ Y') : |
| 65 | + f ≫ eqToHom p = g ↔ f = g ≫ eqToHom p.symm := |
| 66 | + { mp := fun h => h ▸ by simp |
| 67 | + mpr := fun h => by simp [eq_whisker h (eqToHom p)] } |
| 68 | +#align category_theory.comp_eq_to_hom_iff CategoryTheory.comp_eqToHom_iff |
| 69 | + |
| 70 | +theorem eqToHom_comp_iff {X X' Y : C} (p : X = X') (f : X ⟶ Y) (g : X' ⟶ Y) : |
| 71 | + eqToHom p ≫ g = f ↔ g = eqToHom p.symm ≫ f := |
| 72 | + { mp := fun h => h ▸ by simp |
| 73 | + mpr := fun h => h ▸ by simp [whisker_eq _ h] } |
| 74 | +#align category_theory.eq_to_hom_comp_iff CategoryTheory.eqToHom_comp_iff |
| 75 | + |
| 76 | +/- Porting note: simpNF complains about thsi not reducing but it is clearly used |
| 77 | +in `congrArg_mrp_hom_left`. It has been no-linted. -/ |
| 78 | +/-- Reducible form of congrArg_mpr_hom_left -/ |
| 79 | +@[simp, nolint simpNF] |
| 80 | +theorem congrArg_cast_hom_left {X Y Z : C} (p : X = Y) (q : Y ⟶ Z) : |
| 81 | + cast (congrArg (fun W : C => W ⟶ Z) p.symm) q = eqToHom p ≫ q := by |
| 82 | + cases p |
| 83 | + simp |
| 84 | + |
| 85 | + /-- If we (perhaps unintentionally) perform equational rewriting on |
| 86 | +the source object of a morphism, |
| 87 | +we can replace the resulting `_.mpr f` term by a composition with an `eqToHom`. |
| 88 | +
|
| 89 | +It may be advisable to introduce any necessary `eqToHom` morphisms manually, |
| 90 | +rather than relying on this lemma firing. |
| 91 | +-/ |
| 92 | +theorem congrArg_mpr_hom_left {X Y Z : C} (p : X = Y) (q : Y ⟶ Z) : |
| 93 | + (congrArg (fun W : C => W ⟶ Z) p).mpr q = eqToHom p ≫ q := |
| 94 | + by |
| 95 | + cases p |
| 96 | + simp |
| 97 | +#align category_theory.congr_arg_mpr_hom_left CategoryTheory.congrArg_mpr_hom_left |
| 98 | + |
| 99 | +/- Porting note: simpNF complains about thsi not reducing but it is clearly used |
| 100 | +in `congrArg_mrp_hom_right`. It has been no-linted. -/ |
| 101 | +/-- Reducible form of `congrArg_mpr_hom_right` -/ |
| 102 | +@[simp, nolint simpNF] |
| 103 | +theorem congrArg_cast_hom_right {X Y Z : C} (p : X ⟶ Y) (q : Z = Y) : |
| 104 | + cast (congrArg (fun W : C => X ⟶ W) q.symm) p = p ≫ eqToHom q.symm := by |
| 105 | + cases q |
| 106 | + simp |
| 107 | + |
| 108 | +/-- If we (perhaps unintentionally) perform equational rewriting on |
| 109 | +the target object of a morphism, |
| 110 | +we can replace the resulting `_.mpr f` term by a composition with an `eqToHom`. |
| 111 | +
|
| 112 | +It may be advisable to introduce any necessary `eqToHom` morphisms manually, |
| 113 | +rather than relying on this lemma firing. |
| 114 | +-/ |
| 115 | +theorem congrArg_mpr_hom_right {X Y Z : C} (p : X ⟶ Y) (q : Z = Y) : |
| 116 | + (congrArg (fun W : C => X ⟶ W) q).mpr p = p ≫ eqToHom q.symm := |
| 117 | + by |
| 118 | + cases q |
| 119 | + simp |
| 120 | +#align category_theory.congr_arg_mpr_hom_right CategoryTheory.congrArg_mpr_hom_right |
| 121 | + |
| 122 | +/-- An equality `X = Y` gives us an isomorphism `X ≅ Y`. |
| 123 | +
|
| 124 | +It is typically better to use this, rather than rewriting by the equality then using `Iso.refl _` |
| 125 | +which usually leads to dependent type theory hell. |
| 126 | +-/ |
| 127 | +def eqToIso {X Y : C} (p : X = Y) : X ≅ Y := |
| 128 | + ⟨eqToHom p, eqToHom p.symm, by simp, by simp⟩ |
| 129 | +#align category_theory.eq_to_iso CategoryTheory.eqToIso |
| 130 | + |
| 131 | +@[simp] |
| 132 | +theorem eqToIso.hom {X Y : C} (p : X = Y) : (eqToIso p).hom = eqToHom p := |
| 133 | + rfl |
| 134 | +#align category_theory.eq_to_iso.hom CategoryTheory.eqToIso.hom |
| 135 | + |
| 136 | +@[simp] |
| 137 | +theorem eqToIso.inv {X Y : C} (p : X = Y) : (eqToIso p).inv = eqToHom p.symm := |
| 138 | + rfl |
| 139 | +#align category_theory.eq_to_iso.inv CategoryTheory.eqToIso.inv |
| 140 | + |
| 141 | +@[simp] |
| 142 | +theorem eqToIso_refl {X : C} (p : X = X) : eqToIso p = Iso.refl X := |
| 143 | + rfl |
| 144 | +#align category_theory.eq_to_iso_refl CategoryTheory.eqToIso_refl |
| 145 | + |
| 146 | +@[simp] |
| 147 | +theorem eqToIso_trans {X Y Z : C} (p : X = Y) (q : Y = Z) : |
| 148 | + eqToIso p ≪≫ eqToIso q = eqToIso (p.trans q) := by ext; simp |
| 149 | +#align category_theory.eq_to_iso_trans CategoryTheory.eqToIso_trans |
| 150 | + |
| 151 | +@[simp] |
| 152 | +theorem eqToHom_op {X Y : C} (h : X = Y) : (eqToHom h).op = eqToHom (congr_arg op h.symm) := |
| 153 | + by |
| 154 | + cases h |
| 155 | + rfl |
| 156 | +#align category_theory.eq_to_hom_op CategoryTheory.eqToHom_op |
| 157 | + |
| 158 | +@[simp] |
| 159 | +theorem eqToHom_unop {X Y : Cᵒᵖ} (h : X = Y) : (eqToHom h).unop = eqToHom (congr_arg unop h.symm) := |
| 160 | + by |
| 161 | + cases h |
| 162 | + rfl |
| 163 | +#align category_theory.eq_to_hom_unop CategoryTheory.eqToHom_unop |
| 164 | + |
| 165 | +instance {X Y : C} (h : X = Y) : IsIso (eqToHom h) := |
| 166 | + IsIso.of_iso (eqToIso h) |
| 167 | + |
| 168 | +@[simp] |
| 169 | +theorem inv_eqToHom {X Y : C} (h : X = Y) : inv (eqToHom h) = eqToHom h.symm := |
| 170 | + by |
| 171 | + aesop_cat |
| 172 | +#align category_theory.inv_eq_to_hom CategoryTheory.inv_eqToHom |
| 173 | + |
| 174 | +variable {D : Type u₂} [Category.{v₂} D] |
| 175 | + |
| 176 | +namespace Functor |
| 177 | + |
| 178 | +/-- Proving equality between functors. This isn't an extensionality lemma, |
| 179 | + because usually you don't really want to do this. -/ |
| 180 | +theorem ext {F G : C ⥤ D} (h_obj : ∀ X, F.obj X = G.obj X) |
| 181 | + (h_map : ∀ X Y f, F.map f = eqToHom (h_obj X) ≫ G.map f ≫ eqToHom (h_obj Y).symm) : F = G := |
| 182 | + by |
| 183 | + match F, G with |
| 184 | + | mk F_pre _ _ , mk G_pre _ _ => |
| 185 | + match F_pre, G_pre with -- Porting note: did not unfold the Prefunctor unlike Lean3 |
| 186 | + | Prefunctor.mk F_obj _ , Prefunctor.mk G_obj _ => |
| 187 | + obtain rfl : F_obj = G_obj := by |
| 188 | + ext X |
| 189 | + apply h_obj |
| 190 | + congr |
| 191 | + funext X Y f |
| 192 | + simpa using h_map X Y f |
| 193 | +#align category_theory.functor.ext CategoryTheory.Functor.ext |
| 194 | + |
| 195 | +/-- Two morphisms are conjugate via eqToHom if and only if they are heterogeneously equal. -/ |
| 196 | +theorem conj_eqToHom_iff_hEq {W X Y Z : C} (f : W ⟶ X) (g : Y ⟶ Z) (h : W = Y) (h' : X = Z) : |
| 197 | + f = eqToHom h ≫ g ≫ eqToHom h'.symm ↔ HEq f g := |
| 198 | + by |
| 199 | + cases h |
| 200 | + cases h' |
| 201 | + simp |
| 202 | +#align category_theory.functor.conj_eq_to_hom_iff_heq CategoryTheory.Functor.conj_eqToHom_iff_hEq |
| 203 | + |
| 204 | +/-- Proving equality between functors using heterogeneous equality. -/ |
| 205 | +theorem hext {F G : C ⥤ D} (h_obj : ∀ X, F.obj X = G.obj X) |
| 206 | + (h_map : ∀ (X Y) (f : X ⟶ Y), HEq (F.map f) (G.map f)) : F = G := |
| 207 | + Functor.ext h_obj fun _ _ f => (conj_eqToHom_iff_hEq _ _ (h_obj _) (h_obj _)).2 <| h_map _ _ f |
| 208 | +#align category_theory.functor.hext CategoryTheory.Functor.hext |
| 209 | + |
| 210 | +-- Using equalities between functors. |
| 211 | +theorem congr_obj {F G : C ⥤ D} (h : F = G) (X) : F.obj X = G.obj X := by rw [h] |
| 212 | +#align category_theory.functor.congr_obj CategoryTheory.Functor.congr_obj |
| 213 | + |
| 214 | +theorem congr_hom {F G : C ⥤ D} (h : F = G) {X Y} (f : X ⟶ Y) : |
| 215 | + F.map f = eqToHom (congr_obj h X) ≫ G.map f ≫ eqToHom (congr_obj h Y).symm := by |
| 216 | + subst h; simp |
| 217 | +#align category_theory.functor.congr_hom CategoryTheory.Functor.congr_hom |
| 218 | + |
| 219 | +theorem congr_inv_of_congr_hom (F G : C ⥤ D) {X Y : C} (e : X ≅ Y) (hX : F.obj X = G.obj X) |
| 220 | + (hY : F.obj Y = G.obj Y) |
| 221 | + (h₂ : F.map e.hom = eqToHom (by rw [hX]) ≫ G.map e.hom ≫ eqToHom (by rw [hY])) : |
| 222 | + F.map e.inv = eqToHom (by rw [hY]) ≫ G.map e.inv ≫ eqToHom (by rw [hX]) := by |
| 223 | + simp only [← IsIso.Iso.inv_hom e, Functor.map_inv, h₂, IsIso.inv_comp, inv_eqToHom, |
| 224 | + Category.assoc] |
| 225 | +#align category_theory.functor.congr_inv_of_congr_hom CategoryTheory.Functor.congr_inv_of_congr_hom |
| 226 | + |
| 227 | +theorem congr_map (F : C ⥤ D) {X Y : C} {f g : X ⟶ Y} (h : f = g) : F.map f = F.map g := by rw [h] |
| 228 | +#align category_theory.functor.congr_map CategoryTheory.Functor.congr_map |
| 229 | + |
| 230 | +section HEq |
| 231 | + |
| 232 | +-- Composition of functors and maps w.r.t. heq |
| 233 | +variable {E : Type u₃} [Category.{v₃} E] {F G : C ⥤ D} {X Y Z : C} {f : X ⟶ Y} {g : Y ⟶ Z} |
| 234 | + |
| 235 | +theorem map_comp_hEq (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y) (hz : F.obj Z = G.obj Z) |
| 236 | + (hf : HEq (F.map f) (G.map f)) (hg : HEq (F.map g) (G.map g)) : |
| 237 | + HEq (F.map (f ≫ g)) (G.map (f ≫ g)) := |
| 238 | + by |
| 239 | + rw [F.map_comp, G.map_comp] |
| 240 | + congr |
| 241 | +#align category_theory.functor.map_comp_heq CategoryTheory.Functor.map_comp_hEq |
| 242 | + |
| 243 | +theorem map_comp_heq' (hobj : ∀ X : C, F.obj X = G.obj X) |
| 244 | + (hmap : ∀ {X Y} (f : X ⟶ Y), HEq (F.map f) (G.map f)) : HEq (F.map (f ≫ g)) (G.map (f ≫ g)) := |
| 245 | + by rw [Functor.hext hobj fun _ _ => hmap] |
| 246 | +#align category_theory.functor.map_comp_heq' CategoryTheory.Functor.map_comp_heq' |
| 247 | + |
| 248 | +theorem precomp_map_hEq (H : E ⥤ C) (hmap : ∀ {X Y} (f : X ⟶ Y), HEq (F.map f) (G.map f)) {X Y : E} |
| 249 | + (f : X ⟶ Y) : HEq ((H ⋙ F).map f) ((H ⋙ G).map f) := |
| 250 | + hmap _ |
| 251 | +#align category_theory.functor.precomp_map_heq CategoryTheory.Functor.precomp_map_hEq |
| 252 | + |
| 253 | +theorem postcomp_map_hEq (H : D ⥤ E) (hx : F.obj X = G.obj X) (hy : F.obj Y = G.obj Y) |
| 254 | + (hmap : HEq (F.map f) (G.map f)) : HEq ((F ⋙ H).map f) ((G ⋙ H).map f) := |
| 255 | + by |
| 256 | + dsimp |
| 257 | + congr |
| 258 | +#align category_theory.functor.postcomp_map_heq CategoryTheory.Functor.postcomp_map_hEq |
| 259 | + |
| 260 | +theorem postcomp_map_heq' (H : D ⥤ E) (hobj : ∀ X : C, F.obj X = G.obj X) |
| 261 | + (hmap : ∀ {X Y} (f : X ⟶ Y), HEq (F.map f) (G.map f)) : HEq ((F ⋙ H).map f) ((G ⋙ H).map f) := |
| 262 | + by rw [Functor.hext hobj fun _ _ => hmap] |
| 263 | +#align category_theory.functor.postcomp_map_heq' CategoryTheory.Functor.postcomp_map_heq' |
| 264 | + |
| 265 | +theorem hcongr_hom {F G : C ⥤ D} (h : F = G) {X Y} (f : X ⟶ Y) : HEq (F.map f) (G.map f) := by |
| 266 | + rw [h] |
| 267 | +#align category_theory.functor.hcongr_hom CategoryTheory.Functor.hcongr_hom |
| 268 | + |
| 269 | +end HEq |
| 270 | + |
| 271 | +end Functor |
| 272 | + |
| 273 | +/-- This is not always a good idea as a `@[simp]` lemma, |
| 274 | +as we lose the ability to use results that interact with `F`, |
| 275 | +e.g. the naturality of a natural transformation. |
| 276 | +
|
| 277 | +In some files it may be appropriate to use `local attribute [simp] eqToHom_map`, however. |
| 278 | +-/ |
| 279 | +theorem eqToHom_map (F : C ⥤ D) {X Y : C} (p : X = Y) : |
| 280 | + F.map (eqToHom p) = eqToHom (congr_arg F.obj p) := by cases p; simp |
| 281 | +#align category_theory.eq_to_hom_map CategoryTheory.eqToHom_map |
| 282 | + |
| 283 | +/-- See the note on `eqToHom_map` regarding using this as a `simp` lemma. |
| 284 | +-/ |
| 285 | +theorem eqToIso_map (F : C ⥤ D) {X Y : C} (p : X = Y) : |
| 286 | + F.mapIso (eqToIso p) = eqToIso (congr_arg F.obj p) := by ext; cases p; simp |
| 287 | +#align category_theory.eq_to_iso_map CategoryTheory.eqToIso_map |
| 288 | + |
| 289 | +@[simp] |
| 290 | +theorem eqToHom_app {F G : C ⥤ D} (h : F = G) (X : C) : |
| 291 | + (eqToHom h : F ⟶ G).app X = eqToHom (Functor.congr_obj h X) := by subst h; rfl |
| 292 | +#align category_theory.eq_to_hom_app CategoryTheory.eqToHom_app |
| 293 | + |
| 294 | +theorem NatTrans.congr {F G : C ⥤ D} (α : F ⟶ G) {X Y : C} (h : X = Y) : |
| 295 | + α.app X = F.map (eqToHom h) ≫ α.app Y ≫ G.map (eqToHom h.symm) := |
| 296 | + by |
| 297 | + rw [α.naturality_assoc] |
| 298 | + simp [eqToHom_map] |
| 299 | +#align category_theory.nat_trans.congr CategoryTheory.NatTrans.congr |
| 300 | + |
| 301 | +theorem eq_conj_eqToHom {X Y : C} (f : X ⟶ Y) : f = eqToHom rfl ≫ f ≫ eqToHom rfl := by |
| 302 | + simp only [Category.id_comp, eqToHom_refl, Category.comp_id] |
| 303 | +#align category_theory.eq_conj_eq_to_hom CategoryTheory.eq_conj_eqToHom |
| 304 | + |
| 305 | +theorem dcongr_arg {ι : Type _} {F G : ι → C} (α : ∀ i, F i ⟶ G i) {i j : ι} (h : i = j) : |
| 306 | + α i = eqToHom (congr_arg F h) ≫ α j ≫ eqToHom (congr_arg G h.symm) := |
| 307 | + by |
| 308 | + subst h |
| 309 | + simp |
| 310 | +#align category_theory.dcongr_arg CategoryTheory.dcongr_arg |
| 311 | + |
| 312 | +end CategoryTheory |
0 commit comments