File: Mathlib/CategoryTheory/Limits/Shapes/ConcreteCategory.lean

full_name: CategoryTheory.Limits.Concrete.productEquiv
code: /-- The equivalence `(forget C).obj (∏ᶜ F) ≃ ∀ j, F j` if `F : J → C` is a family of objects
in a concrete category `C`. -/
noncomputable def productEquiv : (forget C).obj (∏ᶜ F) ≃ ∀ j, F j 
goal: (CategoryTheory.forget C).obj (∏ᶜ F) ≃ ((j : J) → (CategoryTheory.forget C).obj (F j))

full_name: CategoryTheory.Limits.Concrete.productEquiv_apply_apply
code: @[simp]
lemma productEquiv_apply_apply (x : (forget C).obj (∏ᶜ F)) (j : J) :
    productEquiv F x j = Pi.π F j x 
goal: (CategoryTheory.Limits.Concrete.productEquiv F) x j = (CategoryTheory.Limits.Pi.π F j) x

full_name: CategoryTheory.Limits.Concrete.productEquiv_symm_apply_π
code: @[simp]
lemma productEquiv_symm_apply_π (x : ∀ j, F j) (j : J) :
    Pi.π F j ((productEquiv F).symm x) = x j 
goal: (CategoryTheory.Limits.Pi.π F j) ((CategoryTheory.Limits.Concrete.productEquiv F).symm x) = x j

full_name: CategoryTheory.Limits.Concrete.Pi.map_ext
code: lemma Pi.map_ext (x y : F.obj (∏ᶜ f : C))
    (h : ∀ i, F.map (Pi.π f i) x = F.map (Pi.π f i) y) : x = y 
goal: x = y

full_name: CategoryTheory.Limits.Concrete.uniqueOfTerminalOfPreserves
code: /-- If `forget C` preserves terminals and `X` is terminal, then `(forget C).obj X` is a
singleton. -/
noncomputable def uniqueOfTerminalOfPreserves [PreservesLimit (Functor.empty.{0} C) (forget C)]
    (X : C) (h : IsTerminal X) : Unique ((forget C).obj X) 
goal: Unique ((CategoryTheory.forget C).obj X)

full_name: CategoryTheory.Limits.Concrete.terminalOfUniqueOfReflects
code: /-- If `forget C` reflects terminals and `(forget C).obj X` is a singleton, then `X` is terminal. -/
noncomputable def terminalOfUniqueOfReflects [ReflectsLimit (Functor.empty.{0} C) (forget C)]
    (X : C) (h : Unique ((forget C).obj X)) : IsTerminal X 
goal: CategoryTheory.Limits.IsTerminal X

full_name: CategoryTheory.Limits.Concrete.terminalIffUnique
code: /-- The equivalence `IsTerminal X ≃ Unique ((forget C).obj X)` if the forgetful functor
preserves and reflects terminals. -/
noncomputable def terminalIffUnique [PreservesLimit (Functor.empty.{0} C) (forget C)]
    [ReflectsLimit (Functor.empty.{0} C) (forget C)] (X : C) :
    IsTerminal X ≃ Unique ((forget C).obj X) 
goal: CategoryTheory.Limits.IsTerminal X ≃ Unique ((CategoryTheory.forget C).obj X)

full_name: CategoryTheory.Limits.Concrete.terminalEquiv
code: /-- The equivalence `(forget C).obj (⊤_ C) ≃ PUnit` when `C` is a concrete category. -/
noncomputable def terminalEquiv : (forget C).obj (⊤_ C) ≃ PUnit 
goal: (CategoryTheory.forget C).obj (⊤_ C) ≃ PUnit.{w + 1}

full_name: CategoryTheory.Limits.Concrete.instUniqueObjForgetTerminal
code: noncomputable instance : Unique ((forget C).obj (⊤_ C)) 
goal: Unique ((CategoryTheory.forget C).obj (⊤_ C))

full_name: CategoryTheory.Limits.Concrete.empty_of_initial_of_preserves
code: /-- If `forget C` preserves initials and `X` is initial, then `(forget C).obj X` is empty. -/
lemma empty_of_initial_of_preserves [PreservesColimit (Functor.empty.{0} C) (forget C)] (X : C)
    (h : Nonempty (IsInitial X)) : IsEmpty ((forget C).obj X) 
goal: IsEmpty ((CategoryTheory.forget C).obj X)

full_name: CategoryTheory.Limits.Concrete.initial_of_empty_of_reflects
code: /-- If `forget C` reflects initials and `(forget C).obj X` is empty, then `X` is initial. -/
lemma initial_of_empty_of_reflects [ReflectsColimit (Functor.empty.{0} C) (forget C)] (X : C)
    (h : IsEmpty ((forget C).obj X)) : Nonempty (IsInitial X) 
goal: Nonempty (CategoryTheory.Limits.IsInitial X)

full_name: CategoryTheory.Limits.Concrete.initial_iff_empty_of_preserves_of_reflects
code: /-- If `forget C` preserves and reflects initials, then `X` is initial if and only if
`(forget C).obj X` is empty. -/
lemma initial_iff_empty_of_preserves_of_reflects [PreservesColimit (Functor.empty.{0} C) (forget C)]
    [ReflectsColimit (Functor.empty.{0} C) (forget C)] (X : C) :
    Nonempty (IsInitial X) ↔ IsEmpty ((forget C).obj X) 
goal: Nonempty (CategoryTheory.Limits.IsInitial X) ↔ IsEmpty ((CategoryTheory.forget C).obj X)

full_name: CategoryTheory.Limits.Concrete.prodEquiv
code: /-- The equivalence `(forget C).obj (X₁ ⨯ X₂) ≃ ((forget C).obj X₁) × ((forget C).obj X₂)`
if `X₁` and `X₂` are objects in a concrete category `C`. -/
noncomputable def prodEquiv : (forget C).obj (X₁ ⨯ X₂) ≃ X₁ × X₂ 
goal: (CategoryTheory.forget C).obj (X₁ ⨯ X₂) ≃ (CategoryTheory.forget C).obj X₁ × (CategoryTheory.forget C).obj X₂

full_name: CategoryTheory.Limits.Concrete.prodEquiv_apply_fst
code: @[simp]
lemma prodEquiv_apply_fst (x : (forget C).obj (X₁ ⨯ X₂)) :
    (prodEquiv X₁ X₂ x).fst = (Limits.prod.fst : X₁ ⨯ X₂ ⟶ X₁) x 
goal: ((CategoryTheory.Limits.Concrete.prodEquiv X₁ X₂) x).1 = CategoryTheory.Limits.prod.fst x

full_name: CategoryTheory.Limits.Concrete.prodEquiv_apply_snd
code: @[simp]
lemma prodEquiv_apply_snd (x : (forget C).obj (X₁ ⨯ X₂)) :
    (prodEquiv X₁ X₂ x).snd = (Limits.prod.snd : X₁ ⨯ X₂ ⟶ X₂) x 
goal: ((CategoryTheory.Limits.Concrete.prodEquiv X₁ X₂) x).2 = CategoryTheory.Limits.prod.snd x

full_name: CategoryTheory.Limits.Concrete.prodEquiv_symm_apply_fst
code: @[simp]
lemma prodEquiv_symm_apply_fst (x : X₁ × X₂) :
    (Limits.prod.fst : X₁ ⨯ X₂ ⟶ X₁) ((prodEquiv X₁ X₂).symm x) = x.1 
goal: CategoryTheory.Limits.prod.fst ((CategoryTheory.Limits.Concrete.prodEquiv X₁ X₂).symm x) = x.1

full_name: CategoryTheory.Limits.Concrete.prodEquiv_symm_apply_snd
code: @[simp]
lemma prodEquiv_symm_apply_snd (x : X₁ × X₂) :
    (Limits.prod.snd : X₁ ⨯ X₂ ⟶ X₂) ((prodEquiv X₁ X₂).symm x) = x.2 
goal: CategoryTheory.Limits.prod.snd ((CategoryTheory.Limits.Concrete.prodEquiv X₁ X₂).symm x) = x.2

full_name: CategoryTheory.Limits.Concrete.pullbackEquiv
code: /-- In a concrete category `C`, given two morphisms `f₁ : X₁ ⟶ S` and `f₂ : X₂ ⟶ S`,
the elements in `pullback f₁ f₁` can be identified to compatible tuples of
elements in `X₁` and `X₂`. -/
noncomputable def pullbackEquiv :
    (forget C).obj (pullback f₁ f₂) ≃ { p : X₁ × X₂ // f₁ p.1 = f₂ p.2 } 
goal: (CategoryTheory.forget C).obj (CategoryTheory.Limits.pullback f₁ f₂) ≃ { p // f₁ p.1 = f₂ p.2 }

full_name: CategoryTheory.Limits.Concrete.pullbackMk
code: /-- Constructor for elements in a pullback in a concrete category. -/
noncomputable def pullbackMk (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂) :
    (forget C).obj (pullback f₁ f₂) 
goal: (CategoryTheory.forget C).obj (CategoryTheory.Limits.pullback f₁ f₂)

full_name: CategoryTheory.Limits.Concrete.pullbackMk_surjective
code: lemma pullbackMk_surjective (x : (forget C).obj (pullback f₁ f₂)) :
    ∃ (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂), x = pullbackMk f₁ f₂ x₁ x₂ h 
goal: ∃ x₁ x₂, ∃ (h : f₁ x₁ = f₂ x₂), x = CategoryTheory.Limits.Concrete.pullbackMk f₁ f₂ x₁ x₂ h

full_name: CategoryTheory.Limits.Concrete.pullbackMk_fst
code: @[simp]
lemma pullbackMk_fst (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂) :
    pullback.fst f₁ f₂ (pullbackMk f₁ f₂ x₁ x₂ h) = x₁ 
goal: (CategoryTheory.Limits.pullback.fst f₁ f₂) (CategoryTheory.Limits.Concrete.pullbackMk f₁ f₂ x₁ x₂ h) = x₁

full_name: CategoryTheory.Limits.Concrete.pullbackMk_snd
code: @[simp]
lemma pullbackMk_snd (x₁ : X₁) (x₂ : X₂) (h : f₁ x₁ = f₂ x₂) :
    pullback.snd f₁ f₂ (pullbackMk f₁ f₂ x₁ x₂ h) = x₂ 
goal: (CategoryTheory.Limits.pullback.snd f₁ f₂) (CategoryTheory.Limits.Concrete.pullbackMk f₁ f₂ x₁ x₂ h) = x₂

full_name: CategoryTheory.Limits.Concrete.widePullback_ext
code: theorem widePullback_ext {B : C} {ι : Type w} {X : ι → C} (f : ∀ j : ι, X j ⟶ B)
    [HasWidePullback B X f] [PreservesLimit (wideCospan B X f) (forget C)]
    (x y : ↑(widePullback B X f)) (h₀ : base f x = base f y) (h : ∀ j, π f j x = π f j y) :
    x = y 
goal: x = y

full_name: CategoryTheory.Limits.Concrete.widePullback_ext'
code: theorem widePullback_ext' {B : C} {ι : Type w} [Nonempty ι] {X : ι → C}
    (f : ∀ j : ι, X j ⟶ B) [HasWidePullback.{w} B X f]
    [PreservesLimit (wideCospan B X f) (forget C)] (x y : ↑(widePullback B X f))
    (h : ∀ j, π f j x = π f j y) : x = y 
goal: x = y

full_name: CategoryTheory.Limits.Concrete.multiequalizer_ext
code: theorem multiequalizer_ext {I : MulticospanIndex.{w} C} [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x y : ↑(multiequalizer I))
    (h : ∀ t : I.L, Multiequalizer.ι I t x = Multiequalizer.ι I t y) : x = y 
goal: x = y

full_name: CategoryTheory.Limits.Concrete.multiequalizerEquivAux
code: /-- An auxiliary equivalence to be used in `multiequalizerEquiv` below. -/
def multiequalizerEquivAux (I : MulticospanIndex C) :
    (I.multicospan ⋙ forget C).sections ≃
    { x : ∀ i : I.L, I.left i // ∀ i : I.R, I.fst i (x _) = I.snd i (x _) } 
goal: ↑(I.multicospan.comp (CategoryTheory.forget C)).sections ≃
  { x // ∀ (i : I.R), (I.fst i) (x (I.fstTo i)) = (I.snd i) (x (I.sndTo i)) }

full_name: CategoryTheory.Limits.Concrete.multiequalizerEquiv
code: /-- The equivalence between the noncomputable multiequalizer and
the concrete multiequalizer. -/
noncomputable def multiequalizerEquiv (I : MulticospanIndex.{w} C) [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] :
    (multiequalizer I : C) ≃
      { x : ∀ i : I.L, I.left i // ∀ i : I.R, I.fst i (x _) = I.snd i (x _) } 
goal: (CategoryTheory.forget C).obj (CategoryTheory.Limits.multiequalizer I) ≃
  { x // ∀ (i : I.R), (I.fst i) (x (I.fstTo i)) = (I.snd i) (x (I.sndTo i)) }

full_name: CategoryTheory.Limits.Concrete.multiequalizerEquiv_apply
code: @[simp]
theorem multiequalizerEquiv_apply (I : MulticospanIndex.{w} C) [HasMultiequalizer I]
    [PreservesLimit I.multicospan (forget C)] (x : ↑(multiequalizer I)) (i : I.L) :
    ((Concrete.multiequalizerEquiv I) x : ∀ i : I.L, I.left i) i = Multiequalizer.ι I i x 
goal: ↑((CategoryTheory.Limits.Concrete.multiequalizerEquiv I) x) i = (CategoryTheory.Limits.Multiequalizer.ι I i) x

full_name: CategoryTheory.Limits.Concrete.widePushout_exists_rep
code: theorem widePushout_exists_rep {B : C} {α : Type _} {X : α → C} (f : ∀ j : α, B ⟶ X j)
    [HasWidePushout.{v} B X f] [PreservesColimit (wideSpan B X f) (forget C)]
    (x : ↑(widePushout B X f)) : (∃ y : B, head f y = x) ∨ ∃ (i : α) (y : X i), ι f i y = x 
goal: (∃ y, (CategoryTheory.Limits.WidePushout.head f) y = x) ∨ ∃ i y, (CategoryTheory.Limits.WidePushout.ι f i) y = x

full_name: CategoryTheory.Limits.Concrete.widePushout_exists_rep'
code: theorem widePushout_exists_rep' {B : C} {α : Type _} [Nonempty α] {X : α → C}
    (f : ∀ j : α, B ⟶ X j) [HasWidePushout.{v} B X f] [PreservesColimit (wideSpan B X f) (forget C)]
    (x : ↑(widePushout B X f)) : ∃ (i : α) (y : X i), ι f i y = x 
goal: ∃ i y, (CategoryTheory.Limits.WidePushout.ι f i) y = x

full_name: CategoryTheory.Limits.Concrete.cokernel_funext
code: theorem cokernel_funext {C : Type*} [Category C] [HasZeroMorphisms C] [ConcreteCategory C]
    {M N K : C} {f : M ⟶ N} [HasCokernel f] {g h : cokernel f ⟶ K}
    (w : ∀ n : N, g (cokernel.π f n) = h (cokernel.π f n)) : g = h 
goal: g = h