[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
instance pullback.snd_of_mono {X Y Z : C} {f : X ⟶ Z} {g : Y ⟶ Z} [HasPullback f g] [Mono f] :
    Mono (pullback.snd f g)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_snd_of_is_pullback_of_mono (L50-L56)
theorem mono_snd_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono f] :
    Mono t.snd := by
refine ⟨fun {W} h k i => IsLimit.hom_ext ht ?_ i⟩
  rw [← cancel_mono f, Category.assoc, Category.assoc, condition]
  apply reassoc_of% i

/-- Monomorphisms are stable under pullback in the second argument. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_fst_of_is_pullback_of_mono (L57-L66)
theorem mono_fst_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono g] :
    Mono t.fst := by
refine ⟨fun {W} h k i => IsLimit.hom_ext ht i ?_⟩
  rw [← cancel_mono g, Category.assoc, Category.assoc, ← condition]
  apply reassoc_of% i

/--
The pullback cone `(𝟙 X, 𝟙 X)` for the pair `(f, f)` is a limit if `f` is a mono. The converse is
shown in `mono_of_pullback_is_id`.
-/
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitMkIdId (L67-L75)
def isLimitMkIdId (f : X ⟶ Y) [Mono f] : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f) :=
IsLimit.mk _ (fun s => s.fst) (fun _ => Category.comp_id _)
    (fun s => by rw [← cancel_mono f, Category.comp_id, s.condition]) fun s m m₁ _ => by
    simpa using m₁

/--
`f` is a mono if the pullback cone `(𝟙 X, 𝟙 X)` is a limit for the pair `(f, f)`. The converse is
given in `PullbackCone.is_id_of_mono`.
-/
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_of_isLimitMkIdId (L76-L85)
theorem mono_of_isLimitMkIdId (f : X ⟶ Y) (t : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f)) :
    Mono f :=
⟨fun {Z} g h eq => by
    rcases PullbackCone.IsLimit.lift' t _ _ eq with ⟨_, rfl, rfl⟩
    rfl⟩

set_option backward.isDefEq.respectTransparency false in
/-- Suppose `f` and `g` are two morphisms with a common codomain and `s` is a limit cone over the
diagram formed by `f` and `g`. Suppose `f` and `g` both factor through a monomorphism `h` via
`x` and `y`, respectively.  Then `s` is also a limit cone over the diagram formed by `x` and `y`. -/
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitOfFactors (L86-L104)
def isLimitOfFactors (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ Z) [Mono h] (x : X ⟶ W) (y : Y ⟶ W)
    (hxh : x ≫ h = f) (hyh : y ≫ h = g) (s : PullbackCone f g) (hs : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ x = s.snd ≫ y from
          (cancel_mono h).1 <| by simp only [Category.assoc, hxh, hyh, s.condition])) :=
PullbackCone.isLimitAux' _ fun t =>
    have : fst t ≫ x ≫ h = snd t ≫ y ≫ h := by  -- Porting note: reassoc workaround
      rw [← Category.assoc, ← Category.assoc]
      apply congrArg (· ≫ h) t.condition
    ⟨hs.lift (PullbackCone.mk t.fst t.snd <| by rw [← hxh, ← hyh, this]),
      ⟨hs.fac _ WalkingCospan.left, hs.fac _ WalkingCospan.right, fun hr hr' => by
        apply PullbackCone.IsLimit.hom_ext hs <;>
              simp only [PullbackCone.mk_fst, PullbackCone.mk_snd] at hr hr' ⊢ <;>
            simp only [hr, hr'] <;>
          symm
        exacts [hs.fac _ WalkingCospan.left, hs.fac _ WalkingCospan.right]⟩⟩

/-- If `W` is the pullback of `f, g`, it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitOfCompMono (L105-L124)
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine ⟨l, h₁, h₂, ?_⟩
  intro m hm₁ hm₂
  exact (PullbackCone.IsLimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) :)

end PullbackCone

end Monomorphisms

/-- The pullback of a monomorphism is a monomorphism -/
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_pullback_to_prod (L136-L151)
instance mono_pullback_to_prod {C : Type*} [Category* C] {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z)
    [HasPullback f g] [HasBinaryProduct X Y] :
    Mono (prod.lift (pullback.fst f g) (pullback.snd f g)) :=
⟨fun {W} i₁ i₂ h => by
    ext
    · simpa using congrArg (fun f => f ≫ prod.fst) h
    · simpa using congrArg (fun f => f ≫ prod.snd) h⟩

/-- The pullback of `f, g` is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
noncomputable def pullbackIsPullbackOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i]
    [HasPullback f g] : IsLimit (PullbackCone.mk (pullback.fst f g) (pullback.snd f g)
      -- Porting note: following used to be _
      (show (pullback.fst f g) ≫ f ≫ i = (pullback.snd f g) ≫ g ≫ i by
        simp only [← Category.assoc]; rw [cancel_mono]; apply pullback.condition)) :=
  PullbackCone.isLimitOfCompMono f g i _ (limit.isLimit (cospan f g))
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_comp_mono (L152-L155)
instance hasPullback_of_comp_mono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] [HasPullback f g] :
    HasPullback (f ≫ i) (g ≫ i) :=
⟨⟨⟨_, pullbackIsPullbackOfCompMono f g i⟩⟩⟩
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_right_factors_mono (L162-L164)
instance hasPullback_of_right_factors_mono : HasPullback i (f ≫ i) := by
simpa only [Category.id_comp] using hasPullback_of_comp_mono (𝟙 Z) f i
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.pullback_snd_iso_of_right_factors_mono (L165-L171)
instance pullback_snd_iso_of_right_factors_mono :
    IsIso (pullback.snd i (f ≫ i)) := by
have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono (𝟙 _) f i⟩ WalkingCospan.right
  convert (congrArg IsIso (show _ ≫ pullback.snd (𝟙 Z) f = _ from this)).mp inferInstance
  · exact (Category.id_comp _).symm
  · exact (Category.id_comp _).symm
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_left_factors_mono (L174-L176)
instance hasPullback_of_left_factors_mono : HasPullback (f ≫ i) i := by
simpa only [Category.id_comp] using hasPullback_of_comp_mono f (𝟙 Z) i
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.pullback_snd_iso_of_left_factors_mono (L177-L183)
instance pullback_snd_iso_of_left_factors_mono :
    IsIso (pullback.fst (f ≫ i) i) := by
have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono f (𝟙 _) i⟩ WalkingCospan.left
  convert (congrArg IsIso (show _ ≫ pullback.fst f (𝟙 Z) = _ from this)).mp inferInstance
  · exact (Category.id_comp _).symm
  · exact (Category.id_comp _).symm
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.has_kernel_pair_of_mono (L192-L194)
instance has_kernel_pair_of_mono : HasPullback f f :=
⟨⟨⟨_, PullbackCone.isLimitMkIdId f⟩⟩⟩
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.PullbackCone (L195-L198)
theorem PullbackCone.fst_eq_snd_of_mono_eq {f : X ⟶ Y} [Mono f] (t : PullbackCone f f) :
    t.fst = t.snd :=
(cancel_mono f).1 t.condition
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.fst_eq_snd_of_mono_eq (L199-L201)
theorem fst_eq_snd_of_mono_eq : pullback.fst f f = pullback.snd f f :=
PullbackCone.fst_eq_snd_of_mono_eq (getLimitCone (cospan f f)).cone
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeSmallCategory (L158-L160)
instance biconeSmallCategory : SmallCategory (Bicone J) :=
CategoryTheory.biconeCategory J
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimits (L201-L203)
instance hasColimits [HasColimits T] : HasColimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimit (L140-L143)
instance hasLimit (F : J ⥤ Comma L R) [HasLimit (F ⋙ fst L R)] [HasLimit (F ⋙ snd L R)]
    [PreservesLimit (F ⋙ snd L R) R] : HasLimit F :=
HasLimit.mk ⟨_, coneOfPreservesIsLimit _ (limit.isLimit _) (limit.isLimit _)⟩
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimits (L189-L192)
instance hasLimits [HasLimits T] : HasLimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBicone (L52-L66)
instance finBicone [Fintype J] : Fintype (Bicone J) where
  elems := [Bicone.left, Bicone.right].toFinset ∪ Finset.image Bicone.diagram Fintype.elems
complete j := by
    cases j <;> simp [Fintype.complete]

variable [Category.{v₁} J]

/-- The homs for a walking `Bicone J`. -/
inductive BiconeHom : Bicone J → Bicone J → Type max u₁ v₁
  | left_id : BiconeHom Bicone.left Bicone.left
  | right_id : BiconeHom Bicone.right Bicone.right
  | left (j : J) : BiconeHom Bicone.left (Bicone.diagram j)
  | right (j : J) : BiconeHom Bicone.right (Bicone.diagram j)
  | diagram {j k : J} (f : j ⟶ k) : BiconeHom (Bicone.diagram j) (Bicone.diagram k)
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBiconeHom (L124-L157)
instance finBiconeHom [FinCategory J] (j k : Bicone J) : Fintype (j ⟶ k) := by
cases j <;> cases k
  · exact
      { elems := {BiconeHom.left_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := {BiconeHom.left _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
      { elems := {BiconeHom.right_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := {BiconeHom.right _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := Finset.image BiconeHom.diagram Fintype.elems
      complete := fun f => by
        rcases f with (_ | _ | _ | _ | f)
        simp only [Finset.mem_image]
        use f
        simpa using Fintype.complete _ }
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_iff_mono_right (L251-L260)
theorem mono_iff_mono_right [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) : Mono f ↔ Mono f.right :=
⟨fun _ => inferInstance, fun _ => mono_of_mono_right f⟩

end StructuredArrow

namespace CostructuredArrow

variable {G : A ⥤ T} {X : T} (F : J ⥤ CostructuredArrow G X)
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.BiconeHom (L70-L72)
instance BiconeHom.decidableEq {j k : Bicone J} : DecidableEq (BiconeHom J j k) := fun f g => by
classical cases f <;> cases g <;> simp only [diagram.injEq] <;> infer_instance
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_rightFunc (L208-L218)
instance preservesColimitsOfShape_rightFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.rightFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_snd

end Arrow

namespace StructuredArrow

variable {X : T} {G : A ⥤ T} (F : J ⥤ StructuredArrow X G)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_right_eq_curry_swap_map (L47-L89)
theorem map_id_right_eq_curry_swap_map {j j' : J} {f : j ⟶ j'} {k : K} :
    F.map (f ×ₘ 𝟙 k) = ((curry.obj (Prod.swap K J ⋙ F)).obj k).map f :=
rfl

variable [HasLimitsOfShape J C]
variable [HasColimitsOfShape K C]

set_option backward.isDefEq.respectTransparency false in
/-- The universal morphism
$\colim_k \lim_j F(j,k) → \lim_j \colim_k F(j, k)$.
-/
noncomputable def colimitLimitToLimitColimit :
    colimit (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) ⟶ limit (curry.obj F ⋙ colim) :=
  limit.lift (curry.obj F ⋙ colim)
    { pt := _
      π :=
        { app := fun j =>
            colimit.desc (curry.obj (Prod.swap K J ⋙ F) ⋙ lim)
              { pt := _
                ι :=
                  { app := fun k =>
                      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫
                        colimit.ι ((curry.obj F).obj j) k
                    naturality := by
                      intro k k' f
                      simp only [Functor.comp_obj, lim_obj, colimit.cocone_x,
                        Functor.const_obj_obj, Functor.comp_map, lim_map,
                        curry_obj_obj_obj, Prod.swap_obj, limMap_π_assoc, curry_obj_map_app,
                        Prod.swap_map, Functor.const_obj_map, Category.comp_id]
                      rw [map_id_left_eq_curry_map, colimit.w] } }
          naturality := by
            intro j j' f
            dsimp
            ext k
            simp only [Functor.comp_obj, lim_obj, Category.id_comp, colimit.ι_desc,
              colimit.ι_desc_assoc, Category.assoc, ι_colimMap,
              curry_obj_obj_obj, curry_obj_map_app]
            rw [map_id_right_eq_curry_swap_map, limit.w_assoc] } }

set_option backward.isDefEq.respectTransparency false in
/-- Since `colimit_limit_to_limit_colimit` is a morphism from a colimit to a limit,
this lemma characterises it.
-/
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π_apply (L98-L106)
theorem ι_colimitLimitToLimitColimit_π_apply [Small.{v} J] [Small.{v} K] (F : J × K ⥤ Type v)
    (j : J) (k : K) (f) : limit.π (curry.obj F ⋙ colim) j
        (colimitLimitToLimitColimit F (colimit.ι (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) k f)) =
      colimit.ι ((curry.obj F).obj j) k (limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j f) := by
dsimp [colimitLimitToLimitColimit]
  simp

set_option backward.isDefEq.respectTransparency false in
/-- The map `colimit_limit_to_limit_colimit` realized as a map of cones. -/
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_leftFunc (L204-L207)
instance preservesColimitsOfShape_leftFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.leftFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_fst
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategory (L88-L100)
instance biconeCategory : Category (Bicone J) where
  id_comp f := by cases f <;> simp
comp_id f := by cases f <;> simp
  assoc f g h := by cases f <;> cases g <;> cases h <;> simp

end Bicone

section SmallCategory

variable (J : Type v₁) [SmallCategory J]

/-- Given a diagram `F : J ⥤ C` and two `Cone F`s, we can join them into a diagram `Bicone J ⥤ C`.
-/
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Limits.Comma.colimitAuxiliaryCocone (L94-L101)
def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) :=
(Cocone.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂)

/--
If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and
a cocone for `F ⋙ snd L R : J ⥤ R` we can build a cocone for `F` which will turn out to be a
colimit cocone.
-/
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Limits.Comma.limitAuxiliaryCone (L47-L53)
def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) :=
(Cone.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁)

/-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a
limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit
cone.
-/
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_fst (L162-L168)
instance preservesColimitsOfShape_fst [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.fst L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)
```

-- snippet 32
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_right_of_mono (L247-L250)
instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right :=
show Mono ((proj X G).map f) from inferInstance
```

-- snippet 33
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_snd (L169-L180)
instance preservesColimitsOfShape_snd [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.snd L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)

end Comma

namespace Arrow

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 34
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategoryStruct (L74-L87)
instance biconeCategoryStruct : CategoryStruct (Bicone J) where
  Hom := BiconeHom J
id j := Bicone.casesOn j BiconeHom.left_id BiconeHom.right_id fun k => BiconeHom.diagram (𝟙 k)
  comp f g := by
    rcases f with (_ | _ | _ | _ | f)
    · exact g
    · exact g
    · cases g
      apply BiconeHom.left
    · cases g
      apply BiconeHom.right
    · rcases g with (_ | _ | _ | _ | g)
      exact BiconeHom.diagram (f ≫ g)
```

-- snippet 35
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_left_eq_curry_map (L43-L46)
theorem map_id_left_eq_curry_map {j : J} {k k' : K} {f : k ⟶ k'} :
    F.map (𝟙 j ×ₘ f) = ((curry.obj F).obj j).map f :=
rfl
```

-- snippet 36
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimit (L151-L154)
instance hasColimit (F : J ⥤ Comma L R) [HasColimit (F ⋙ fst L R)] [HasColimit (F ⋙ snd L R)]
    [PreservesColimit (F ⋙ fst L R) L] : HasColimit F :=
HasColimit.mk ⟨_, coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _)⟩
```

-- snippet 37
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π (L91-L96)
theorem ι_colimitLimitToLimitColimit_π (j) (k) :
    colimit.ι _ k ≫ colimitLimitToLimitColimit F ≫ limit.π _ j =
      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫ colimit.ι ((curry.obj F).obj j) k := by
dsimp [colimitLimitToLimitColimit]
  simp
```

-- snippet 38
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeMk (L102-L123)
def biconeMk {C : Type u₁} [Category.{v₁} C] {F : J ⥤ C} (c₁ c₂ : Cone F) : Bicone J ⥤ C where
  obj X := Bicone.casesOn X c₁.pt c₂.pt fun j => F.obj j
map f := by
    rcases f with (_ | _ | _ | _ | f)
    · exact 𝟙 _
    · exact 𝟙 _
    · exact c₁.π.app _
    · exact c₂.π.app _
    · exact F.map f
  map_id X := by cases X <;> simp
  map_comp f g := by
    rcases f with (_ | _ | _ | _ | _)
    · exact (Category.id_comp _).symm
    · exact (Category.id_comp _).symm
    · cases g
      exact (Category.id_comp _).symm.trans (c₁.π.naturality _)
    · cases g
      exact (Category.id_comp _).symm.trans (c₂.π.naturality _)
    · cases g
      apply F.map_comp

open scoped Classical in
```

-- snippet 39
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimitsOfSize (L147-L150)
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [HasLimitsOfSize.{w, w'} B]
    [PreservesLimitsOfSize.{w, w'} R] : HasLimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 40
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimitsOfSize (L158-L161)
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [HasColimitsOfSize.{w, w'} B]
    [PreservesColimitsOfSize.{w, w'} L] : HasColimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
instance pullback.snd_of_mono {X Y Z : C} {f : X ⟶ Z} {g : Y ⟶ Z} [HasPullback f g] [Mono f] :
    Mono (pullback.snd f g)
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_snd_of_is_pullback_of_mono (L50-L56)
theorem mono_snd_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono f] :
    Mono t.snd := by
refine ⟨fun {W} h k i => IsLimit.hom_ext ht ?_ i⟩
  rw [← cancel_mono f, Category.assoc, Category.assoc, condition]
  apply reassoc_of% i

/-- Monomorphisms are stable under pullback in the second argument. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_fst_of_is_pullback_of_mono (L57-L66)
theorem mono_fst_of_is_pullback_of_mono {t : PullbackCone f g} (ht : IsLimit t) [Mono g] :
    Mono t.fst := by
refine ⟨fun {W} h k i => IsLimit.hom_ext ht i ?_⟩
  rw [← cancel_mono g, Category.assoc, Category.assoc, ← condition]
  apply reassoc_of% i

/--
The pullback cone `(𝟙 X, 𝟙 X)` for the pair `(f, f)` is a limit if `f` is a mono. The converse is
shown in `mono_of_pullback_is_id`.
-/
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitMkIdId (L67-L75)
def isLimitMkIdId (f : X ⟶ Y) [Mono f] : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f) :=
IsLimit.mk _ (fun s => s.fst) (fun _ => Category.comp_id _)
    (fun s => by rw [← cancel_mono f, Category.comp_id, s.condition]) fun s m m₁ _ => by
    simpa using m₁

/--
`f` is a mono if the pullback cone `(𝟙 X, 𝟙 X)` is a limit for the pair `(f, f)`. The converse is
given in `PullbackCone.is_id_of_mono`.
-/
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_of_isLimitMkIdId (L76-L85)
theorem mono_of_isLimitMkIdId (f : X ⟶ Y) (t : IsLimit (mk (𝟙 X) (𝟙 X) rfl : PullbackCone f f)) :
    Mono f :=
⟨fun {Z} g h eq => by
    rcases PullbackCone.IsLimit.lift' t _ _ eq with ⟨_, rfl, rfl⟩
    rfl⟩

set_option backward.isDefEq.respectTransparency false in
/-- Suppose `f` and `g` are two morphisms with a common codomain and `s` is a limit cone over the
diagram formed by `f` and `g`. Suppose `f` and `g` both factor through a monomorphism `h` via
`x` and `y`, respectively.  Then `s` is also a limit cone over the diagram formed by `x` and `y`. -/
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitOfFactors (L86-L104)
def isLimitOfFactors (f : X ⟶ Z) (g : Y ⟶ Z) (h : W ⟶ Z) [Mono h] (x : X ⟶ W) (y : Y ⟶ W)
    (hxh : x ≫ h = f) (hyh : y ≫ h = g) (s : PullbackCone f g) (hs : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ x = s.snd ≫ y from
          (cancel_mono h).1 <| by simp only [Category.assoc, hxh, hyh, s.condition])) :=
PullbackCone.isLimitAux' _ fun t =>
    have : fst t ≫ x ≫ h = snd t ≫ y ≫ h := by  -- Porting note: reassoc workaround
      rw [← Category.assoc, ← Category.assoc]
      apply congrArg (· ≫ h) t.condition
    ⟨hs.lift (PullbackCone.mk t.fst t.snd <| by rw [← hxh, ← hyh, this]),
      ⟨hs.fac _ WalkingCospan.left, hs.fac _ WalkingCospan.right, fun hr hr' => by
        apply PullbackCone.IsLimit.hom_ext hs <;>
              simp only [PullbackCone.mk_fst, PullbackCone.mk_snd] at hr hr' ⊢ <;>
            simp only [hr, hr'] <;>
          symm
        exacts [hs.fac _ WalkingCospan.left, hs.fac _ WalkingCospan.right]⟩⟩

/-- If `W` is the pullback of `f, g`, it is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.isLimitOfCompMono (L105-L124)
def isLimitOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] (s : PullbackCone f g)
    (H : IsLimit s) :
    IsLimit
      (PullbackCone.mk _ _
        (show s.fst ≫ f ≫ i = s.snd ≫ g ≫ i by
          rw [← Category.assoc, ← Category.assoc, s.condition])) := by
apply PullbackCone.isLimitAux'
  intro s
  rcases PullbackCone.IsLimit.lift' H s.fst s.snd
      ((cancel_mono i).mp (by simpa using s.condition)) with
    ⟨l, h₁, h₂⟩
  refine ⟨l, h₁, h₂, ?_⟩
  intro m hm₁ hm₂
  exact (PullbackCone.IsLimit.hom_ext H (hm₁.trans h₁.symm) (hm₂.trans h₂.symm) :)

end PullbackCone

end Monomorphisms

/-- The pullback of a monomorphism is a monomorphism -/
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.mono_pullback_to_prod (L136-L151)
instance mono_pullback_to_prod {C : Type*} [Category* C] {X Y Z : C} (f : X ⟶ Z) (g : Y ⟶ Z)
    [HasPullback f g] [HasBinaryProduct X Y] :
    Mono (prod.lift (pullback.fst f g) (pullback.snd f g)) :=
⟨fun {W} i₁ i₂ h => by
    ext
    · simpa using congrArg (fun f => f ≫ prod.fst) h
    · simpa using congrArg (fun f => f ≫ prod.snd) h⟩

/-- The pullback of `f, g` is also the pullback of `f ≫ i, g ≫ i` for any mono `i`. -/
noncomputable def pullbackIsPullbackOfCompMono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i]
    [HasPullback f g] : IsLimit (PullbackCone.mk (pullback.fst f g) (pullback.snd f g)
      -- Porting note: following used to be _
      (show (pullback.fst f g) ≫ f ≫ i = (pullback.snd f g) ≫ g ≫ i by
        simp only [← Category.assoc]; rw [cancel_mono]; apply pullback.condition)) :=
  PullbackCone.isLimitOfCompMono f g i _ (limit.isLimit (cospan f g))
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_comp_mono (L152-L155)
instance hasPullback_of_comp_mono (f : X ⟶ W) (g : Y ⟶ W) (i : W ⟶ Z) [Mono i] [HasPullback f g] :
    HasPullback (f ≫ i) (g ≫ i) :=
⟨⟨⟨_, pullbackIsPullbackOfCompMono f g i⟩⟩⟩
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_right_factors_mono (L162-L164)
instance hasPullback_of_right_factors_mono : HasPullback i (f ≫ i) := by
simpa only [Category.id_comp] using hasPullback_of_comp_mono (𝟙 Z) f i
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.pullback_snd_iso_of_right_factors_mono (L165-L171)
instance pullback_snd_iso_of_right_factors_mono :
    IsIso (pullback.snd i (f ≫ i)) := by
have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono (𝟙 _) f i⟩ WalkingCospan.right
  convert (congrArg IsIso (show _ ≫ pullback.snd (𝟙 Z) f = _ from this)).mp inferInstance
  · exact (Category.id_comp _).symm
  · exact (Category.id_comp _).symm
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.hasPullback_of_left_factors_mono (L174-L176)
instance hasPullback_of_left_factors_mono : HasPullback (f ≫ i) i := by
simpa only [Category.id_comp] using hasPullback_of_comp_mono f (𝟙 Z) i
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.pullback_snd_iso_of_left_factors_mono (L177-L183)
instance pullback_snd_iso_of_left_factors_mono :
    IsIso (pullback.fst (f ≫ i) i) := by
have := limit.isoLimitCone_hom_π ⟨_, pullbackIsPullbackOfCompMono f (𝟙 _) i⟩ WalkingCospan.left
  convert (congrArg IsIso (show _ ≫ pullback.fst f (𝟙 Z) = _ from this)).mp inferInstance
  · exact (Category.id_comp _).symm
  · exact (Category.id_comp _).symm
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.has_kernel_pair_of_mono (L192-L194)
instance has_kernel_pair_of_mono : HasPullback f f :=
⟨⟨⟨_, PullbackCone.isLimitMkIdId f⟩⟩⟩
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.PullbackCone (L195-L198)
theorem PullbackCone.fst_eq_snd_of_mono_eq {f : X ⟶ Y} [Mono f] (t : PullbackCone f f) :
    t.fst = t.snd :=
(cancel_mono f).1 t.condition
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Limits.Shapes.Pullback.Mono.fst_eq_snd_of_mono_eq (L199-L201)
theorem fst_eq_snd_of_mono_eq : pullback.fst f f = pullback.snd f f :=
PullbackCone.fst_eq_snd_of_mono_eq (getLimitCone (cospan f f)).cone
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeSmallCategory (L158-L160)
instance biconeSmallCategory : SmallCategory (Bicone J) :=
CategoryTheory.biconeCategory J
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimits (L201-L203)
instance hasColimits [HasColimits T] : HasColimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimit (L140-L143)
instance hasLimit (F : J ⥤ Comma L R) [HasLimit (F ⋙ fst L R)] [HasLimit (F ⋙ snd L R)]
    [PreservesLimit (F ⋙ snd L R) R] : HasLimit F :=
HasLimit.mk ⟨_, coneOfPreservesIsLimit _ (limit.isLimit _) (limit.isLimit _)⟩
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimits (L189-L192)
instance hasLimits [HasLimits T] : HasLimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBicone (L52-L66)
instance finBicone [Fintype J] : Fintype (Bicone J) where
  elems := [Bicone.left, Bicone.right].toFinset ∪ Finset.image Bicone.diagram Fintype.elems
complete j := by
    cases j <;> simp [Fintype.complete]

variable [Category.{v₁} J]

/-- The homs for a walking `Bicone J`. -/
inductive BiconeHom : Bicone J → Bicone J → Type max u₁ v₁
  | left_id : BiconeHom Bicone.left Bicone.left
  | right_id : BiconeHom Bicone.right Bicone.right
  | left (j : J) : BiconeHom Bicone.left (Bicone.diagram j)
  | right (j : J) : BiconeHom Bicone.right (Bicone.diagram j)
  | diagram {j k : J} (f : j ⟶ k) : BiconeHom (Bicone.diagram j) (Bicone.diagram k)
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBiconeHom (L124-L157)
instance finBiconeHom [FinCategory J] (j k : Bicone J) : Fintype (j ⟶ k) := by
cases j <;> cases k
  · exact
      { elems := {BiconeHom.left_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := {BiconeHom.left _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
      { elems := {BiconeHom.right_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := {BiconeHom.right _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := Finset.image BiconeHom.diagram Fintype.elems
      complete := fun f => by
        rcases f with (_ | _ | _ | _ | f)
        simp only [Finset.mem_image]
        use f
        simpa using Fintype.complete _ }
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_iff_mono_right (L251-L260)
theorem mono_iff_mono_right [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) : Mono f ↔ Mono f.right :=
⟨fun _ => inferInstance, fun _ => mono_of_mono_right f⟩

end StructuredArrow

namespace CostructuredArrow

variable {G : A ⥤ T} {X : T} (F : J ⥤ CostructuredArrow G X)
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.BiconeHom (L70-L72)
instance BiconeHom.decidableEq {j k : Bicone J} : DecidableEq (BiconeHom J j k) := fun f g => by
classical cases f <;> cases g <;> simp only [diagram.injEq] <;> infer_instance
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_rightFunc (L208-L218)
instance preservesColimitsOfShape_rightFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.rightFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_snd

end Arrow

namespace StructuredArrow

variable {X : T} {G : A ⥤ T} (F : J ⥤ StructuredArrow X G)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_right_eq_curry_swap_map (L47-L89)
theorem map_id_right_eq_curry_swap_map {j j' : J} {f : j ⟶ j'} {k : K} :
    F.map (f ×ₘ 𝟙 k) = ((curry.obj (Prod.swap K J ⋙ F)).obj k).map f :=
rfl

variable [HasLimitsOfShape J C]
variable [HasColimitsOfShape K C]

set_option backward.isDefEq.respectTransparency false in
/-- The universal morphism
$\colim_k \lim_j F(j,k) → \lim_j \colim_k F(j, k)$.
-/
noncomputable def colimitLimitToLimitColimit :
    colimit (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) ⟶ limit (curry.obj F ⋙ colim) :=
  limit.lift (curry.obj F ⋙ colim)
    { pt := _
      π :=
        { app := fun j =>
            colimit.desc (curry.obj (Prod.swap K J ⋙ F) ⋙ lim)
              { pt := _
                ι :=
                  { app := fun k =>
                      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫
                        colimit.ι ((curry.obj F).obj j) k
                    naturality := by
                      intro k k' f
                      simp only [Functor.comp_obj, lim_obj, colimit.cocone_x,
                        Functor.const_obj_obj, Functor.comp_map, lim_map,
                        curry_obj_obj_obj, Prod.swap_obj, limMap_π_assoc, curry_obj_map_app,
                        Prod.swap_map, Functor.const_obj_map, Category.comp_id]
                      rw [map_id_left_eq_curry_map, colimit.w] } }
          naturality := by
            intro j j' f
            dsimp
            ext k
            simp only [Functor.comp_obj, lim_obj, Category.id_comp, colimit.ι_desc,
              colimit.ι_desc_assoc, Category.assoc, ι_colimMap,
              curry_obj_obj_obj, curry_obj_map_app]
            rw [map_id_right_eq_curry_swap_map, limit.w_assoc] } }

set_option backward.isDefEq.respectTransparency false in
/-- Since `colimit_limit_to_limit_colimit` is a morphism from a colimit to a limit,
this lemma characterises it.
-/
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π_apply (L98-L106)
theorem ι_colimitLimitToLimitColimit_π_apply [Small.{v} J] [Small.{v} K] (F : J × K ⥤ Type v)
    (j : J) (k : K) (f) : limit.π (curry.obj F ⋙ colim) j
        (colimitLimitToLimitColimit F (colimit.ι (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) k f)) =
      colimit.ι ((curry.obj F).obj j) k (limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j f) := by
dsimp [colimitLimitToLimitColimit]
  simp

set_option backward.isDefEq.respectTransparency false in
/-- The map `colimit_limit_to_limit_colimit` realized as a map of cones. -/
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_leftFunc (L204-L207)
instance preservesColimitsOfShape_leftFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.leftFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_fst
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategory (L88-L100)
instance biconeCategory : Category (Bicone J) where
  id_comp f := by cases f <;> simp
comp_id f := by cases f <;> simp
  assoc f g h := by cases f <;> cases g <;> cases h <;> simp

end Bicone

section SmallCategory

variable (J : Type v₁) [SmallCategory J]

/-- Given a diagram `F : J ⥤ C` and two `Cone F`s, we can join them into a diagram `Bicone J ⥤ C`.
-/
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Limits.Comma.colimitAuxiliaryCocone (L94-L101)
def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) :=
(Cocone.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂)

/--
If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and
a cocone for `F ⋙ snd L R : J ⥤ R` we can build a cocone for `F` which will turn out to be a
colimit cocone.
-/
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Limits.Comma.limitAuxiliaryCone (L47-L53)
def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) :=
(Cone.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁)

/-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a
limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit
cone.
-/
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_fst (L162-L168)
instance preservesColimitsOfShape_fst [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.fst L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)
```

-- snippet 32
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_right_of_mono (L247-L250)
instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right :=
show Mono ((proj X G).map f) from inferInstance
```

-- snippet 33
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_snd (L169-L180)
instance preservesColimitsOfShape_snd [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.snd L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)

end Comma

namespace Arrow

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 34
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategoryStruct (L74-L87)
instance biconeCategoryStruct : CategoryStruct (Bicone J) where
  Hom := BiconeHom J
id j := Bicone.casesOn j BiconeHom.left_id BiconeHom.right_id fun k => BiconeHom.diagram (𝟙 k)
  comp f g := by
    rcases f with (_ | _ | _ | _ | f)
    · exact g
    · exact g
    · cases g
      apply BiconeHom.left
    · cases g
      apply BiconeHom.right
    · rcases g with (_ | _ | _ | _ | g)
      exact BiconeHom.diagram (f ≫ g)
```

-- snippet 35
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_left_eq_curry_map (L43-L46)
theorem map_id_left_eq_curry_map {j : J} {k k' : K} {f : k ⟶ k'} :
    F.map (𝟙 j ×ₘ f) = ((curry.obj F).obj j).map f :=
rfl
```

-- snippet 36
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimit (L151-L154)
instance hasColimit (F : J ⥤ Comma L R) [HasColimit (F ⋙ fst L R)] [HasColimit (F ⋙ snd L R)]
    [PreservesColimit (F ⋙ fst L R) L] : HasColimit F :=
HasColimit.mk ⟨_, coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _)⟩
```

-- snippet 37
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π (L91-L96)
theorem ι_colimitLimitToLimitColimit_π (j) (k) :
    colimit.ι _ k ≫ colimitLimitToLimitColimit F ≫ limit.π _ j =
      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫ colimit.ι ((curry.obj F).obj j) k := by
dsimp [colimitLimitToLimitColimit]
  simp
```

-- snippet 38
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeMk (L102-L123)
def biconeMk {C : Type u₁} [Category.{v₁} C] {F : J ⥤ C} (c₁ c₂ : Cone F) : Bicone J ⥤ C where
  obj X := Bicone.casesOn X c₁.pt c₂.pt fun j => F.obj j
map f := by
    rcases f with (_ | _ | _ | _ | f)
    · exact 𝟙 _
    · exact 𝟙 _
    · exact c₁.π.app _
    · exact c₂.π.app _
    · exact F.map f
  map_id X := by cases X <;> simp
  map_comp f g := by
    rcases f with (_ | _ | _ | _ | _)
    · exact (Category.id_comp _).symm
    · exact (Category.id_comp _).symm
    · cases g
      exact (Category.id_comp _).symm.trans (c₁.π.naturality _)
    · cases g
      exact (Category.id_comp _).symm.trans (c₂.π.naturality _)
    · cases g
      apply F.map_comp

open scoped Classical in
```

-- snippet 39
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimitsOfSize (L147-L150)
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [HasLimitsOfSize.{w, w'} B]
    [PreservesLimitsOfSize.{w, w'} R] : HasLimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 40
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimitsOfSize (L158-L161)
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [HasColimitsOfSize.{w, w'} B]
    [PreservesColimitsOfSize.{w, w'} L] : HasColimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```
[/INST]


[System] You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Preserves.Opposites).

[User]
Prove the following theorem. The retrieved context below may help.

```lean
lemma preservesColimitsOfSize_of_leftOp (F : C ⥤ Dᵒᵖ) [PreservesLimitsOfSize.{w, w'} F.leftOp] :
    PreservesColimitsOfSize.{w, w'} F where
  preservesColimitsOfShape {_} _
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_op (L35-L41)
lemma preservesLimit_op (K : J ⥤ Cᵒᵖ) (F : C ⥤ D) [PreservesColimit K.leftOp F] :
    PreservesLimit K F.op where
  preserves {_} hc :=
⟨isLimitConeRightOpOfCocone _ (isColimitOfPreserves F (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ D` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_op (L42-L47)
lemma preservesLimit_of_op (K : J ⥤ C) (F : C ⥤ D) [PreservesColimit K.op F.op] :
    PreservesLimit K F where
  preserves {_} hc := ⟨isLimitOfOp (isColimitOfPreserves F.op (IsLimit.op hc))⟩
/-- If `F : C ⥤ Dᵒᵖ` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.leftOp : Cᵒᵖ ⥤ D`
preserves limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_leftOp (L48-L54)
lemma preservesLimit_leftOp (K : J ⥤ Cᵒᵖ) (F : C ⥤ Dᵒᵖ) [PreservesColimit K.leftOp F] :
    PreservesLimit K F.leftOp where
  preserves {_} hc :=
⟨isLimitConeUnopOfCocone _ (isColimitOfPreserves F (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F.leftOp : Cᵒᵖ ⥤ D` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_leftOp (L55-L61)
lemma preservesLimit_of_leftOp (K : J ⥤ C) (F : C ⥤ Dᵒᵖ) [PreservesColimit K.op F.leftOp] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfCoconeLeftOpOfCone _ (isColimitOfPreserves F.leftOp (IsLimit.op hc))⟩

/-- If `F : Cᵒᵖ ⥤ D` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.rightOp : C ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_rightOp (L62-L68)
lemma preservesLimit_rightOp (K : J ⥤ C) (F : Cᵒᵖ ⥤ D) [PreservesColimit K.op F] :
    PreservesLimit K F.rightOp where
  preserves {_} hc :=
⟨isLimitConeRightOpOfCocone _ (isColimitOfPreserves F hc.op)⟩

/-- If `F.rightOp : C ⥤ Dᵒᵖ` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : Cᵒᵖ ⥤ D`
preserves limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_rightOp (L69-L75)
lemma preservesLimit_of_rightOp (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ D) [PreservesColimit K.leftOp F.rightOp] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfOp (isColimitOfPreserves F.rightOp (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.unop : C ⥤ D` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_unop (L76-L82)
lemma preservesLimit_unop (K : J ⥤ C) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesColimit K.op F] :
    PreservesLimit K F.unop where
  preserves {_} hc :=
⟨isLimitConeUnopOfCocone _ (isColimitOfPreserves F hc.op)⟩

/-- If `F.unop : C ⥤ D` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_unop (L83-L89)
lemma preservesLimit_of_unop (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesColimit K.leftOp F.unop] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfCoconeLeftOpOfCone _ (isColimitOfPreserves F.unop (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F : C ⥤ D` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_op (L90-L96)
lemma preservesColimit_op (K : J ⥤ Cᵒᵖ) (F : C ⥤ D) [PreservesLimit K.leftOp F] :
    PreservesColimit K F.op where
  preserves {_} hc :=
⟨isColimitCoconeRightOpOfCone _ (isLimitOfPreserves F (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ D` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_op (L97-L102)
lemma preservesColimit_of_op (K : J ⥤ C) (F : C ⥤ D) [PreservesLimit K.op F.op] :
    PreservesColimit K F where
  preserves {_} hc := ⟨isColimitOfOp (isLimitOfPreserves F.op (IsColimit.op hc))⟩
/-- If `F : C ⥤ Dᵒᵖ` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.leftOp : Cᵒᵖ ⥤ D` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_leftOp (L103-L109)
lemma preservesColimit_leftOp (K : J ⥤ Cᵒᵖ) (F : C ⥤ Dᵒᵖ) [PreservesLimit K.leftOp F] :
    PreservesColimit K F.leftOp where
  preserves {_} hc :=
⟨isColimitCoconeUnopOfCone _ (isLimitOfPreserves F (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F.leftOp : Cᵒᵖ ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_leftOp (L110-L116)
lemma preservesColimit_of_leftOp (K : J ⥤ C) (F : C ⥤ Dᵒᵖ) [PreservesLimit K.op F.leftOp] :
    PreservesColimit K F where
  preserves {_} hc :=
⟨isColimitOfConeLeftOpOfCocone _ (isLimitOfPreserves F.leftOp (IsColimit.op hc))⟩

/-- If `F : Cᵒᵖ ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.rightOp : C ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_rightOp (L117-L123)
lemma preservesColimit_rightOp (K : J ⥤ C) (F : Cᵒᵖ ⥤ D) [PreservesLimit K.op F] :
    PreservesColimit K F.rightOp where
  preserves {_} hc :=
⟨isColimitCoconeRightOpOfCone _ (isLimitOfPreserves F hc.op)⟩

/-- If `F.rightOp : C ⥤ Dᵒᵖ` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ D`
preserves colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_rightOp (L124-L130)
lemma preservesColimit_of_rightOp (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ D) [PreservesLimit K.leftOp F.rightOp] :
    PreservesColimit K F where
  preserves {_} hc :=
⟨isColimitOfOp (isLimitOfPreserves F.rightOp (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.unop : C ⥤ D` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_unop (L131-L137)
lemma preservesColimit_unop (K : J ⥤ C) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesLimit K.op F] :
    PreservesColimit K F.unop where
  preserves {_} hc :=
⟨isColimitCoconeUnopOfCone _ (isLimitOfPreserves F hc.op)⟩

/-- If `F.unop : C ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBicone (L52-L66)
instance finBicone [Fintype J] : Fintype (Bicone J) where
  elems := [Bicone.left, Bicone.right].toFinset ∪ Finset.image Bicone.diagram Fintype.elems
complete j := by
    cases j <;> simp [Fintype.complete]

variable [Category.{v₁} J]

/-- The homs for a walking `Bicone J`. -/
inductive BiconeHom : Bicone J → Bicone J → Type max u₁ v₁
  | left_id : BiconeHom Bicone.left Bicone.left
  | right_id : BiconeHom Bicone.right Bicone.right
  | left (j : J) : BiconeHom Bicone.left (Bicone.diagram j)
  | right (j : J) : BiconeHom Bicone.right (Bicone.diagram j)
  | diagram {j k : J} (f : j ⟶ k) : BiconeHom (Bicone.diagram j) (Bicone.diagram k)
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_rightFunc (L208-L218)
instance preservesColimitsOfShape_rightFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.rightFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_snd

end Arrow

namespace StructuredArrow

variable {X : T} {G : A ⥤ T} (F : J ⥤ StructuredArrow X G)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_snd (L169-L180)
instance preservesColimitsOfShape_snd [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.snd L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)

end Comma

namespace Arrow

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBiconeHom (L124-L157)
instance finBiconeHom [FinCategory J] (j k : Bicone J) : Fintype (j ⟶ k) := by
cases j <;> cases k
  · exact
      { elems := {BiconeHom.left_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := {BiconeHom.left _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
      { elems := {BiconeHom.right_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := {BiconeHom.right _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := Finset.image BiconeHom.diagram Fintype.elems
      complete := fun f => by
        rcases f with (_ | _ | _ | _ | f)
        simp only [Finset.mem_image]
        use f
        simpa using Fintype.complete _ }
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategoryStruct (L74-L87)
instance biconeCategoryStruct : CategoryStruct (Bicone J) where
  Hom := BiconeHom J
id j := Bicone.casesOn j BiconeHom.left_id BiconeHom.right_id fun k => BiconeHom.diagram (𝟙 k)
  comp f g := by
    rcases f with (_ | _ | _ | _ | f)
    · exact g
    · exact g
    · cases g
      apply BiconeHom.left
    · cases g
      apply BiconeHom.right
    · rcases g with (_ | _ | _ | _ | g)
      exact BiconeHom.diagram (f ≫ g)
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_right_eq_curry_swap_map (L47-L89)
theorem map_id_right_eq_curry_swap_map {j j' : J} {f : j ⟶ j'} {k : K} :
    F.map (f ×ₘ 𝟙 k) = ((curry.obj (Prod.swap K J ⋙ F)).obj k).map f :=
rfl

variable [HasLimitsOfShape J C]
variable [HasColimitsOfShape K C]

set_option backward.isDefEq.respectTransparency false in
/-- The universal morphism
$\colim_k \lim_j F(j,k) → \lim_j \colim_k F(j, k)$.
-/
noncomputable def colimitLimitToLimitColimit :
    colimit (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) ⟶ limit (curry.obj F ⋙ colim) :=
  limit.lift (curry.obj F ⋙ colim)
    { pt := _
      π :=
        { app := fun j =>
            colimit.desc (curry.obj (Prod.swap K J ⋙ F) ⋙ lim)
              { pt := _
                ι :=
                  { app := fun k =>
                      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫
                        colimit.ι ((curry.obj F).obj j) k
                    naturality := by
                      intro k k' f
                      simp only [Functor.comp_obj, lim_obj, colimit.cocone_x,
                        Functor.const_obj_obj, Functor.comp_map, lim_map,
                        curry_obj_obj_obj, Prod.swap_obj, limMap_π_assoc, curry_obj_map_app,
                        Prod.swap_map, Functor.const_obj_map, Category.comp_id]
                      rw [map_id_left_eq_curry_map, colimit.w] } }
          naturality := by
            intro j j' f
            dsimp
            ext k
            simp only [Functor.comp_obj, lim_obj, Category.id_comp, colimit.ι_desc,
              colimit.ι_desc_assoc, Category.assoc, ι_colimMap,
              curry_obj_obj_obj, curry_obj_map_app]
            rw [map_id_right_eq_curry_swap_map, limit.w_assoc] } }

set_option backward.isDefEq.respectTransparency false in
/-- Since `colimit_limit_to_limit_colimit` is a morphism from a colimit to a limit,
this lemma characterises it.
-/
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_leftFunc (L204-L207)
instance preservesColimitsOfShape_leftFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.leftFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_fst
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π (L91-L96)
theorem ι_colimitLimitToLimitColimit_π (j) (k) :
    colimit.ι _ k ≫ colimitLimitToLimitColimit F ≫ limit.π _ j =
      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫ colimit.ι ((curry.obj F).obj j) k := by
dsimp [colimitLimitToLimitColimit]
  simp
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.BiconeHom (L70-L72)
instance BiconeHom.decidableEq {j k : Bicone J} : DecidableEq (BiconeHom J j k) := fun f g => by
classical cases f <;> cases g <;> simp only [diagram.injEq] <;> infer_instance
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π_apply (L98-L106)
theorem ι_colimitLimitToLimitColimit_π_apply [Small.{v} J] [Small.{v} K] (F : J × K ⥤ Type v)
    (j : J) (k : K) (f) : limit.π (curry.obj F ⋙ colim) j
        (colimitLimitToLimitColimit F (colimit.ι (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) k f)) =
      colimit.ι ((curry.obj F).obj j) k (limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j f) := by
dsimp [colimitLimitToLimitColimit]
  simp

set_option backward.isDefEq.respectTransparency false in
/-- The map `colimit_limit_to_limit_colimit` realized as a map of cones. -/
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Limits.Comma.limitAuxiliaryCone (L47-L53)
def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) :=
(Cone.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁)

/-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a
limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit
cone.
-/
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimitsOfSize (L158-L161)
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [HasColimitsOfSize.{w, w'} B]
    [PreservesColimitsOfSize.{w, w'} L] : HasColimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimits (L201-L203)
instance hasColimits [HasColimits T] : HasColimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimit (L140-L143)
instance hasLimit (F : J ⥤ Comma L R) [HasLimit (F ⋙ fst L R)] [HasLimit (F ⋙ snd L R)]
    [PreservesLimit (F ⋙ snd L R) R] : HasLimit F :=
HasLimit.mk ⟨_, coneOfPreservesIsLimit _ (limit.isLimit _) (limit.isLimit _)⟩
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimits (L189-L192)
instance hasLimits [HasLimits T] : HasLimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Limits.Comma.colimitAuxiliaryCocone (L94-L101)
def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) :=
(Cocone.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂)

/--
If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and
a cocone for `F ⋙ snd L R : J ⥤ R` we can build a cocone for `F` which will turn out to be a
colimit cocone.
-/
```

-- snippet 32
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_fst (L162-L168)
instance preservesColimitsOfShape_fst [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.fst L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)
```

-- snippet 33
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimitsOfSize (L147-L150)
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [HasLimitsOfSize.{w, w'} B]
    [PreservesLimitsOfSize.{w, w'} R] : HasLimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 34
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_right_of_mono (L247-L250)
instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right :=
show Mono ((proj X G).map f) from inferInstance
```

-- snippet 35
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeMk (L102-L123)
def biconeMk {C : Type u₁} [Category.{v₁} C] {F : J ⥤ C} (c₁ c₂ : Cone F) : Bicone J ⥤ C where
  obj X := Bicone.casesOn X c₁.pt c₂.pt fun j => F.obj j
map f := by
    rcases f with (_ | _ | _ | _ | f)
    · exact 𝟙 _
    · exact 𝟙 _
    · exact c₁.π.app _
    · exact c₂.π.app _
    · exact F.map f
  map_id X := by cases X <;> simp
  map_comp f g := by
    rcases f with (_ | _ | _ | _ | _)
    · exact (Category.id_comp _).symm
    · exact (Category.id_comp _).symm
    · cases g
      exact (Category.id_comp _).symm.trans (c₁.π.naturality _)
    · cases g
      exact (Category.id_comp _).symm.trans (c₂.π.naturality _)
    · cases g
      apply F.map_comp

open scoped Classical in
```

-- snippet 36
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimit (L151-L154)
instance hasColimit (F : J ⥤ Comma L R) [HasColimit (F ⋙ fst L R)] [HasColimit (F ⋙ snd L R)]
    [PreservesColimit (F ⋙ fst L R) L] : HasColimit F :=
HasColimit.mk ⟨_, coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _)⟩
```

-- snippet 37
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeSmallCategory (L158-L160)
instance biconeSmallCategory : SmallCategory (Bicone J) :=
CategoryTheory.biconeCategory J
```

-- snippet 38
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategory (L88-L100)
instance biconeCategory : Category (Bicone J) where
  id_comp f := by cases f <;> simp
comp_id f := by cases f <;> simp
  assoc f g h := by cases f <;> cases g <;> cases h <;> simp

end Bicone

section SmallCategory

variable (J : Type v₁) [SmallCategory J]

/-- Given a diagram `F : J ⥤ C` and two `Cone F`s, we can join them into a diagram `Bicone J ⥤ C`.
-/
```

-- snippet 39
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_left_eq_curry_map (L43-L46)
theorem map_id_left_eq_curry_map {j : J} {k k' : K} {f : k ⟶ k'} :
    F.map (𝟙 j ×ₘ f) = ((curry.obj F).obj j).map f :=
rfl
```

-- snippet 40
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_iff_mono_right (L251-L260)
theorem mono_iff_mono_right [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) : Mono f ↔ Mono f.right :=
⟨fun _ => inferInstance, fun _ => mono_of_mono_right f⟩

end StructuredArrow

namespace CostructuredArrow

variable {G : A ⥤ T} {X : T} (F : J ⥤ CostructuredArrow G X)
```

<s>[SYSTEM_PROMPT]You are Leanstral, a Lean 4 proof assistant. Complete the task below using the provided Lean source context. The target mathlib commit is 5e932f97dd25535344f80f9dd8da3aab83df0fe6 (module Mathlib.CategoryTheory.Limits.Preserves.Opposites).[/SYSTEM_PROMPT][MODEL_SETTINGS]{"reasoning_effort": "none"}[/MODEL_SETTINGS][INST]Prove the following theorem. The retrieved context below may help.

```lean
lemma preservesColimitsOfSize_of_leftOp (F : C ⥤ Dᵒᵖ) [PreservesLimitsOfSize.{w, w'} F.leftOp] :
    PreservesColimitsOfSize.{w, w'} F where
  preservesColimitsOfShape {_} _
```

## Retrieved context
-- snippet 1
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_op (L35-L41)
lemma preservesLimit_op (K : J ⥤ Cᵒᵖ) (F : C ⥤ D) [PreservesColimit K.leftOp F] :
    PreservesLimit K F.op where
  preserves {_} hc :=
⟨isLimitConeRightOpOfCocone _ (isColimitOfPreserves F (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ D` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 2
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_op (L42-L47)
lemma preservesLimit_of_op (K : J ⥤ C) (F : C ⥤ D) [PreservesColimit K.op F.op] :
    PreservesLimit K F where
  preserves {_} hc := ⟨isLimitOfOp (isColimitOfPreserves F.op (IsLimit.op hc))⟩
/-- If `F : C ⥤ Dᵒᵖ` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.leftOp : Cᵒᵖ ⥤ D`
preserves limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 3
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_leftOp (L48-L54)
lemma preservesLimit_leftOp (K : J ⥤ Cᵒᵖ) (F : C ⥤ Dᵒᵖ) [PreservesColimit K.leftOp F] :
    PreservesLimit K F.leftOp where
  preserves {_} hc :=
⟨isLimitConeUnopOfCocone _ (isColimitOfPreserves F (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F.leftOp : Cᵒᵖ ⥤ D` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 4
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_leftOp (L55-L61)
lemma preservesLimit_of_leftOp (K : J ⥤ C) (F : C ⥤ Dᵒᵖ) [PreservesColimit K.op F.leftOp] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfCoconeLeftOpOfCone _ (isColimitOfPreserves F.leftOp (IsLimit.op hc))⟩

/-- If `F : Cᵒᵖ ⥤ D` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.rightOp : C ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 5
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_rightOp (L62-L68)
lemma preservesLimit_rightOp (K : J ⥤ C) (F : Cᵒᵖ ⥤ D) [PreservesColimit K.op F] :
    PreservesLimit K F.rightOp where
  preserves {_} hc :=
⟨isLimitConeRightOpOfCocone _ (isColimitOfPreserves F hc.op)⟩

/-- If `F.rightOp : C ⥤ Dᵒᵖ` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : Cᵒᵖ ⥤ D`
preserves limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 6
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_rightOp (L69-L75)
lemma preservesLimit_of_rightOp (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ D) [PreservesColimit K.leftOp F.rightOp] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfOp (isColimitOfPreserves F.rightOp (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves colimits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.unop : C ⥤ D` preserves
limits of `K : J ⥤ C`. -/
```

-- snippet 7
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_unop (L76-L82)
lemma preservesLimit_unop (K : J ⥤ C) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesColimit K.op F] :
    PreservesLimit K F.unop where
  preserves {_} hc :=
⟨isLimitConeUnopOfCocone _ (isColimitOfPreserves F hc.op)⟩

/-- If `F.unop : C ⥤ D` preserves colimits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves
limits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 8
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesLimit_of_unop (L83-L89)
lemma preservesLimit_of_unop (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesColimit K.leftOp F.unop] :
    PreservesLimit K F where
  preserves {_} hc :=
⟨isLimitOfCoconeLeftOpOfCone _ (isColimitOfPreserves F.unop (isColimitCoconeLeftOpOfCone _ hc))⟩

/-- If `F : C ⥤ D` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 9
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_op (L90-L96)
lemma preservesColimit_op (K : J ⥤ Cᵒᵖ) (F : C ⥤ D) [PreservesLimit K.leftOp F] :
    PreservesColimit K F.op where
  preserves {_} hc :=
⟨isColimitCoconeRightOpOfCone _ (isLimitOfPreserves F (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F.op : Cᵒᵖ ⥤ Dᵒᵖ` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ D` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 10
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_op (L97-L102)
lemma preservesColimit_of_op (K : J ⥤ C) (F : C ⥤ D) [PreservesLimit K.op F.op] :
    PreservesColimit K F where
  preserves {_} hc := ⟨isColimitOfOp (isLimitOfPreserves F.op (IsColimit.op hc))⟩
/-- If `F : C ⥤ Dᵒᵖ` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F.leftOp : Cᵒᵖ ⥤ D` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 11
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_leftOp (L103-L109)
lemma preservesColimit_leftOp (K : J ⥤ Cᵒᵖ) (F : C ⥤ Dᵒᵖ) [PreservesLimit K.leftOp F] :
    PreservesColimit K F.leftOp where
  preserves {_} hc :=
⟨isColimitCoconeUnopOfCone _ (isLimitOfPreserves F (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F.leftOp : Cᵒᵖ ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F : C ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 12
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_leftOp (L110-L116)
lemma preservesColimit_of_leftOp (K : J ⥤ C) (F : C ⥤ Dᵒᵖ) [PreservesLimit K.op F.leftOp] :
    PreservesColimit K F where
  preserves {_} hc :=
⟨isColimitOfConeLeftOpOfCocone _ (isLimitOfPreserves F.leftOp (IsColimit.op hc))⟩

/-- If `F : Cᵒᵖ ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.rightOp : C ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 13
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_rightOp (L117-L123)
lemma preservesColimit_rightOp (K : J ⥤ C) (F : Cᵒᵖ ⥤ D) [PreservesLimit K.op F] :
    PreservesColimit K F.rightOp where
  preserves {_} hc :=
⟨isColimitCoconeRightOpOfCone _ (isLimitOfPreserves F hc.op)⟩

/-- If `F.rightOp : C ⥤ Dᵒᵖ` preserves limits of `K.leftOp : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ D`
preserves colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 14
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_of_rightOp (L124-L130)
lemma preservesColimit_of_rightOp (K : J ⥤ Cᵒᵖ) (F : Cᵒᵖ ⥤ D) [PreservesLimit K.leftOp F.rightOp] :
    PreservesColimit K F where
  preserves {_} hc :=
⟨isColimitOfOp (isLimitOfPreserves F.rightOp (isLimitConeLeftOpOfCocone _ hc))⟩

/-- If `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves limits of `K.op : Jᵒᵖ ⥤ Cᵒᵖ`, then `F.unop : C ⥤ D` preserves
colimits of `K : J ⥤ C`. -/
```

-- snippet 15
```lean
-- Mathlib.CategoryTheory.Limits.Preserves.Opposites.preservesColimit_unop (L131-L137)
lemma preservesColimit_unop (K : J ⥤ C) (F : Cᵒᵖ ⥤ Dᵒᵖ) [PreservesLimit K.op F] :
    PreservesColimit K F.unop where
  preserves {_} hc :=
⟨isColimitCoconeUnopOfCone _ (isLimitOfPreserves F hc.op)⟩

/-- If `F.unop : C ⥤ D` preserves limits of `K.op : Jᵒᵖ ⥤ C`, then `F : Cᵒᵖ ⥤ Dᵒᵖ` preserves
colimits of `K : J ⥤ Cᵒᵖ`. -/
```

-- snippet 16
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBicone (L52-L66)
instance finBicone [Fintype J] : Fintype (Bicone J) where
  elems := [Bicone.left, Bicone.right].toFinset ∪ Finset.image Bicone.diagram Fintype.elems
complete j := by
    cases j <;> simp [Fintype.complete]

variable [Category.{v₁} J]

/-- The homs for a walking `Bicone J`. -/
inductive BiconeHom : Bicone J → Bicone J → Type max u₁ v₁
  | left_id : BiconeHom Bicone.left Bicone.left
  | right_id : BiconeHom Bicone.right Bicone.right
  | left (j : J) : BiconeHom Bicone.left (Bicone.diagram j)
  | right (j : J) : BiconeHom Bicone.right (Bicone.diagram j)
  | diagram {j k : J} (f : j ⟶ k) : BiconeHom (Bicone.diagram j) (Bicone.diagram k)
```

-- snippet 17
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_rightFunc (L208-L218)
instance preservesColimitsOfShape_rightFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.rightFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_snd

end Arrow

namespace StructuredArrow

variable {X : T} {G : A ⥤ T} (F : J ⥤ StructuredArrow X G)

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 18
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_snd (L169-L180)
instance preservesColimitsOfShape_snd [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.snd L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)

end Comma

namespace Arrow

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 19
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.finBiconeHom (L124-L157)
instance finBiconeHom [FinCategory J] (j k : Bicone J) : Fintype (j ⟶ k) := by
cases j <;> cases k
  · exact
      { elems := {BiconeHom.left_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := {BiconeHom.left _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
      { elems := {BiconeHom.right_id}
        complete := fun f => by cases f; simp }
  · exact
    { elems := {BiconeHom.right _}
      complete := fun f => by cases f; simp }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := ∅
      complete := fun f => by cases f }
  · exact
    { elems := Finset.image BiconeHom.diagram Fintype.elems
      complete := fun f => by
        rcases f with (_ | _ | _ | _ | f)
        simp only [Finset.mem_image]
        use f
        simpa using Fintype.complete _ }
```

-- snippet 20
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategoryStruct (L74-L87)
instance biconeCategoryStruct : CategoryStruct (Bicone J) where
  Hom := BiconeHom J
id j := Bicone.casesOn j BiconeHom.left_id BiconeHom.right_id fun k => BiconeHom.diagram (𝟙 k)
  comp f g := by
    rcases f with (_ | _ | _ | _ | f)
    · exact g
    · exact g
    · cases g
      apply BiconeHom.left
    · cases g
      apply BiconeHom.right
    · rcases g with (_ | _ | _ | _ | g)
      exact BiconeHom.diagram (f ≫ g)
```

-- snippet 21
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_right_eq_curry_swap_map (L47-L89)
theorem map_id_right_eq_curry_swap_map {j j' : J} {f : j ⟶ j'} {k : K} :
    F.map (f ×ₘ 𝟙 k) = ((curry.obj (Prod.swap K J ⋙ F)).obj k).map f :=
rfl

variable [HasLimitsOfShape J C]
variable [HasColimitsOfShape K C]

set_option backward.isDefEq.respectTransparency false in
/-- The universal morphism
$\colim_k \lim_j F(j,k) → \lim_j \colim_k F(j, k)$.
-/
noncomputable def colimitLimitToLimitColimit :
    colimit (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) ⟶ limit (curry.obj F ⋙ colim) :=
  limit.lift (curry.obj F ⋙ colim)
    { pt := _
      π :=
        { app := fun j =>
            colimit.desc (curry.obj (Prod.swap K J ⋙ F) ⋙ lim)
              { pt := _
                ι :=
                  { app := fun k =>
                      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫
                        colimit.ι ((curry.obj F).obj j) k
                    naturality := by
                      intro k k' f
                      simp only [Functor.comp_obj, lim_obj, colimit.cocone_x,
                        Functor.const_obj_obj, Functor.comp_map, lim_map,
                        curry_obj_obj_obj, Prod.swap_obj, limMap_π_assoc, curry_obj_map_app,
                        Prod.swap_map, Functor.const_obj_map, Category.comp_id]
                      rw [map_id_left_eq_curry_map, colimit.w] } }
          naturality := by
            intro j j' f
            dsimp
            ext k
            simp only [Functor.comp_obj, lim_obj, Category.id_comp, colimit.ι_desc,
              colimit.ι_desc_assoc, Category.assoc, ι_colimMap,
              curry_obj_obj_obj, curry_obj_map_app]
            rw [map_id_right_eq_curry_swap_map, limit.w_assoc] } }

set_option backward.isDefEq.respectTransparency false in
/-- Since `colimit_limit_to_limit_colimit` is a morphism from a colimit to a limit,
this lemma characterises it.
-/
```

-- snippet 22
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_leftFunc (L204-L207)
instance preservesColimitsOfShape_leftFunc [HasColimitsOfShape J T] :
    PreservesColimitsOfShape J (Arrow.leftFunc : _ ⥤ T) := by
apply Comma.preservesColimitsOfShape_fst
```

-- snippet 23
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π (L91-L96)
theorem ι_colimitLimitToLimitColimit_π (j) (k) :
    colimit.ι _ k ≫ colimitLimitToLimitColimit F ≫ limit.π _ j =
      limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j ≫ colimit.ι ((curry.obj F).obj j) k := by
dsimp [colimitLimitToLimitColimit]
  simp
```

-- snippet 24
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.BiconeHom (L70-L72)
instance BiconeHom.decidableEq {j k : Bicone J} : DecidableEq (BiconeHom J j k) := fun f g => by
classical cases f <;> cases g <;> simp only [diagram.injEq] <;> infer_instance
```

-- snippet 25
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.ι_colimitLimitToLimitColimit_π_apply (L98-L106)
theorem ι_colimitLimitToLimitColimit_π_apply [Small.{v} J] [Small.{v} K] (F : J × K ⥤ Type v)
    (j : J) (k : K) (f) : limit.π (curry.obj F ⋙ colim) j
        (colimitLimitToLimitColimit F (colimit.ι (curry.obj (Prod.swap K J ⋙ F) ⋙ lim) k f)) =
      colimit.ι ((curry.obj F).obj j) k (limit.π ((curry.obj (Prod.swap K J ⋙ F)).obj k) j f) := by
dsimp [colimitLimitToLimitColimit]
  simp

set_option backward.isDefEq.respectTransparency false in
/-- The map `colimit_limit_to_limit_colimit` realized as a map of cones. -/
```

-- snippet 26
```lean
-- Mathlib.CategoryTheory.Limits.Comma.limitAuxiliaryCone (L47-L53)
def limitAuxiliaryCone (c₁ : Cone (F ⋙ fst L R)) : Cone ((F ⋙ snd L R) ⋙ R) :=
(Cone.postcompose (whiskerLeft F (Comma.natTrans L R) :)).obj (L.mapCone c₁)

/-- If `R` preserves the appropriate limit, then given a cone for `F ⋙ fst L R : J ⥤ L` and a
limit cone for `F ⋙ snd L R : J ⥤ R` we can build a cone for `F` which will turn out to be a limit
cone.
-/
```

-- snippet 27
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimitsOfSize (L158-L161)
instance hasColimitsOfSize [HasColimitsOfSize.{w, w'} A] [HasColimitsOfSize.{w, w'} B]
    [PreservesColimitsOfSize.{w, w'} L] : HasColimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 28
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimits (L201-L203)
instance hasColimits [HasColimits T] : HasColimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 29
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimit (L140-L143)
instance hasLimit (F : J ⥤ Comma L R) [HasLimit (F ⋙ fst L R)] [HasLimit (F ⋙ snd L R)]
    [PreservesLimit (F ⋙ snd L R) R] : HasLimit F :=
HasLimit.mk ⟨_, coneOfPreservesIsLimit _ (limit.isLimit _) (limit.isLimit _)⟩
```

-- snippet 30
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimits (L189-L192)
instance hasLimits [HasLimits T] : HasLimits (Arrow T) :=
⟨fun _ _ => inferInstance⟩

set_option backward.isDefEq.respectTransparency false in
```

-- snippet 31
```lean
-- Mathlib.CategoryTheory.Limits.Comma.colimitAuxiliaryCocone (L94-L101)
def colimitAuxiliaryCocone (c₂ : Cocone (F ⋙ snd L R)) : Cocone ((F ⋙ fst L R) ⋙ L) :=
(Cocone.precompose (whiskerLeft F (Comma.natTrans L R) :)).obj (R.mapCocone c₂)

/--
If `L` preserves the appropriate colimit, then given a colimit cocone for `F ⋙ fst L R : J ⥤ L` and
a cocone for `F ⋙ snd L R : J ⥤ R` we can build a cocone for `F` which will turn out to be a
colimit cocone.
-/
```

-- snippet 32
```lean
-- Mathlib.CategoryTheory.Limits.Comma.preservesColimitsOfShape_fst (L162-L168)
instance preservesColimitsOfShape_fst [HasColimitsOfShape J A] [HasColimitsOfShape J B]
    [PreservesColimitsOfShape J L] : PreservesColimitsOfShape J (Comma.fst L R) where
  preservesColimit :=
preservesColimit_of_preserves_colimit_cocone
      (coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _))
      (colimit.isColimit _)
```

-- snippet 33
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasLimitsOfSize (L147-L150)
instance hasLimitsOfSize [HasLimitsOfSize.{w, w'} A] [HasLimitsOfSize.{w, w'} B]
    [PreservesLimitsOfSize.{w, w'} R] : HasLimitsOfSize.{w, w'} (Comma L R) :=
⟨fun _ _ => inferInstance⟩
```

-- snippet 34
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_right_of_mono (L247-L250)
instance mono_right_of_mono [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) [Mono f] : Mono f.right :=
show Mono ((proj X G).map f) from inferInstance
```

-- snippet 35
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeMk (L102-L123)
def biconeMk {C : Type u₁} [Category.{v₁} C] {F : J ⥤ C} (c₁ c₂ : Cone F) : Bicone J ⥤ C where
  obj X := Bicone.casesOn X c₁.pt c₂.pt fun j => F.obj j
map f := by
    rcases f with (_ | _ | _ | _ | f)
    · exact 𝟙 _
    · exact 𝟙 _
    · exact c₁.π.app _
    · exact c₂.π.app _
    · exact F.map f
  map_id X := by cases X <;> simp
  map_comp f g := by
    rcases f with (_ | _ | _ | _ | _)
    · exact (Category.id_comp _).symm
    · exact (Category.id_comp _).symm
    · cases g
      exact (Category.id_comp _).symm.trans (c₁.π.naturality _)
    · cases g
      exact (Category.id_comp _).symm.trans (c₂.π.naturality _)
    · cases g
      apply F.map_comp

open scoped Classical in
```

-- snippet 36
```lean
-- Mathlib.CategoryTheory.Limits.Comma.hasColimit (L151-L154)
instance hasColimit (F : J ⥤ Comma L R) [HasColimit (F ⋙ fst L R)] [HasColimit (F ⋙ snd L R)]
    [PreservesColimit (F ⋙ fst L R) L] : HasColimit F :=
HasColimit.mk ⟨_, coconeOfPreservesIsColimit _ (colimit.isColimit _) (colimit.isColimit _)⟩
```

-- snippet 37
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeSmallCategory (L158-L160)
instance biconeSmallCategory : SmallCategory (Bicone J) :=
CategoryTheory.biconeCategory J
```

-- snippet 38
```lean
-- Mathlib.CategoryTheory.Limits.Bicones.biconeCategory (L88-L100)
instance biconeCategory : Category (Bicone J) where
  id_comp f := by cases f <;> simp
comp_id f := by cases f <;> simp
  assoc f g h := by cases f <;> cases g <;> cases h <;> simp

end Bicone

section SmallCategory

variable (J : Type v₁) [SmallCategory J]

/-- Given a diagram `F : J ⥤ C` and two `Cone F`s, we can join them into a diagram `Bicone J ⥤ C`.
-/
```

-- snippet 39
```lean
-- Mathlib.CategoryTheory.Limits.ColimitLimit.map_id_left_eq_curry_map (L43-L46)
theorem map_id_left_eq_curry_map {j : J} {k k' : K} {f : k ⟶ k'} :
    F.map (𝟙 j ×ₘ f) = ((curry.obj F).obj j).map f :=
rfl
```

-- snippet 40
```lean
-- Mathlib.CategoryTheory.Limits.Comma.mono_iff_mono_right (L251-L260)
theorem mono_iff_mono_right [HasPullbacks A] [PreservesLimitsOfShape WalkingCospan G]
    {Y Z : StructuredArrow X G} (f : Y ⟶ Z) : Mono f ↔ Mono f.right :=
⟨fun _ => inferInstance, fun _ => mono_of_mono_right f⟩

end StructuredArrow

namespace CostructuredArrow

variable {G : A ⥤ T} {X : T} (F : J ⥤ CostructuredArrow G X)
```
[/INST]