Module docstring
{"# Initial and terminal objects in a category.
{"# Initial and terminal objects in a category.
CategoryTheory.Limits.HasTerminal
      abbrev
    
        /-- A category has a terminal object if it has a limit over the empty diagram.
Use `hasTerminal_of_unique` to construct instances.
-/
abbrev HasTerminal :=
  HasLimitsOfShape (Discrete.{0} PEmpty) C
        CategoryTheory.Limits.HasInitial
      abbrev
    
        /-- A category has an initial object if it has a colimit over the empty diagram.
Use `hasInitial_of_unique` to construct instances.
-/
abbrev HasInitial :=
  HasColimitsOfShape (Discrete.{0} PEmpty) C
        CategoryTheory.Limits.hasTerminalChangeDiagram
      theorem
     (h : HasLimit F₁) : HasLimit F₂
        theorem hasTerminalChangeDiagram (h : HasLimit F₁) : HasLimit F₂ :=
  ⟨⟨⟨⟨limit F₁, by aesop_cat, by simp⟩,
    isLimitChangeEmptyCone C (limit.isLimit F₁) _ (eqToIso rfl)⟩⟩⟩
        CategoryTheory.Limits.hasTerminalChangeUniverse
      theorem
     [h : HasLimitsOfShape (Discrete.{w} PEmpty) C] : HasLimitsOfShape (Discrete.{w'} PEmpty) C
        theorem hasTerminalChangeUniverse [h : HasLimitsOfShape (Discrete.{w} PEmpty) C] :
    HasLimitsOfShape (Discrete.{w'} PEmpty) C where
  has_limit _ := hasTerminalChangeDiagram C (h.1 (Functor.empty C))
        CategoryTheory.Limits.hasInitialChangeDiagram
      theorem
     (h : HasColimit F₁) : HasColimit F₂
        theorem hasInitialChangeDiagram (h : HasColimit F₁) : HasColimit F₂ :=
  ⟨⟨⟨⟨colimit F₁, by aesop_cat, by simp⟩,
    isColimitChangeEmptyCocone C (colimit.isColimit F₁) _ (eqToIso rfl)⟩⟩⟩
        CategoryTheory.Limits.hasInitialChangeUniverse
      theorem
     [h : HasColimitsOfShape (Discrete.{w} PEmpty) C] : HasColimitsOfShape (Discrete.{w'} PEmpty) C
        theorem hasInitialChangeUniverse [h : HasColimitsOfShape (Discrete.{w} PEmpty) C] :
    HasColimitsOfShape (Discrete.{w'} PEmpty) C where
  has_colimit _ := hasInitialChangeDiagram C (h.1 (Functor.empty C))
        CategoryTheory.Limits.terminal
      abbrev
     [HasTerminal C] : C
        /-- An arbitrary choice of terminal object, if one exists.
You can use the notation `⊤_ C`.
This object is characterized by having a unique morphism from any object.
-/
abbrev terminal [HasTerminal C] : C :=
  limit (Functor.empty.{0} C)
        CategoryTheory.Limits.initial
      abbrev
     [HasInitial C] : C
        /-- An arbitrary choice of initial object, if one exists.
You can use the notation `⊥_ C`.
This object is characterized by having a unique morphism to any object.
-/
abbrev initial [HasInitial C] : C :=
  colimit (Functor.empty.{0} C)
        CategoryTheory.Limits.term⊤__
      definition
     : Lean.ParserDescr✝
        
      CategoryTheory.Limits.term⊥__
      definition
     : Lean.ParserDescr✝
        
      CategoryTheory.Limits.hasTerminal_of_unique
      theorem
     (X : C) [∀ Y, Nonempty (Y ⟶ X)] [∀ Y, Subsingleton (Y ⟶ X)] : HasTerminal C
        /-- We can more explicitly show that a category has a terminal object by specifying the object,
and showing there is a unique morphism to it from any other object. -/
theorem hasTerminal_of_unique (X : C) [∀ Y, Nonempty (Y ⟶ X)] [∀ Y, Subsingleton (Y ⟶ X)] :
    HasTerminal C where
  has_limit F := .mk ⟨_, (isTerminalEquivUnique F X).invFun fun _ ↦
    ⟨Classical.inhabited_of_nonempty', (Subsingleton.elim · _)⟩⟩
        CategoryTheory.Limits.IsTerminal.hasTerminal
      theorem
     {X : C} (h : IsTerminal X) : HasTerminal C
        theorem IsTerminal.hasTerminal {X : C} (h : IsTerminal X) : HasTerminal C :=
  { has_limit := fun F => HasLimit.mk ⟨⟨X, by aesop_cat, by simp⟩,
    isLimitChangeEmptyCone _ h _ (Iso.refl _)⟩ }
        CategoryTheory.Limits.hasInitial_of_unique
      theorem
     (X : C) [∀ Y, Nonempty (X ⟶ Y)] [∀ Y, Subsingleton (X ⟶ Y)] : HasInitial C
        /-- We can more explicitly show that a category has an initial object by specifying the object,
and showing there is a unique morphism from it to any other object. -/
theorem hasInitial_of_unique (X : C) [∀ Y, Nonempty (X ⟶ Y)] [∀ Y, Subsingleton (X ⟶ Y)] :
    HasInitial C where
  has_colimit F := .mk ⟨_, (isInitialEquivUnique F X).invFun fun _ ↦
    ⟨Classical.inhabited_of_nonempty', (Subsingleton.elim · _)⟩⟩
        CategoryTheory.Limits.IsInitial.hasInitial
      theorem
     {X : C} (h : IsInitial X) : HasInitial C
        theorem IsInitial.hasInitial {X : C} (h : IsInitial X) : HasInitial C where
  has_colimit F :=
    HasColimit.mk ⟨⟨X, by aesop_cat, by simp⟩, isColimitChangeEmptyCocone _ h _ (Iso.refl _)⟩
        CategoryTheory.Limits.terminal.from
      abbrev
     [HasTerminal C] (P : C) : P ⟶ ⊤_ C
        /-- The map from an object to the terminal object. -/
abbrev terminal.from [HasTerminal C] (P : C) : P ⟶ ⊤_ C :=
  limit.lift (Functor.empty C) (asEmptyCone P)
        CategoryTheory.Limits.initial.to
      abbrev
     [HasInitial C] (P : C) : ⊥_ C ⟶ P
        /-- The map to an object from the initial object. -/
abbrev initial.to [HasInitial C] (P : C) : ⊥_ C⊥_ C ⟶ P :=
  colimit.desc (Functor.empty C) (asEmptyCocone P)
        CategoryTheory.Limits.terminalIsTerminal
      definition
     [HasTerminal C] : IsTerminal (⊤_ C)
        /-- A terminal object is terminal. -/
def terminalIsTerminal [HasTerminal C] : IsTerminal (⊤_ C) where
  lift _ := terminal.from _
        CategoryTheory.Limits.initialIsInitial
      definition
     [HasInitial C] : IsInitial (⊥_ C)
        /-- An initial object is initial. -/
def initialIsInitial [HasInitial C] : IsInitial (⊥_ C) where
  desc _ := initial.to _
        CategoryTheory.Limits.uniqueToTerminal
      instance
     [HasTerminal C] (P : C) : Unique (P ⟶ ⊤_ C)
        instance uniqueToTerminal [HasTerminal C] (P : C) : Unique (P ⟶ ⊤_ C) :=
  isTerminalEquivUnique _ (⊤_ C) terminalIsTerminal P
        CategoryTheory.Limits.uniqueFromInitial
      instance
     [HasInitial C] (P : C) : Unique (⊥_ C ⟶ P)
        instance uniqueFromInitial [HasInitial C] (P : C) : Unique (⊥_ C⊥_ C ⟶ P) :=
  isInitialEquivUnique _ (⊥_ C) initialIsInitial P
        CategoryTheory.Limits.terminal.hom_ext
      theorem
     [HasTerminal C] {P : C} (f g : P ⟶ ⊤_ C) : f = g
        @[ext] theorem terminal.hom_ext [HasTerminal C] {P : C} (f g : P ⟶ ⊤_ C) : f = g := by ext ⟨⟨⟩⟩
        CategoryTheory.Limits.initial.hom_ext
      theorem
     [HasInitial C] {P : C} (f g : ⊥_ C ⟶ P) : f = g
        @[ext] theorem initial.hom_ext [HasInitial C] {P : C} (f g : ⊥_ C⊥_ C ⟶ P) : f = g := by ext ⟨⟨⟩⟩
        CategoryTheory.Limits.terminal.comp_from
      theorem
     [HasTerminal C] {P Q : C} (f : P ⟶ Q) : f ≫ terminal.from Q = terminal.from P
        @[reassoc (attr := simp)]
theorem terminal.comp_from [HasTerminal C] {P Q : C} (f : P ⟶ Q) :
    f ≫ terminal.from Q = terminal.from P := by
  simp [eq_iff_true_of_subsingleton]
        CategoryTheory.Limits.initial.to_comp
      theorem
     [HasInitial C] {P Q : C} (f : P ⟶ Q) : initial.to P ≫ f = initial.to Q
        @[simp, reassoc]
theorem initial.to_comp [HasInitial C] {P Q : C} (f : P ⟶ Q) : initial.toinitial.to P ≫ f = initial.to Q := by
  simp [eq_iff_true_of_subsingleton]
        CategoryTheory.Limits.initialIsoIsInitial
      definition
     [HasInitial C] {P : C} (t : IsInitial P) : ⊥_ C ≅ P
        /-- The (unique) isomorphism between the chosen initial object and any other initial object. -/
@[simps!]
def initialIsoIsInitial [HasInitial C] {P : C} (t : IsInitial P) : ⊥_ C⊥_ C ≅ P :=
  initialIsInitial.uniqueUpToIso t
        CategoryTheory.Limits.terminalIsoIsTerminal
      definition
     [HasTerminal C] {P : C} (t : IsTerminal P) : ⊤_ C ≅ P
        /-- The (unique) isomorphism between the chosen terminal object and any other terminal object. -/
@[simps!]
def terminalIsoIsTerminal [HasTerminal C] {P : C} (t : IsTerminal P) : ⊤_ C⊤_ C ≅ P :=
  terminalIsTerminal.uniqueUpToIso t
        CategoryTheory.Limits.terminal.isSplitMono_from
      instance
     {Y : C} [HasTerminal C] (f : ⊤_ C ⟶ Y) : IsSplitMono f
        /-- Any morphism from a terminal object is split mono. -/
instance terminal.isSplitMono_from {Y : C} [HasTerminal C] (f : ⊤_ C⊤_ C ⟶ Y) : IsSplitMono f :=
  IsTerminal.isSplitMono_from terminalIsTerminal _
        CategoryTheory.Limits.initial.isSplitEpi_to
      instance
     {Y : C} [HasInitial C] (f : Y ⟶ ⊥_ C) : IsSplitEpi f
        /-- Any morphism to an initial object is split epi. -/
instance initial.isSplitEpi_to {Y : C} [HasInitial C] (f : Y ⟶ ⊥_ C) : IsSplitEpi f :=
  IsInitial.isSplitEpi_to initialIsInitial _
        CategoryTheory.Limits.hasInitial_op_of_hasTerminal
      instance
     [HasTerminal C] : HasInitial Cᵒᵖ
        instance hasInitial_op_of_hasTerminal [HasTerminal C] : HasInitial Cᵒᵖ :=
  (initialOpOfTerminal terminalIsTerminal).hasInitial
        CategoryTheory.Limits.hasTerminal_op_of_hasInitial
      instance
     [HasInitial C] : HasTerminal Cᵒᵖ
        instance hasTerminal_op_of_hasInitial [HasInitial C] : HasTerminal Cᵒᵖ :=
  (terminalOpOfInitial initialIsInitial).hasTerminal
        CategoryTheory.Limits.hasTerminal_of_hasInitial_op
      theorem
     [HasInitial Cᵒᵖ] : HasTerminal C
        theorem hasTerminal_of_hasInitial_op [HasInitial Cᵒᵖ] : HasTerminal C :=
  (terminalUnopOfInitial initialIsInitial).hasTerminal
        CategoryTheory.Limits.hasInitial_of_hasTerminal_op
      theorem
     [HasTerminal Cᵒᵖ] : HasInitial C
        theorem hasInitial_of_hasTerminal_op [HasTerminal Cᵒᵖ] : HasInitial C :=
  (initialUnopOfTerminal terminalIsTerminal).hasInitial
        CategoryTheory.Limits.instHasLimitObjFunctorConstTerminal
      instance
     {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C] :
  HasLimit ((CategoryTheory.Functor.const J).obj (⊤_ C))
        instance {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C] :
    HasLimit ((CategoryTheory.Functor.const J).obj (⊤_ C)) :=
  HasLimit.mk
    { cone :=
        { pt := ⊤_ C
          π := { app := fun _ => terminal.from _ } }
      isLimit := { lift := fun _ => terminal.from _ } }
        CategoryTheory.Limits.limitConstTerminal
      definition
     {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C] :
  limit ((CategoryTheory.Functor.const J).obj (⊤_ C)) ≅ ⊤_ C
        /-- The limit of the constant `⊤_ C` functor is `⊤_ C`. -/
@[simps hom]
def limitConstTerminal {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C] :
    limitlimit ((CategoryTheory.Functor.const J).obj (⊤_ C)) ≅ ⊤_ C where
  hom := terminal.from _
  inv :=
    limit.lift ((CategoryTheory.Functor.const J).obj (⊤_ C))
      { pt := ⊤_ C
        π := { app := fun _ => terminal.from _ } }
        CategoryTheory.Limits.limitConstTerminal_inv_π
      theorem
     {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C] {j : J} :
  limitConstTerminal.inv ≫ limit.π ((CategoryTheory.Functor.const J).obj (⊤_ C)) j = terminal.from _
        @[reassoc (attr := simp)]
theorem limitConstTerminal_inv_π {J : Type*} [Category J] {C : Type*} [Category C] [HasTerminal C]
    {j : J} :
    limitConstTerminallimitConstTerminal.inv ≫ limit.π ((CategoryTheory.Functor.const J).obj (⊤_ C)) j =
      terminal.from _ := by aesop_cat
        CategoryTheory.Limits.instHasColimitObjFunctorConstInitial
      instance
     {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C] :
  HasColimit ((CategoryTheory.Functor.const J).obj (⊥_ C))
        instance {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C] :
    HasColimit ((CategoryTheory.Functor.const J).obj (⊥_ C)) :=
  HasColimit.mk
    { cocone :=
        { pt := ⊥_ C
          ι := { app := fun _ => initial.to _ } }
      isColimit := { desc := fun _ => initial.to _ } }
        CategoryTheory.Limits.colimitConstInitial
      definition
     {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C] :
  colimit ((CategoryTheory.Functor.const J).obj (⊥_ C)) ≅ ⊥_ C
        /-- The colimit of the constant `⊥_ C` functor is `⊥_ C`. -/
@[simps inv]
def colimitConstInitial {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C] :
    colimitcolimit ((CategoryTheory.Functor.const J).obj (⊥_ C)) ≅ ⊥_ C where
  hom :=
    colimit.desc ((CategoryTheory.Functor.const J).obj (⊥_ C))
      { pt := ⊥_ C
        ι := { app := fun _ => initial.to _ } }
  inv := initial.to _
        CategoryTheory.Limits.ι_colimitConstInitial_hom
      theorem
     {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C] {j : J} :
  colimit.ι ((CategoryTheory.Functor.const J).obj (⊥_ C)) j ≫ colimitConstInitial.hom = initial.to _
        @[reassoc (attr := simp)]
theorem ι_colimitConstInitial_hom {J : Type*} [Category J] {C : Type*} [Category C] [HasInitial C]
    {j : J} :
    colimit.ιcolimit.ι ((CategoryTheory.Functor.const J).obj (⊥_ C)) j ≫ colimitConstInitial.hom =
      initial.to _ := by aesop_cat
        CategoryTheory.Limits.initial.mono_from
      instance
     [HasInitial C] [InitialMonoClass C] (X : C) (f : ⊥_ C ⟶ X) : Mono f
        instance (priority := 100) initial.mono_from [HasInitial C] [InitialMonoClass C] (X : C)
    (f : ⊥_ C⊥_ C ⟶ X) : Mono f :=
  initialIsInitial.mono_from f
        CategoryTheory.Limits.InitialMonoClass.of_initial
      theorem
     [HasInitial C] (h : ∀ X : C, Mono (initial.to X)) : InitialMonoClass C
        /-- To show a category is an `InitialMonoClass` it suffices to show every morphism out of the
initial object is a monomorphism. -/
theorem InitialMonoClass.of_initial [HasInitial C] (h : ∀ X : C, Mono (initial.to X)) :
    InitialMonoClass C :=
  InitialMonoClass.of_isInitial initialIsInitial h
        CategoryTheory.Limits.InitialMonoClass.of_terminal
      theorem
     [HasInitial C] [HasTerminal C] (h : Mono (initial.to (⊤_ C))) : InitialMonoClass C
        /-- To show a category is an `InitialMonoClass` it suffices to show the unique morphism from the
initial object to a terminal object is a monomorphism. -/
theorem InitialMonoClass.of_terminal [HasInitial C] [HasTerminal C] (h : Mono (initial.to (⊤_ C))) :
    InitialMonoClass C :=
  InitialMonoClass.of_isTerminal initialIsInitial terminalIsTerminal h
        CategoryTheory.Limits.terminalComparison
      definition
     [HasTerminal C] [HasTerminal D] : G.obj (⊤_ C) ⟶ ⊤_ D
        /-- The comparison morphism from the image of a terminal object to the terminal object in the target
category.
This is an isomorphism iff `G` preserves terminal objects, see
`CategoryTheory.Limits.PreservesTerminal.ofIsoComparison`.
-/
def terminalComparison [HasTerminal C] [HasTerminal D] : G.obj (⊤_ C) ⟶ ⊤_ D :=
  terminal.from _
        CategoryTheory.Limits.initialComparison
      definition
     [HasInitial C] [HasInitial D] : ⊥_ D ⟶ G.obj (⊥_ C)
        /--
The comparison morphism from the initial object in the target category to the image of the initial
object.
-/
def initialComparison [HasInitial C] [HasInitial D] : ⊥_ D⊥_ D ⟶ G.obj (⊥_ C) :=
  initial.to _
        CategoryTheory.Limits.hasLimit_of_domain_hasInitial
      instance
     [HasInitial J] {F : J ⥤ C} : HasLimit F
        instance hasLimit_of_domain_hasInitial [HasInitial J] {F : J ⥤ C} : HasLimit F :=
  HasLimit.mk { cone := _, isLimit := limitOfDiagramInitial (initialIsInitial) F }
        CategoryTheory.Limits.limitOfInitial
      abbrev
     (F : J ⥤ C) [HasInitial J] : limit F ≅ F.obj (⊥_ J)
        /-- For a functor `F : J ⥤ C`, if `J` has an initial object then the image of it is isomorphic
to the limit of `F`. -/
abbrev limitOfInitial (F : J ⥤ C) [HasInitial J] : limitlimit F ≅ F.obj (⊥_ J) :=
  IsLimit.conePointUniqueUpToIso (limit.isLimit _) (limitOfDiagramInitial initialIsInitial F)
        CategoryTheory.Limits.hasLimit_of_domain_hasTerminal
      instance
     [HasTerminal J] {F : J ⥤ C} [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : HasLimit F
        instance hasLimit_of_domain_hasTerminal [HasTerminal J] {F : J ⥤ C}
    [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : HasLimit F :=
  HasLimit.mk { cone := _, isLimit := limitOfDiagramTerminal (terminalIsTerminal) F }
        CategoryTheory.Limits.limitOfTerminal
      abbrev
     (F : J ⥤ C) [HasTerminal J] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : limit F ≅ F.obj (⊤_ J)
        /-- For a functor `F : J ⥤ C`, if `J` has a terminal object and all the morphisms in the diagram
are isomorphisms, then the image of the terminal object is isomorphic to the limit of `F`. -/
abbrev limitOfTerminal (F : J ⥤ C) [HasTerminal J] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] :
    limitlimit F ≅ F.obj (⊤_ J) :=
  IsLimit.conePointUniqueUpToIso (limit.isLimit _) (limitOfDiagramTerminal terminalIsTerminal F)
        CategoryTheory.Limits.hasColimit_of_domain_hasTerminal
      instance
     [HasTerminal J] {F : J ⥤ C} : HasColimit F
        instance hasColimit_of_domain_hasTerminal [HasTerminal J] {F : J ⥤ C} : HasColimit F :=
  HasColimit.mk { cocone := _, isColimit := colimitOfDiagramTerminal (terminalIsTerminal) F }
        CategoryTheory.Limits.colimitOfTerminal
      abbrev
     (F : J ⥤ C) [HasTerminal J] : colimit F ≅ F.obj (⊤_ J)
        /-- For a functor `F : J ⥤ C`, if `J` has a terminal object then the image of it is isomorphic
to the colimit of `F`. -/
abbrev colimitOfTerminal (F : J ⥤ C) [HasTerminal J] : colimitcolimit F ≅ F.obj (⊤_ J) :=
  IsColimit.coconePointUniqueUpToIso (colimit.isColimit _)
    (colimitOfDiagramTerminal terminalIsTerminal F)
        CategoryTheory.Limits.hasColimit_of_domain_hasInitial
      instance
     [HasInitial J] {F : J ⥤ C} [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : HasColimit F
        instance hasColimit_of_domain_hasInitial [HasInitial J] {F : J ⥤ C}
    [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : HasColimit F :=
  HasColimit.mk { cocone := _, isColimit := colimitOfDiagramInitial (initialIsInitial) F }
        CategoryTheory.Limits.colimitOfInitial
      abbrev
     (F : J ⥤ C) [HasInitial J] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : colimit F ≅ F.obj (⊥_ J)
        /-- For a functor `F : J ⥤ C`, if `J` has an initial object and all the morphisms in the diagram
are isomorphisms, then the image of the initial object is isomorphic to the colimit of `F`. -/
abbrev colimitOfInitial (F : J ⥤ C) [HasInitial J] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] :
    colimitcolimit F ≅ F.obj (⊥_ J) :=
  IsColimit.coconePointUniqueUpToIso (colimit.isColimit _)
    (colimitOfDiagramInitial initialIsInitial _)
        CategoryTheory.Limits.isIso_π_of_isInitial
      theorem
     {j : J} (I : IsInitial j) (F : J ⥤ C) [HasLimit F] : IsIso (limit.π F j)
        /-- If `j` is initial in the index category, then the map `limit.π F j` is an isomorphism.
-/
theorem isIso_π_of_isInitial {j : J} (I : IsInitial j) (F : J ⥤ C) [HasLimit F] :
    IsIso (limit.π F j) :=
  ⟨⟨limit.lift _ (coneOfDiagramInitial I F), ⟨by ext; simp, by simp⟩⟩⟩
        CategoryTheory.Limits.isIso_π_initial
      instance
     [HasInitial J] (F : J ⥤ C) : IsIso (limit.π F (⊥_ J))
        instance isIso_π_initial [HasInitial J] (F : J ⥤ C) : IsIso (limit.π F (⊥_ J)) :=
  isIso_π_of_isInitial initialIsInitial F
        CategoryTheory.Limits.isIso_π_of_isTerminal
      theorem
     {j : J} (I : IsTerminal j) (F : J ⥤ C) [HasLimit F] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (limit.π F j)
        theorem isIso_π_of_isTerminal {j : J} (I : IsTerminal j) (F : J ⥤ C) [HasLimit F]
    [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (limit.π F j) :=
  ⟨⟨limit.lift _ (coneOfDiagramTerminal I F), by ext; simp, by simp⟩⟩
        CategoryTheory.Limits.isIso_π_terminal
      instance
     [HasTerminal J] (F : J ⥤ C) [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (limit.π F (⊤_ J))
        instance isIso_π_terminal [HasTerminal J] (F : J ⥤ C) [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] :
    IsIso (limit.π F (⊤_ J)) :=
  isIso_π_of_isTerminal terminalIsTerminal F
        CategoryTheory.Limits.isIso_ι_of_isTerminal
      theorem
     {j : J} (I : IsTerminal j) (F : J ⥤ C) [HasColimit F] : IsIso (colimit.ι F j)
        /-- If `j` is terminal in the index category, then the map `colimit.ι F j` is an isomorphism.
-/
theorem isIso_ι_of_isTerminal {j : J} (I : IsTerminal j) (F : J ⥤ C) [HasColimit F] :
    IsIso (colimit.ι F j) :=
  ⟨⟨colimit.desc _ (coconeOfDiagramTerminal I F), ⟨by simp, by ext; simp⟩⟩⟩
        CategoryTheory.Limits.isIso_ι_terminal
      instance
     [HasTerminal J] (F : J ⥤ C) : IsIso (colimit.ι F (⊤_ J))
        instance isIso_ι_terminal [HasTerminal J] (F : J ⥤ C) : IsIso (colimit.ι F (⊤_ J)) :=
  isIso_ι_of_isTerminal terminalIsTerminal F
        CategoryTheory.Limits.isIso_ι_of_isInitial
      theorem
     {j : J} (I : IsInitial j) (F : J ⥤ C) [HasColimit F] [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (colimit.ι F j)
        theorem isIso_ι_of_isInitial {j : J} (I : IsInitial j) (F : J ⥤ C) [HasColimit F]
    [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (colimit.ι F j) :=
  ⟨⟨colimit.desc _ (coconeOfDiagramInitial I F), by
    refine ⟨?_, by ext; simp⟩
    dsimp; simp only [colimit.ι_desc, coconeOfDiagramInitial_pt, coconeOfDiagramInitial_ι_app,
      Functor.const_obj_obj, IsInitial.to_self, Functor.map_id]
    dsimp [inv]; simp only [Category.id_comp, Category.comp_id, and_self]
    apply @Classical.choose_spec _ (fun x => x = 𝟙 F.obj j) _
  ⟩⟩
        CategoryTheory.Limits.isIso_ι_initial
      instance
     [HasInitial J] (F : J ⥤ C) [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] : IsIso (colimit.ι F (⊥_ J))
        instance isIso_ι_initial [HasInitial J] (F : J ⥤ C) [∀ (i j : J) (f : i ⟶ j), IsIso (F.map f)] :
    IsIso (colimit.ι F (⊥_ J)) :=
  isIso_ι_of_isInitial initialIsInitial F