File: Mathlib/CategoryTheory/Subobject/Basic.lean

full_name: CategoryTheory.Subobject
code: /-- The category of subobjects of `X : C`, defined as isomorphism classes of monomorphisms into `X`.
-/
def Subobject (X : C) 
goal: Type (max u₁ v₁)

full_name: CategoryTheory.instPartialOrderSubobject
code: instance (X : C) : PartialOrder (Subobject X) 
goal: PartialOrder (CategoryTheory.Subobject X)

full_name: CategoryTheory.Subobject.mk
code: /-- Convenience constructor for a subobject. -/
def mk {X A : C} (f : A ⟶ X) [Mono f] : Subobject X 
goal: CategoryTheory.Subobject X

full_name: CategoryTheory.Subobject.ind
code: protected theorem ind {X : C} (p : Subobject X → Prop)
    (h : ∀ ⦃A : C⦄ (f : A ⟶ X) [Mono f], p (Subobject.mk f)) (P : Subobject X) : p P 
goal: p P

full_name: CategoryTheory.Subobject.ind₂
code: protected theorem ind₂ {X : C} (p : Subobject X → Subobject X → Prop)
    (h : ∀ ⦃A B : C⦄ (f : A ⟶ X) (g : B ⟶ X) [Mono f] [Mono g],
      p (Subobject.mk f) (Subobject.mk g))
    (P Q : Subobject X) : p P Q 
goal: p P Q

full_name: CategoryTheory.Subobject.lift
code: /-- Declare a function on subobjects of `X` by specifying a function on monomorphisms with
    codomain `X`. -/
protected def lift {α : Sort*} {X : C} (F : ∀ ⦃A : C⦄ (f : A ⟶ X) [Mono f], α)
    (h :
      ∀ ⦃A B : C⦄ (f : A ⟶ X) (g : B ⟶ X) [Mono f] [Mono g] (i : A ≅ B),
        i.hom ≫ g = f → F f = F g) :
    Subobject X → α 
goal: CategoryTheory.Subobject X → α

full_name: CategoryTheory.Subobject.lift_mk
code: @[simp]
protected theorem lift_mk {α : Sort*} {X : C} (F : ∀ ⦃A : C⦄ (f : A ⟶ X) [Mono f], α) {h A}
    (f : A ⟶ X) [Mono f] : Subobject.lift F h (Subobject.mk f) = F f 
goal: CategoryTheory.Subobject.lift F h (CategoryTheory.Subobject.mk f) = F f

full_name: CategoryTheory.Subobject.equivMonoOver
code: /-- The category of subobjects is equivalent to the `MonoOver` category. It is more convenient to
use the former due to the partial order instance, but oftentimes it is easier to define structures
on the latter. -/
noncomputable def equivMonoOver (X : C) : Subobject X ≌ MonoOver X 
goal: CategoryTheory.Subobject X ≌ CategoryTheory.MonoOver X

full_name: CategoryTheory.Subobject.representative
code: /-- Use choice to pick a representative `MonoOver X` for each `Subobject X`.
-/
noncomputable def representative {X : C} : Subobject X ⥤ MonoOver X 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X) (CategoryTheory.MonoOver X)

full_name: CategoryTheory.Subobject.representativeIso
code: /-- Starting with `A : MonoOver X`, we can take its equivalence class in `Subobject X`
then pick an arbitrary representative using `representative.obj`.
This is isomorphic (in `MonoOver X`) to the original `A`.
-/
noncomputable def representativeIso {X : C} (A : MonoOver X) :
    representative.obj ((toThinSkeleton _).obj A) ≅ A 
goal: CategoryTheory.Subobject.representative.obj ((CategoryTheory.toThinSkeleton (CategoryTheory.MonoOver X)).obj A) ≅ A

full_name: CategoryTheory.Subobject.underlying
code: /-- Use choice to pick a representative underlying object in `C` for any `Subobject X`.

Prefer to use the coercion `P : C` rather than explicitly writing `underlying.obj P`.
-/
noncomputable def underlying {X : C} : Subobject X ⥤ C 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X) C

full_name: CategoryTheory.Subobject.instCoeOut
code: instance : CoeOut (Subobject X) C 
goal: CoeOut (CategoryTheory.Subobject X) C

full_name: CategoryTheory.Subobject.underlyingIso
code: /-- If we construct a `Subobject Y` from an explicit `f : X ⟶ Y` with `[Mono f]`,
then pick an arbitrary choice of underlying object `(Subobject.mk f : C)` back in `C`,
it is isomorphic (in `C`) to the original `X`.
-/
noncomputable def underlyingIso {X Y : C} (f : X ⟶ Y) [Mono f] : (Subobject.mk f : C) ≅ X 
goal: CategoryTheory.Subobject.underlying.obj (CategoryTheory.Subobject.mk f) ≅ X

full_name: CategoryTheory.Subobject.arrow
code: /-- The morphism in `C` from the arbitrarily chosen underlying object to the ambient object.
-/
noncomputable def arrow {X : C} (Y : Subobject X) : (Y : C) ⟶ X 
goal: CategoryTheory.Subobject.underlying.obj Y ⟶ X

full_name: CategoryTheory.Subobject.arrow_mono
code: instance arrow_mono {X : C} (Y : Subobject X) : Mono Y.arrow 
goal: CategoryTheory.Mono Y.arrow

full_name: CategoryTheory.Subobject.arrow_congr
code: @[simp]
theorem arrow_congr {A : C} (X Y : Subobject A) (h : X = Y) :
    eqToHom (congr_arg (fun X : Subobject A => (X : C)) h) ≫ Y.arrow = X.arrow 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.eqToHom ⋯) Y.arrow = X.arrow

full_name: CategoryTheory.Subobject.representative_coe
code: @[simp]
theorem representative_coe (Y : Subobject X) : (representative.obj Y : C) = (Y : C) 
goal: (CategoryTheory.Subobject.representative.obj Y).obj.left = CategoryTheory.Subobject.underlying.obj Y

full_name: CategoryTheory.Subobject.representative_arrow
code: @[simp]
theorem representative_arrow (Y : Subobject X) : (representative.obj Y).arrow = Y.arrow 
goal: (CategoryTheory.Subobject.representative.obj Y).arrow = Y.arrow

full_name: CategoryTheory.Subobject.underlying_arrow
code: @[reassoc (attr := simp)]
theorem underlying_arrow {X : C} {Y Z : Subobject X} (f : Y ⟶ Z) :
    underlying.map f ≫ arrow Z = arrow Y 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.underlying.map f) Z.arrow = Y.arrow

full_name: CategoryTheory.Subobject.underlyingIso_arrow
code: @[reassoc (attr := simp), elementwise (attr := simp)]
theorem underlyingIso_arrow {X Y : C} (f : X ⟶ Y) [Mono f] :
    (underlyingIso f).inv ≫ (Subobject.mk f).arrow = f 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.underlyingIso f).inv
    (CategoryTheory.Subobject.mk f).arrow =
  f

full_name: CategoryTheory.Subobject.underlyingIso_hom_comp_eq_mk
code: @[reassoc (attr := simp)]
theorem underlyingIso_hom_comp_eq_mk {X Y : C} (f : X ⟶ Y) [Mono f] :
    (underlyingIso f).hom ≫ f = (mk f).arrow 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.underlyingIso f).hom f =
  (CategoryTheory.Subobject.mk f).arrow

full_name: CategoryTheory.Subobject.eq_of_comp_arrow_eq
code: /-- Two morphisms into a subobject are equal exactly if
the morphisms into the ambient object are equal -/
@[ext]
theorem eq_of_comp_arrow_eq {X Y : C} {P : Subobject Y} {f g : X ⟶ P}
    (h : f ≫ P.arrow = g ≫ P.arrow) : f = g 
goal: f = g

full_name: CategoryTheory.Subobject.mk_le_mk_of_comm
code: theorem mk_le_mk_of_comm {B A₁ A₂ : C} {f₁ : A₁ ⟶ B} {f₂ : A₂ ⟶ B} [Mono f₁] [Mono f₂] (g : A₁ ⟶ A₂)
    (w : g ≫ f₂ = f₁) : mk f₁ ≤ mk f₂ 
goal: CategoryTheory.Subobject.mk f₁ ≤ CategoryTheory.Subobject.mk f₂

full_name: CategoryTheory.Subobject.mk_arrow
code: @[simp]
theorem mk_arrow (P : Subobject X) : mk P.arrow = P 
goal: CategoryTheory.Subobject.mk P.arrow = P

full_name: CategoryTheory.Subobject.le_of_comm
code: theorem le_of_comm {B : C} {X Y : Subobject B} (f : (X : C) ⟶ (Y : C)) (w : f ≫ Y.arrow = X.arrow) :
    X ≤ Y 
goal: X ≤ Y

full_name: CategoryTheory.Subobject.le_mk_of_comm
code: theorem le_mk_of_comm {B A : C} {X : Subobject B} {f : A ⟶ B} [Mono f] (g : (X : C) ⟶ A)
    (w : g ≫ f = X.arrow) : X ≤ mk f 
goal: X ≤ CategoryTheory.Subobject.mk f

full_name: CategoryTheory.Subobject.mk_le_of_comm
code: theorem mk_le_of_comm {B A : C} {X : Subobject B} {f : A ⟶ B} [Mono f] (g : A ⟶ (X : C))
    (w : g ≫ X.arrow = f) : mk f ≤ X 
goal: CategoryTheory.Subobject.mk f ≤ X

full_name: CategoryTheory.Subobject.eq_of_comm
code: /-- To show that two subobjects are equal, it suffices to exhibit an isomorphism commuting with
    the arrows. -/
@[ext]
theorem eq_of_comm {B : C} {X Y : Subobject B} (f : (X : C) ≅ (Y : C))
    (w : f.hom ≫ Y.arrow = X.arrow) : X = Y 
goal: X = Y

full_name: CategoryTheory.Subobject.eq_mk_of_comm
code: /-- To show that two subobjects are equal, it suffices to exhibit an isomorphism commuting with
    the arrows. -/
theorem eq_mk_of_comm {B A : C} {X : Subobject B} (f : A ⟶ B) [Mono f] (i : (X : C) ≅ A)
    (w : i.hom ≫ f = X.arrow) : X = mk f 
goal: X = CategoryTheory.Subobject.mk f

full_name: CategoryTheory.Subobject.mk_eq_of_comm
code: /-- To show that two subobjects are equal, it suffices to exhibit an isomorphism commuting with
    the arrows. -/
theorem mk_eq_of_comm {B A : C} {X : Subobject B} (f : A ⟶ B) [Mono f] (i : A ≅ (X : C))
    (w : i.hom ≫ X.arrow = f) : mk f = X 
goal: CategoryTheory.Subobject.mk f = X

full_name: CategoryTheory.Subobject.mk_eq_mk_of_comm
code: /-- To show that two subobjects are equal, it suffices to exhibit an isomorphism commuting with
    the arrows. -/
theorem mk_eq_mk_of_comm {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (i : A₁ ≅ A₂)
    (w : i.hom ≫ g = f) : mk f = mk g 
goal: CategoryTheory.Subobject.mk f = CategoryTheory.Subobject.mk g

full_name: CategoryTheory.Subobject.ofLE
code: /-- An inequality of subobjects is witnessed by some morphism between the corresponding objects. -/
def ofLE {B : C} (X Y : Subobject B) (h : X ≤ Y) : (X : C) ⟶ (Y : C) 
goal: CategoryTheory.Subobject.underlying.obj X ⟶ CategoryTheory.Subobject.underlying.obj Y

full_name: CategoryTheory.Subobject.ofLE_arrow
code: @[reassoc (attr := simp)]
theorem ofLE_arrow {B : C} {X Y : Subobject B} (h : X ≤ Y) : ofLE X Y h ≫ Y.arrow = X.arrow 
goal: CategoryTheory.CategoryStruct.comp (X.ofLE Y h) Y.arrow = X.arrow

full_name: CategoryTheory.Subobject.instMonoOfLE
code: instance {B : C} (X Y : Subobject B) (h : X ≤ Y) : Mono (ofLE X Y h) 
goal: CategoryTheory.Mono (X.ofLE Y h)

full_name: CategoryTheory.Subobject.ofLE_mk_le_mk_of_comm
code: theorem ofLE_mk_le_mk_of_comm {B A₁ A₂ : C} {f₁ : A₁ ⟶ B} {f₂ : A₂ ⟶ B} [Mono f₁] [Mono f₂]
    (g : A₁ ⟶ A₂) (w : g ≫ f₂ = f₁) :
    ofLE _ _ (mk_le_mk_of_comm g w) = (underlyingIso _).hom ≫ g ≫ (underlyingIso _).inv 
goal: (CategoryTheory.Subobject.mk f₁).ofLE (CategoryTheory.Subobject.mk f₂) ⋯ =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.underlyingIso f₁).hom
    (CategoryTheory.CategoryStruct.comp g (CategoryTheory.Subobject.underlyingIso f₂).inv)

full_name: CategoryTheory.Subobject.ofLEMk
code: /-- An inequality of subobjects is witnessed by some morphism between the corresponding objects. -/
def ofLEMk {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (h : X ≤ mk f) : (X : C) ⟶ A 
goal: CategoryTheory.Subobject.underlying.obj X ⟶ A

full_name: CategoryTheory.Subobject.instMonoOfLEMk
code: instance {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (h : X ≤ mk f) :
    Mono (ofLEMk X f h) 
goal: CategoryTheory.Mono (X.ofLEMk f h)

full_name: CategoryTheory.Subobject.ofLEMk_comp
code: @[simp]
theorem ofLEMk_comp {B A : C} {X : Subobject B} {f : A ⟶ B} [Mono f] (h : X ≤ mk f) :
    ofLEMk X f h ≫ f = X.arrow 
goal: CategoryTheory.CategoryStruct.comp (X.ofLEMk f h) f = X.arrow

full_name: CategoryTheory.Subobject.ofMkLE
code: /-- An inequality of subobjects is witnessed by some morphism between the corresponding objects. -/
def ofMkLE {B A : C} (f : A ⟶ B) [Mono f] (X : Subobject B) (h : mk f ≤ X) : A ⟶ (X : C) 
goal: A ⟶ CategoryTheory.Subobject.underlying.obj X

full_name: CategoryTheory.Subobject.instMonoOfMkLE
code: instance {B A : C} (f : A ⟶ B) [Mono f] (X : Subobject B) (h : mk f ≤ X) :
    Mono (ofMkLE f X h) 
goal: CategoryTheory.Mono (CategoryTheory.Subobject.ofMkLE f X h)

full_name: CategoryTheory.Subobject.ofMkLE_arrow
code: @[simp]
theorem ofMkLE_arrow {B A : C} {f : A ⟶ B} [Mono f] {X : Subobject B} (h : mk f ≤ X) :
    ofMkLE f X h ≫ X.arrow = f 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLE f X h) X.arrow = f

full_name: CategoryTheory.Subobject.ofMkLEMk
code: /-- An inequality of subobjects is witnessed by some morphism between the corresponding objects. -/
def ofMkLEMk {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (h : mk f ≤ mk g) :
    A₁ ⟶ A₂ 
goal: A₁ ⟶ A₂

full_name: CategoryTheory.Subobject.instMonoOfMkLEMk
code: instance {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (h : mk f ≤ mk g) :
    Mono (ofMkLEMk f g h) 
goal: CategoryTheory.Mono (CategoryTheory.Subobject.ofMkLEMk f g h)

full_name: CategoryTheory.Subobject.ofMkLEMk_comp
code: @[simp]
theorem ofMkLEMk_comp {B A₁ A₂ : C} {f : A₁ ⟶ B} {g : A₂ ⟶ B} [Mono f] [Mono g] (h : mk f ≤ mk g) :
    ofMkLEMk f g h ≫ g = f 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLEMk f g h) g = f

full_name: CategoryTheory.Subobject.ofLE_comp_ofLE
code: @[reassoc (attr := simp)]
theorem ofLE_comp_ofLE {B : C} (X Y Z : Subobject B) (h₁ : X ≤ Y) (h₂ : Y ≤ Z) :
    ofLE X Y h₁ ≫ ofLE Y Z h₂ = ofLE X Z (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (X.ofLE Y h₁) (Y.ofLE Z h₂) = X.ofLE Z ⋯

full_name: CategoryTheory.Subobject.ofLE_comp_ofLEMk
code: @[reassoc (attr := simp)]
theorem ofLE_comp_ofLEMk {B A : C} (X Y : Subobject B) (f : A ⟶ B) [Mono f] (h₁ : X ≤ Y)
    (h₂ : Y ≤ mk f) : ofLE X Y h₁ ≫ ofLEMk Y f h₂ = ofLEMk X f (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (X.ofLE Y h₁) (Y.ofLEMk f h₂) = X.ofLEMk f ⋯

full_name: CategoryTheory.Subobject.ofLEMk_comp_ofMkLE
code: @[reassoc (attr := simp)]
theorem ofLEMk_comp_ofMkLE {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (Y : Subobject B)
    (h₁ : X ≤ mk f) (h₂ : mk f ≤ Y) : ofLEMk X f h₁ ≫ ofMkLE f Y h₂ = ofLE X Y (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (X.ofLEMk f h₁) (CategoryTheory.Subobject.ofMkLE f Y h₂) = X.ofLE Y ⋯

full_name: CategoryTheory.Subobject.ofLEMk_comp_ofMkLEMk
code: @[reassoc (attr := simp)]
theorem ofLEMk_comp_ofMkLEMk {B A₁ A₂ : C} (X : Subobject B) (f : A₁ ⟶ B) [Mono f] (g : A₂ ⟶ B)
    [Mono g] (h₁ : X ≤ mk f) (h₂ : mk f ≤ mk g) :
    ofLEMk X f h₁ ≫ ofMkLEMk f g h₂ = ofLEMk X g (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (X.ofLEMk f h₁) (CategoryTheory.Subobject.ofMkLEMk f g h₂) = X.ofLEMk g ⋯

full_name: CategoryTheory.Subobject.ofMkLE_comp_ofLE
code: @[reassoc (attr := simp)]
theorem ofMkLE_comp_ofLE {B A₁ : C} (f : A₁ ⟶ B) [Mono f] (X Y : Subobject B) (h₁ : mk f ≤ X)
    (h₂ : X ≤ Y) : ofMkLE f X h₁ ≫ ofLE X Y h₂ = ofMkLE f Y (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLE f X h₁) (X.ofLE Y h₂) =
  CategoryTheory.Subobject.ofMkLE f Y ⋯

full_name: CategoryTheory.Subobject.ofMkLE_comp_ofLEMk
code: @[reassoc (attr := simp)]
theorem ofMkLE_comp_ofLEMk {B A₁ A₂ : C} (f : A₁ ⟶ B) [Mono f] (X : Subobject B) (g : A₂ ⟶ B)
    [Mono g] (h₁ : mk f ≤ X) (h₂ : X ≤ mk g) :
    ofMkLE f X h₁ ≫ ofLEMk X g h₂ = ofMkLEMk f g (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLE f X h₁) (X.ofLEMk g h₂) =
  CategoryTheory.Subobject.ofMkLEMk f g ⋯

full_name: CategoryTheory.Subobject.ofMkLEMk_comp_ofMkLE
code: @[reassoc (attr := simp)]
theorem ofMkLEMk_comp_ofMkLE {B A₁ A₂ : C} (f : A₁ ⟶ B) [Mono f] (g : A₂ ⟶ B) [Mono g]
    (X : Subobject B) (h₁ : mk f ≤ mk g) (h₂ : mk g ≤ X) :
    ofMkLEMk f g h₁ ≫ ofMkLE g X h₂ = ofMkLE f X (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLEMk f g h₁) (CategoryTheory.Subobject.ofMkLE g X h₂) =
  CategoryTheory.Subobject.ofMkLE f X ⋯

full_name: CategoryTheory.Subobject.ofMkLEMk_comp_ofMkLEMk
code: @[reassoc (attr := simp)]
theorem ofMkLEMk_comp_ofMkLEMk {B A₁ A₂ A₃ : C} (f : A₁ ⟶ B) [Mono f] (g : A₂ ⟶ B) [Mono g]
    (h : A₃ ⟶ B) [Mono h] (h₁ : mk f ≤ mk g) (h₂ : mk g ≤ mk h) :
    ofMkLEMk f g h₁ ≫ ofMkLEMk g h h₂ = ofMkLEMk f h (h₁.trans h₂) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.Subobject.ofMkLEMk f g h₁)
    (CategoryTheory.Subobject.ofMkLEMk g h h₂) =
  CategoryTheory.Subobject.ofMkLEMk f h ⋯

full_name: CategoryTheory.Subobject.ofLE_refl
code: @[simp]
theorem ofLE_refl {B : C} (X : Subobject B) : ofLE X X le_rfl = 𝟙 _ 
goal: X.ofLE X ⋯ = CategoryTheory.CategoryStruct.id (CategoryTheory.Subobject.underlying.obj X)

full_name: CategoryTheory.Subobject.ofMkLEMk_refl
code: @[simp]
theorem ofMkLEMk_refl {B A₁ : C} (f : A₁ ⟶ B) [Mono f] : ofMkLEMk f f le_rfl = 𝟙 _ 
goal: CategoryTheory.Subobject.ofMkLEMk f f ⋯ = CategoryTheory.CategoryStruct.id A₁

full_name: CategoryTheory.Subobject.isoOfEq
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects.
(One could use `underlying.mapIso (eqToIso h))` here, but this is more readable.) -/
@[simps]
def isoOfEq {B : C} (X Y : Subobject B) (h : X = Y) : (X : C) ≅ (Y : C) 
goal: CategoryTheory.Subobject.underlying.obj X ≅ CategoryTheory.Subobject.underlying.obj Y

full_name: CategoryTheory.Subobject.isoOfEq_hom
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects.
(One could use `underlying.mapIso (eqToIso h))` here, but this is more readable.) -/
@[simps]
def isoOfEq {B : C} (X Y : Subobject B) (h : X = Y) : (X : C) ≅ (Y : C) 
goal: (X.isoOfEq Y h).hom = X.ofLE Y ⋯

full_name: CategoryTheory.Subobject.isoOfEq_inv
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects.
(One could use `underlying.mapIso (eqToIso h))` here, but this is more readable.) -/
@[simps]
def isoOfEq {B : C} (X Y : Subobject B) (h : X = Y) : (X : C) ≅ (Y : C) 
goal: (X.isoOfEq Y h).inv = Y.ofLE X ⋯

full_name: CategoryTheory.Subobject.isoOfEqMk
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfEqMk {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (h : X = mk f) : (X : C) ≅ A 
goal: CategoryTheory.Subobject.underlying.obj X ≅ A

full_name: CategoryTheory.Subobject.isoOfEqMk_inv
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfEqMk {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (h : X = mk f) : (X : C) ≅ A 
goal: (X.isoOfEqMk f h).inv = CategoryTheory.Subobject.ofMkLE f X ⋯

full_name: CategoryTheory.Subobject.isoOfEqMk_hom
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfEqMk {B A : C} (X : Subobject B) (f : A ⟶ B) [Mono f] (h : X = mk f) : (X : C) ≅ A 
goal: (X.isoOfEqMk f h).hom = X.ofLEMk f ⋯

full_name: CategoryTheory.Subobject.isoOfMkEq_hom
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEq {B A : C} (f : A ⟶ B) [Mono f] (X : Subobject B) (h : mk f = X) : A ≅ (X : C) 
goal: (CategoryTheory.Subobject.isoOfMkEq f X h).hom = CategoryTheory.Subobject.ofMkLE f X ⋯

full_name: CategoryTheory.Subobject.isoOfMkEq
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEq {B A : C} (f : A ⟶ B) [Mono f] (X : Subobject B) (h : mk f = X) : A ≅ (X : C) 
goal: A ≅ CategoryTheory.Subobject.underlying.obj X

full_name: CategoryTheory.Subobject.isoOfMkEq_inv
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEq {B A : C} (f : A ⟶ B) [Mono f] (X : Subobject B) (h : mk f = X) : A ≅ (X : C) 
goal: (CategoryTheory.Subobject.isoOfMkEq f X h).inv = X.ofLEMk f ⋯

full_name: CategoryTheory.Subobject.isoOfMkEqMk_inv
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEqMk {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (h : mk f = mk g) :
    A₁ ≅ A₂ 
goal: (CategoryTheory.Subobject.isoOfMkEqMk f g h).inv = CategoryTheory.Subobject.ofMkLEMk g f ⋯

full_name: CategoryTheory.Subobject.isoOfMkEqMk
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEqMk {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (h : mk f = mk g) :
    A₁ ≅ A₂ 
goal: A₁ ≅ A₂

full_name: CategoryTheory.Subobject.isoOfMkEqMk_hom
code: /-- An equality of subobjects gives an isomorphism of the corresponding objects. -/
@[simps]
def isoOfMkEqMk {B A₁ A₂ : C} (f : A₁ ⟶ B) (g : A₂ ⟶ B) [Mono f] [Mono g] (h : mk f = mk g) :
    A₁ ≅ A₂ 
goal: (CategoryTheory.Subobject.isoOfMkEqMk f g h).hom = CategoryTheory.Subobject.ofMkLEMk f g ⋯

full_name: CategoryTheory.Subobject.lower
code: /-- Any functor `MonoOver X ⥤ MonoOver Y` descends to a functor
`Subobject X ⥤ Subobject Y`, because `MonoOver Y` is thin. -/
def lower {Y : D} (F : MonoOver X ⥤ MonoOver Y) : Subobject X ⥤ Subobject Y 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X) (CategoryTheory.Subobject Y)

full_name: CategoryTheory.Subobject.lower_iso
code: /-- Isomorphic functors become equal when lowered to `Subobject`.
(It's not as evil as usual to talk about equality between functors
because the categories are thin and skeletal.) -/
theorem lower_iso (F₁ F₂ : MonoOver X ⥤ MonoOver Y) (h : F₁ ≅ F₂) : lower F₁ = lower F₂ 
goal: CategoryTheory.Subobject.lower F₁ = CategoryTheory.Subobject.lower F₂

full_name: CategoryTheory.Subobject.lower₂
code: /-- A ternary version of `Subobject.lower`. -/
def lower₂ (F : MonoOver X ⥤ MonoOver Y ⥤ MonoOver Z) : Subobject X ⥤ Subobject Y ⥤ Subobject Z 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X)
  (CategoryTheory.Functor (CategoryTheory.Subobject Y) (CategoryTheory.Subobject Z))

full_name: CategoryTheory.Subobject.lower_comm
code: @[simp]
theorem lower_comm (F : MonoOver Y ⥤ MonoOver X) :
    toThinSkeleton _ ⋙ lower F = F ⋙ toThinSkeleton _ 
goal: (CategoryTheory.toThinSkeleton (CategoryTheory.MonoOver Y)).comp (CategoryTheory.Subobject.lower F) =
  F.comp (CategoryTheory.toThinSkeleton (CategoryTheory.MonoOver X))

full_name: CategoryTheory.Subobject.lowerAdjunction
code: /-- An adjunction between `MonoOver A` and `MonoOver B` gives an adjunction
between `Subobject A` and `Subobject B`. -/
def lowerAdjunction {A : C} {B : D} {L : MonoOver A ⥤ MonoOver B} {R : MonoOver B ⥤ MonoOver A}
    (h : L ⊣ R) : lower L ⊣ lower R 
goal: CategoryTheory.Subobject.lower L ⊣ CategoryTheory.Subobject.lower R

full_name: CategoryTheory.Subobject.lowerEquivalence_inverse
code: /-- An equivalence between `MonoOver A` and `MonoOver B` gives an equivalence
between `Subobject A` and `Subobject B`. -/
@[simps]
def lowerEquivalence {A : C} {B : D} (e : MonoOver A ≌ MonoOver B) : Subobject A ≌ Subobject B 
goal: (CategoryTheory.Subobject.lowerEquivalence e).inverse = CategoryTheory.Subobject.lower e.inverse

full_name: CategoryTheory.Subobject.lowerEquivalence_unitIso
code: /-- An equivalence between `MonoOver A` and `MonoOver B` gives an equivalence
between `Subobject A` and `Subobject B`. -/
@[simps]
def lowerEquivalence {A : C} {B : D} (e : MonoOver A ≌ MonoOver B) : Subobject A ≌ Subobject B 
goal: (CategoryTheory.Subobject.lowerEquivalence e).unitIso = CategoryTheory.eqToIso ⋯

full_name: CategoryTheory.Subobject.lowerEquivalence_counitIso
code: /-- An equivalence between `MonoOver A` and `MonoOver B` gives an equivalence
between `Subobject A` and `Subobject B`. -/
@[simps]
def lowerEquivalence {A : C} {B : D} (e : MonoOver A ≌ MonoOver B) : Subobject A ≌ Subobject B 
goal: (CategoryTheory.Subobject.lowerEquivalence e).counitIso = CategoryTheory.eqToIso ⋯

full_name: CategoryTheory.Subobject.lowerEquivalence_functor
code: /-- An equivalence between `MonoOver A` and `MonoOver B` gives an equivalence
between `Subobject A` and `Subobject B`. -/
@[simps]
def lowerEquivalence {A : C} {B : D} (e : MonoOver A ≌ MonoOver B) : Subobject A ≌ Subobject B 
goal: (CategoryTheory.Subobject.lowerEquivalence e).functor = CategoryTheory.Subobject.lower e.functor

full_name: CategoryTheory.Subobject.lowerEquivalence
code: /-- An equivalence between `MonoOver A` and `MonoOver B` gives an equivalence
between `Subobject A` and `Subobject B`. -/
@[simps]
def lowerEquivalence {A : C} {B : D} (e : MonoOver A ≌ MonoOver B) : Subobject A ≌ Subobject B 
goal: CategoryTheory.Subobject A ≌ CategoryTheory.Subobject B

full_name: CategoryTheory.Subobject.pullback
code: /-- When `C` has pullbacks, a morphism `f : X ⟶ Y` induces a functor `Subobject Y ⥤ Subobject X`,
by pulling back a monomorphism along `f`. -/
def pullback (f : X ⟶ Y) : Subobject Y ⥤ Subobject X 
goal: CategoryTheory.Functor (CategoryTheory.Subobject Y) (CategoryTheory.Subobject X)

full_name: CategoryTheory.Subobject.pullback_id
code: theorem pullback_id (x : Subobject X) : (pullback (𝟙 X)).obj x = x 
goal: (CategoryTheory.Subobject.pullback (CategoryTheory.CategoryStruct.id X)).obj x = x

full_name: CategoryTheory.Subobject.pullback_comp
code: theorem pullback_comp (f : X ⟶ Y) (g : Y ⟶ Z) (x : Subobject Z) :
    (pullback (f ≫ g)).obj x = (pullback f).obj ((pullback g).obj x) 
goal: (CategoryTheory.Subobject.pullback (CategoryTheory.CategoryStruct.comp f g)).obj x =
  (CategoryTheory.Subobject.pullback f).obj ((CategoryTheory.Subobject.pullback g).obj x)

full_name: CategoryTheory.Subobject.instFaithfulPullback
code: instance (f : X ⟶ Y) : (pullback f).Faithful 
goal: (CategoryTheory.Subobject.pullback f).Faithful

full_name: CategoryTheory.Subobject.map
code: /-- We can map subobjects of `X` to subobjects of `Y`
by post-composition with a monomorphism `f : X ⟶ Y`.
-/
def map (f : X ⟶ Y) [Mono f] : Subobject X ⥤ Subobject Y 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X) (CategoryTheory.Subobject Y)

full_name: CategoryTheory.Subobject.map_id
code: theorem map_id (x : Subobject X) : (map (𝟙 X)).obj x = x 
goal: (CategoryTheory.Subobject.map (CategoryTheory.CategoryStruct.id X)).obj x = x

full_name: CategoryTheory.Subobject.map_comp
code: theorem map_comp (f : X ⟶ Y) (g : Y ⟶ Z) [Mono f] [Mono g] (x : Subobject X) :
    (map (f ≫ g)).obj x = (map g).obj ((map f).obj x) 
goal: (CategoryTheory.Subobject.map (CategoryTheory.CategoryStruct.comp f g)).obj x =
  (CategoryTheory.Subobject.map g).obj ((CategoryTheory.Subobject.map f).obj x)

full_name: CategoryTheory.Subobject.mapIso
code: /-- Isomorphic objects have equivalent subobject lattices. -/
def mapIso {A B : C} (e : A ≅ B) : Subobject A ≌ Subobject B 
goal: CategoryTheory.Subobject A ≌ CategoryTheory.Subobject B

full_name: CategoryTheory.Subobject.mapIsoToOrderIso
code: /-- In fact, there's a type level bijection between the subobjects of isomorphic objects,
which preserves the order. -/
def mapIsoToOrderIso (e : X ≅ Y) : Subobject X ≃o Subobject Y 
goal: CategoryTheory.Subobject X ≃o CategoryTheory.Subobject Y

full_name: CategoryTheory.Subobject.mapIsoToOrderIso_apply
code: @[simp]
theorem mapIsoToOrderIso_apply (e : X ≅ Y) (P : Subobject X) :
    mapIsoToOrderIso e P = (map e.hom).obj P 
goal: (CategoryTheory.Subobject.mapIsoToOrderIso e) P = (CategoryTheory.Subobject.map e.hom).obj P

full_name: CategoryTheory.Subobject.mapIsoToOrderIso_symm_apply
code: @[simp]
theorem mapIsoToOrderIso_symm_apply (e : X ≅ Y) (Q : Subobject Y) :
    (mapIsoToOrderIso e).symm Q = (map e.inv).obj Q 
goal: (CategoryTheory.Subobject.mapIsoToOrderIso e).symm Q = (CategoryTheory.Subobject.map e.inv).obj Q

full_name: CategoryTheory.Subobject.mapPullbackAdj
code: /-- `map f : Subobject X ⥤ Subobject Y` is
the left adjoint of `pullback f : Subobject Y ⥤ Subobject X`. -/
def mapPullbackAdj [HasPullbacks C] (f : X ⟶ Y) [Mono f] : map f ⊣ pullback f 
goal: CategoryTheory.Subobject.map f ⊣ CategoryTheory.Subobject.pullback f

full_name: CategoryTheory.Subobject.pullback_map_self
code: @[simp]
theorem pullback_map_self [HasPullbacks C] (f : X ⟶ Y) [Mono f] (g : Subobject X) :
    (pullback f).obj ((map f).obj g) = g 
goal: (CategoryTheory.Subobject.pullback f).obj ((CategoryTheory.Subobject.map f).obj g) = g

full_name: CategoryTheory.Subobject.map_pullback
code: theorem map_pullback [HasPullbacks C] {X Y Z W : C} {f : X ⟶ Y} {g : X ⟶ Z} {h : Y ⟶ W} {k : Z ⟶ W}
    [Mono h] [Mono g] (comm : f ≫ h = g ≫ k) (t : IsLimit (PullbackCone.mk f g comm))
    (p : Subobject Y) : (map g).obj ((pullback f).obj p) = (pullback k).obj ((map h).obj p) 
goal: (CategoryTheory.Subobject.map g).obj ((CategoryTheory.Subobject.pullback f).obj p) =
  (CategoryTheory.Subobject.pullback k).obj ((CategoryTheory.Subobject.map h).obj p)

full_name: CategoryTheory.Subobject.exists
code: /-- The functor from subobjects of `X` to subobjects of `Y` given by
sending the subobject `S` to its "image" under `f`, usually denoted $\exists_f$.
For instance, when `C` is the category of types,
viewing `Subobject X` as `Set X` this is just `Set.image f`.

This functor is left adjoint to the `pullback f` functor (shown in `existsPullbackAdj`)
provided both are defined, and generalises the `map f` functor, again provided it is defined.
-/
def «exists» (f : X ⟶ Y) : Subobject X ⥤ Subobject Y 
goal: CategoryTheory.Functor (CategoryTheory.Subobject X) (CategoryTheory.Subobject Y)

full_name: CategoryTheory.Subobject.exists_iso_map
code: /-- When `f : X ⟶ Y` is a monomorphism, `exists f` agrees with `map f`.
-/
theorem exists_iso_map (f : X ⟶ Y) [Mono f] : «exists» f = map f 
goal: CategoryTheory.Subobject.exists f = CategoryTheory.Subobject.map f

full_name: CategoryTheory.Subobject.existsPullbackAdj
code: /-- `exists f : Subobject X ⥤ Subobject Y` is
left adjoint to `pullback f : Subobject Y ⥤ Subobject X`.
-/
def existsPullbackAdj (f : X ⟶ Y) [HasPullbacks C] : «exists» f ⊣ pullback f 
goal: CategoryTheory.Subobject.exists f ⊣ CategoryTheory.Subobject.pullback f