l3lab/ntp-mathlib huggingface dataset:
/-- The colimit of `F.flip ⋙ colim` is isomorphic to the colimit of `F ⋙ colim`. -/
noncomputable def colimitFlipCompColimIsoColimitCompColim :
    colimit (F.flip ⋙ colim) ≅ colimit (F ⋙ colim) :=
  (colimitUncurryIsoColimitCompColim _).symm ≪≫
    HasColimit.isoOfNatIso (uncurryObjFlip _) ≪≫
      HasColimit.isoOfEquivalence (Prod.braiding _ _)
          (NatIso.ofComponents fun _ => by 

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
x✝ : K × J
⊢ ((Prod.braiding K J).functor ⋙ uncurry.obj F).obj x✝ ≅ (Prod.swap K J ⋙ uncurry.obj F).obj x✝

Next tactic:
rfl
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_hom (j) (k) :
    colimit.ι (F.flip.obj k) j ≫ colimit.ι (F.flip ⋙ colim) k ≫
      (colimitFlipCompColimIsoColimitCompColim F).hom =
        (colimit.ι _ k ≫ colimit.ι (F ⋙ colim) j : _ ⟶ colimit (F⋙ colim)) := by
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
⊢ colimit.ι ((Functor.flip F).obj k) j ≫
      colimit.ι (Functor.flip F ⋙ colim) k ≫ (colimitFlipCompColimIsoColimitCompColim F).hom =
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j

Next tactic:
dsimp [colimitFlipCompColimIsoColimitCompColim]
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_hom (j) (k) :
    colimit.ι (F.flip.obj k) j ≫ colimit.ι (F.flip ⋙ colim) k ≫
      (colimitFlipCompColimIsoColimitCompColim F).hom =
        (colimit.ι _ k ≫ colimit.ι (F ⋙ colim) j : _ ⟶ colimit (F⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
⊢ colimit.ι ((Functor.flip F).obj k) j ≫
      colimit.ι (Functor.flip F ⋙ colim) k ≫
        (colimitUncurryIsoColimitCompColim (Functor.flip F)).inv ≫
          (HasColimit.isoOfNatIso (uncurryObjFlip F)).hom ≫
            (HasColimit.isoOfEquivalence (Prod.braiding K J)
                  (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).hom ≫
              (colimitUncurryIsoColimitCompColim F).hom =
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j

Next tactic:
slice_lhs 1 3 => simp only []
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_hom (j) (k) :
    colimit.ι (F.flip.obj k) j ≫ colimit.ι (F.flip ⋙ colim) k ≫
      (colimitFlipCompColimIsoColimitCompColim F).hom =
        (colimit.ι _ k ≫ colimit.ι (F ⋙ colim) j : _ ⟶ colimit (F⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  slice_lhs 1 3 => 

Proof state:
case a.a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
| colimit.ι ((Functor.flip F).obj k) j ≫
    colimit.ι (Functor.flip F ⋙ colim) k ≫ (colimitUncurryIsoColimitCompColim (Functor.flip F)).inv
case a.a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
| (HasColimit.isoOfNatIso (uncurryObjFlip F)).hom
case a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
| (HasColimit.isoOfEquivalence (Prod.braiding K J) (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).hom
case a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
| (colimitUncurryIsoColimitCompColim F).hom

Next tactic:
simp only []
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_hom (j) (k) :
    colimit.ι (F.flip.obj k) j ≫ colimit.ι (F.flip ⋙ colim) k ≫
      (colimitFlipCompColimIsoColimitCompColim F).hom =
        (colimit.ι _ k ≫ colimit.ι (F ⋙ colim) j : _ ⟶ colimit (F⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  slice_lhs 1 3 => simp only []
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
j : J
k : K
⊢ (((colimit.ι ((Functor.flip F).obj k) j ≫
            colimit.ι (Functor.flip F ⋙ colim) k ≫ (colimitUncurryIsoColimitCompColim (Functor.flip F)).inv) ≫
          (HasColimit.isoOfNatIso (uncurryObjFlip F)).hom) ≫
        (HasColimit.isoOfEquivalence (Prod.braiding K J)
            (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).hom) ≫
      (colimitUncurryIsoColimitCompColim F).hom =
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j

Next tactic:
simp
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) :
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫
      (colimitFlipCompColimIsoColimitCompColim F).inv =
        (colimit.ι _ j ≫ colimit.ι (F.flip ⋙ colim) k : _ ⟶ colimit (F.flip ⋙ colim)) := by
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
⊢ colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫ (colimitFlipCompColimIsoColimitCompColim F).inv =
    colimit.ι ((Functor.flip F).obj k) j ≫ colimit.ι (Functor.flip F ⋙ colim) k

Next tactic:
dsimp [colimitFlipCompColimIsoColimitCompColim]
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) :
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫
      (colimitFlipCompColimIsoColimitCompColim F).inv =
        (colimit.ι _ j ≫ colimit.ι (F.flip ⋙ colim) k : _ ⟶ colimit (F.flip ⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
⊢ colimit.ι (F.obj j) k ≫
      colimit.ι (F ⋙ colim) j ≫
        (((colimitUncurryIsoColimitCompColim F).inv ≫
              (HasColimit.isoOfEquivalence (Prod.braiding K J)
                  (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).inv) ≫
            (HasColimit.isoOfNatIso (uncurryObjFlip F)).inv) ≫
          (colimitUncurryIsoColimitCompColim (Functor.flip F)).hom =
    colimit.ι ((Functor.flip F).obj k) j ≫ colimit.ι (Functor.flip F ⋙ colim) k

Next tactic:
slice_lhs 1 3 => simp only []
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) :
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫
      (colimitFlipCompColimIsoColimitCompColim F).inv =
        (colimit.ι _ j ≫ colimit.ι (F.flip ⋙ colim) k : _ ⟶ colimit (F.flip ⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  slice_lhs 1 3 => 

Proof state:
case a.a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
| colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫ (colimitUncurryIsoColimitCompColim F).inv
case a.a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
| (HasColimit.isoOfEquivalence (Prod.braiding K J) (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).inv
case a.a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
| (HasColimit.isoOfNatIso (uncurryObjFlip F)).inv
case a
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
| (colimitUncurryIsoColimitCompColim (Functor.flip F)).hom

Next tactic:
simp only []
@[simp, reassoc]
theorem colimitFlipCompColimIsoColimitCompColim_ι_ι_inv (k) (j) :
    colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫
      (colimitFlipCompColimIsoColimitCompColim F).inv =
        (colimit.ι _ j ≫ colimit.ι (F.flip ⋙ colim) k : _ ⟶ colimit (F.flip ⋙ colim)) := by
  dsimp [colimitFlipCompColimIsoColimitCompColim]
  slice_lhs 1 3 => simp only []
  

Proof state:
J K : Type v
inst✝⁶ : SmallCategory J
inst✝⁵ : SmallCategory K
C : Type u
inst✝⁴ : Category.{v, u} C
F : J ⥤ K ⥤ C
inst✝³ : HasColimitsOfShape J C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimitsOfShape (J × K) C
inst✝ : HasColimitsOfShape (K × J) C
k : K
j : J
⊢ (((colimit.ι (F.obj j) k ≫ colimit.ι (F ⋙ colim) j ≫ (colimitUncurryIsoColimitCompColim F).inv) ≫
          (HasColimit.isoOfEquivalence (Prod.braiding K J)
              (NatIso.ofComponents fun x => Iso.refl ((F.obj x.2).obj x.1))).inv) ≫
        (HasColimit.isoOfNatIso (uncurryObjFlip F)).inv) ≫
      (colimitUncurryIsoColimitCompColim (Functor.flip F)).hom =
    colimit.ι ((Functor.flip F).obj k) j ≫ colimit.ι (Functor.flip F ⋙ colim) k

Next tactic:
simp
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the limit of `G` can be computed as
the limit of the limits of the functors `G.obj (j, _)`.
-/
noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ lim) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
⊢ limit G ≅ limit (curry.obj G ⋙ lim)

Next tactic:
have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the limit of `G` can be computed as
the limit of the limits of the functors `G.obj (j, _)`.
-/
noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ lim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
i : G ≅ uncurry.obj (curry.obj G)
⊢ limit G ≅ limit (curry.obj G ⋙ lim)

Next tactic:
haveI : Limits.HasLimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasLimitOfIso i
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the limit of `G` can be computed as
the limit of the limits of the functors `G.obj (j, _)`.
-/
noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ lim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasLimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasLimitOfIso i
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasLimit (uncurry.obj (curry.obj G))
⊢ limit G ≅ limit (curry.obj G ⋙ lim)

Next tactic:
trans limit (uncurry.obj ((@curry J _ K _ C _).obj G))
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the limit of `G` can be computed as
the limit of the limits of the functors `G.obj (j, _)`.
-/
noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ lim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasLimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasLimitOfIso i
  trans limit (uncurry.obj ((@curry J _ K _ C _).obj G))
  · 

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasLimit (uncurry.obj (curry.obj G))
⊢ limit G ≅ limit (uncurry.obj (curry.obj G))

Next tactic:
apply HasLimit.isoOfNatIso i
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the limit of `G` can be computed as
the limit of the limits of the functors `G.obj (j, _)`.
-/
noncomputable def limitIsoLimitCurryCompLim : limit G ≅ limit (curry.obj G ⋙ lim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasLimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasLimitOfIso i
  trans limit (uncurry.obj ((@curry J _ K _ C _).obj G))
  · apply HasLimit.isoOfNatIso i
  · 

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasLimit (uncurry.obj (curry.obj G))
⊢ limit (uncurry.obj (curry.obj G)) ≅ limit (curry.obj G ⋙ lim)

Next tactic:
exact limitUncurryIsoLimitCompLim ((@curry J _ K _ C _).obj G)
@[simp, reassoc]
theorem limitIsoLimitCurryCompLim_hom_π_π {j} {k} :
    (limitIsoLimitCurryCompLim G).hom ≫ limit.π _ j ≫ limit.π _ k = limit.π _ (j, k) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
j : J
k : K
⊢ (limitIsoLimitCurryCompLim G).hom ≫ limit.π (curry.obj G ⋙ lim) j ≫ limit.π ((curry.obj G).obj j) k = limit.π G (j, k)

Next tactic:
simp [limitIsoLimitCurryCompLim, Trans.simple, HasLimit.isoOfNatIso, limitUncurryIsoLimitCompLim]
@[simp, reassoc]
theorem limitIsoLimitCurryCompLim_inv_π {j} {k} :
    (limitIsoLimitCurryCompLim G).inv ≫ limit.π _ (j, k) =
      (limit.π _ j ≫ limit.π _ k : limit (_ ⋙ lim) ⟶ _) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
j : J
k : K
⊢ (limitIsoLimitCurryCompLim G).inv ≫ limit.π G (j, k) = limit.π (curry.obj G ⋙ lim) j ≫ limit.π ((curry.obj G).obj j) k

Next tactic:
rw [← cancel_epi (limitIsoLimitCurryCompLim G).hom]
@[simp, reassoc]
theorem limitIsoLimitCurryCompLim_inv_π {j} {k} :
    (limitIsoLimitCurryCompLim G).inv ≫ limit.π _ (j, k) =
      (limit.π _ j ≫ limit.π _ k : limit (_ ⋙ lim) ⟶ _) := by
  rw [← cancel_epi (limitIsoLimitCurryCompLim G).hom]
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasLimitsOfShape K C
inst✝¹ : HasLimit G
inst✝ : HasLimit (curry.obj G ⋙ lim)
j : J
k : K
⊢ (limitIsoLimitCurryCompLim G).hom ≫ (limitIsoLimitCurryCompLim G).inv ≫ limit.π G (j, k) =
    (limitIsoLimitCurryCompLim G).hom ≫ limit.π (curry.obj G ⋙ lim) j ≫ limit.π ((curry.obj G).obj j) k

Next tactic:
simp
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the colimit of `G` can be computed as
the colimit of the colimits of the functors `G.obj (j, _)`.
-/
noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry.obj G ⋙ colim) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
⊢ colimit G ≅ colimit (curry.obj G ⋙ colim)

Next tactic:
have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the colimit of `G` can be computed as
the colimit of the colimits of the functors `G.obj (j, _)`.
-/
noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry.obj G ⋙ colim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
i : G ≅ uncurry.obj (curry.obj G)
⊢ colimit G ≅ colimit (curry.obj G ⋙ colim)

Next tactic:
haveI : Limits.HasColimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasColimitOfIso i.symm
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the colimit of `G` can be computed as
the colimit of the colimits of the functors `G.obj (j, _)`.
-/
noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry.obj G ⋙ colim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasColimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasColimitOfIso i.symm
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasColimit (uncurry.obj (curry.obj G))
⊢ colimit G ≅ colimit (curry.obj G ⋙ colim)

Next tactic:
trans colimit (uncurry.obj ((@curry J _ K _ C _).obj G))
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the colimit of `G` can be computed as
the colimit of the colimits of the functors `G.obj (j, _)`.
-/
noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry.obj G ⋙ colim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasColimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasColimitOfIso i.symm
  trans colimit (uncurry.obj ((@curry J _ K _ C _).obj G))
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasColimit (uncurry.obj (curry.obj G))
⊢ colimit G ≅ colimit (uncurry.obj (curry.obj G))
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasColimit (uncurry.obj (curry.obj G))
⊢ colimit (uncurry.obj (curry.obj G)) ≅ colimit (curry.obj G ⋙ colim)

Next tactic:
apply HasColimit.isoOfNatIso i
/-- The Fubini theorem for a functor `G : J × K ⥤ C`,
showing that the colimit of `G` can be computed as
the colimit of the colimits of the functors `G.obj (j, _)`.
-/
noncomputable def colimitIsoColimitCurryCompColim : colimit G ≅ colimit (curry.obj G ⋙ colim) := by
  have i : G ≅ uncurry.obj ((@curry J _ K _ C _).obj G) := currying.symm.unitIso.app G
  haveI : Limits.HasColimit (uncurry.obj ((@curry J _ K _ C _).obj G)) := hasColimitOfIso i.symm
  trans colimit (uncurry.obj ((@curry J _ K _ C _).obj G))
  apply HasColimit.isoOfNatIso i
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
i : G ≅ uncurry.obj (curry.obj G)
this : HasColimit (uncurry.obj (curry.obj G))
⊢ colimit (uncurry.obj (curry.obj G)) ≅ colimit (curry.obj G ⋙ colim)

Next tactic:
exact colimitUncurryIsoColimitCompColim ((@curry J _ K _ C _).obj G)
@[simp, reassoc]
theorem colimitIsoColimitCurryCompColim_ι_ι_inv {j} {k} :
    colimit.ι ((curry.obj G).obj j) k ≫ colimit.ι (curry.obj G ⋙ colim) j ≫
      (colimitIsoColimitCurryCompColim G).inv  = colimit.ι _ (j, k) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
j : J
k : K
⊢ colimit.ι ((curry.obj G).obj j) k ≫ colimit.ι (curry.obj G ⋙ colim) j ≫ (colimitIsoColimitCurryCompColim G).inv =
    colimit.ι G (j, k)

Next tactic:
simp [colimitIsoColimitCurryCompColim, Trans.simple, HasColimit.isoOfNatIso,
    colimitUncurryIsoColimitCompColim]
@[simp, reassoc]
theorem colimitIsoColimitCurryCompColim_ι_hom {j} {k} :
    colimit.ι _ (j, k) ≫ (colimitIsoColimitCurryCompColim G).hom =
      (colimit.ι (_) k ≫ colimit.ι (curry.obj G ⋙ colim) j : _ ⟶ colimit (_ ⋙ colim)) := by
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
j : J
k : K
⊢ colimit.ι G (j, k) ≫ (colimitIsoColimitCurryCompColim G).hom =
    colimit.ι ((curry.obj G).obj j) k ≫ colimit.ι (curry.obj G ⋙ colim) j

Next tactic:
rw [← cancel_mono (colimitIsoColimitCurryCompColim G).inv]
@[simp, reassoc]
theorem colimitIsoColimitCurryCompColim_ι_hom {j} {k} :
    colimit.ι _ (j, k) ≫ (colimitIsoColimitCurryCompColim G).hom =
      (colimit.ι (_) k ≫ colimit.ι (curry.obj G ⋙ colim) j : _ ⟶ colimit (_ ⋙ colim)) := by
  rw [← cancel_mono (colimitIsoColimitCurryCompColim G).inv]
  

Proof state:
J K : Type v
inst✝⁵ : SmallCategory J
inst✝⁴ : SmallCategory K
C : Type u
inst✝³ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝² : HasColimitsOfShape K C
inst✝¹ : HasColimit G
inst✝ : HasColimit (curry.obj G ⋙ colim)
j : J
k : K
⊢ (colimit.ι G (j, k) ≫ (colimitIsoColimitCurryCompColim G).hom) ≫ (colimitIsoColimitCurryCompColim G).inv =
    (colimit.ι ((curry.obj G).obj j) k ≫ colimit.ι (curry.obj G ⋙ colim) j) ≫ (colimitIsoColimitCurryCompColim G).inv

Next tactic:
simp
@[simp]
theorem limitCurrySwapCompLimIsoLimitCurryCompLim_hom_π_π {j} {k} :
    (limitCurrySwapCompLimIsoLimitCurryCompLim G).hom ≫ limit.π _ j ≫ limit.π _ k =
      (limit.π _ k ≫ limit.π _ j : limit (_ ⋙ lim) ⟶ _) := by
  

Proof state:
J K : Type v
inst✝³ : SmallCategory J
inst✝² : SmallCategory K
C : Type u
inst✝¹ : Category.{v, u} C
F : J ⥤ K ⥤ C
G : J × K ⥤ C
inst✝ : HasLimits C
j : J
k : K
⊢ (limitCurrySwapCompLimIsoLimitCurryCompLim G).hom ≫ limit.π (curry.obj G ⋙ lim) j ≫ limit.π ((curry.obj G).obj j) k =
    limit.π (curry.obj (Prod.swap K J ⋙ G) ⋙ lim) k ≫ limit.π ((curry.obj (Prod.swap K J ⋙ G)).obj k) j

Next tactic:
dsimp [limitCurrySwapCompLimIsoLimitCurryCompLim]