l3lab/ntp-mathlib huggingface dataset:
/-- If `F G : presheaf C X` are isomorphic presheaves,
then the `fork F U`, the canonical cone of the sheaf condition diagram for `F`,
is isomorphic to `fork F G` postcomposed with the corresponding isomorphism between
sheaf condition diagrams.
-/
def fork.isoOfIso (α : F ≅ G) :
    fork F U ≅ (Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U) := by
  fapply Fork.ext
  · apply α.app
  · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
    -- See https://github.com/leanprover-community/mathlib4/issues/5229
    

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
G : Presheaf C X
α : F ≅ G
⊢ autoParam
    ((α.app (op (iSup U))).hom ≫ Fork.ι ((Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U)) =
      Fork.ι (fork F U))
    _auto✝

Next tactic:
refine limit.hom_ext (fun _ => ?_)
/-- If `F G : presheaf C X` are isomorphic presheaves,
then the `fork F U`, the canonical cone of the sheaf condition diagram for `F`,
is isomorphic to `fork F G` postcomposed with the corresponding isomorphism between
sheaf condition diagrams.
-/
def fork.isoOfIso (α : F ≅ G) :
    fork F U ≅ (Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U) := by
  fapply Fork.ext
  · apply α.app
  · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
    -- See https://github.com/leanprover-community/mathlib4/issues/5229
    refine limit.hom_ext (fun _ => ?_)
    

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
G : Presheaf C X
α : F ≅ G
x✝ : Discrete ι
⊢ ((α.app (op (iSup U))).hom ≫ Fork.ι ((Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U))) ≫
      limit.π (Discrete.functor fun i => F.obj (op (U i))) x✝ =
    Fork.ι (fork F U) ≫ limit.π (Discrete.functor fun i => F.obj (op (U i))) x✝

Next tactic:
dsimp only [Fork.ι]
/-- If `F G : presheaf C X` are isomorphic presheaves,
then the `fork F U`, the canonical cone of the sheaf condition diagram for `F`,
is isomorphic to `fork F G` postcomposed with the corresponding isomorphism between
sheaf condition diagrams.
-/
def fork.isoOfIso (α : F ≅ G) :
    fork F U ≅ (Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U) := by
  fapply Fork.ext
  · apply α.app
  · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
    -- See https://github.com/leanprover-community/mathlib4/issues/5229
    refine limit.hom_ext (fun _ => ?_)
    dsimp only [Fork.ι]
    -- Ugh, `simp` can't unfold abbreviations.
    

Proof state:
case w
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
G : Presheaf C X
α : F ≅ G
x✝ : Discrete ι
⊢ ((α.app (op (iSup U))).hom ≫
        ((Cones.postcompose (diagram.isoOfIso U α).inv).obj (fork G U)).π.app WalkingParallelPair.zero) ≫
      limit.π (Discrete.functor fun i => F.obj (op (U i))) x✝ =
    (fork F U).π.app WalkingParallelPair.zero ≫ limit.π (Discrete.functor fun i => F.obj (op (U i))) x✝

Next tactic:
simp only [res, diagram.isoOfIso, Iso.app_hom, piOpens.isoOfIso, Cones.postcompose_obj_π,
      NatTrans.comp_app, fork_π_app_walkingParallelPair_zero, NatIso.ofComponents_inv_app,
      Functor.mapIso_inv, lim_map, limit.lift_map, Category.assoc, limit.lift_π, Fan.mk_π_app,
      Discrete.natIso_inv_app, Iso.app_inv, NatTrans.naturality, Iso.hom_inv_id_app_assoc]
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
Y Z : WalkingParallelPair
f : Y ⟶ Z
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        Z =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        Y ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases Y
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> 

Proof state:
case zero
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
Z : WalkingParallelPair
f : WalkingParallelPair.zero ⟶ Z
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        Z =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases Z
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> 

Proof state:
case one
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
Z : WalkingParallelPair
f : WalkingParallelPair.one ⟶ Z
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        Z =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases Z
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> 

Proof state:
case zero.zero
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
f : WalkingParallelPair.zero ⟶ WalkingParallelPair.zero
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases f
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> 

Proof state:
case zero.one
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
f : WalkingParallelPair.zero ⟶ WalkingParallelPair.one
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases f
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> 

Proof state:
case one.zero
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
f : WalkingParallelPair.one ⟶ WalkingParallelPair.zero
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases f
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> 

Proof state:
case one.one
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
f : WalkingParallelPair.one ⟶ WalkingParallelPair.one
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map f ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one ≫
      (SheafConditionEqualizerProducts.diagram F U).map f

Next tactic:
cases f
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          

Proof state:
case zero.zero.id
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map (WalkingParallelPairHom.id WalkingParallelPair.zero) ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero ≫
      (SheafConditionEqualizerProducts.diagram F U).map (WalkingParallelPairHom.id WalkingParallelPair.zero)

Next tactic:
refine limit.hom_ext fun i => ?_
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          

Proof state:
case zero.zero.id
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
i : Discrete ι
⊢ (((Functor.const WalkingParallelPair).obj c.pt).map (WalkingParallelPairHom.id WalkingParallelPair.zero) ≫
        (fun Z =>
            WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
              (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
          WalkingParallelPair.zero) ≫
      limit.π (Discrete.functor fun i => F.obj (op (U i))) i =
    ((fun Z =>
            WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
              (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
          WalkingParallelPair.zero ≫
        (SheafConditionEqualizerProducts.diagram F U).map (WalkingParallelPairHom.id WalkingParallelPair.zero)) ≫
      limit.π (Discrete.functor fun i => F.obj (op (U i))) i

Next tactic:
dsimp
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          dsimp
          

Proof state:
case zero.zero.id
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
i : Discrete ι
⊢ (𝟙 c.pt ≫ Pi.lift fun i => c.π.app (op (single i))) ≫ limit.π (Discrete.functor fun i => F.obj (op (U i))) i =
    ((Pi.lift fun i => c.π.app (op (single i))) ≫
        (SheafConditionEqualizerProducts.diagram F U).map (𝟙 WalkingParallelPair.zero)) ≫
      limit.π (Discrete.functor fun i => F.obj (op (U i))) i

Next tactic:
simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app, CategoryTheory.Functor.map_id,
            Category.assoc]
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app, CategoryTheory.Functor.map_id,
            Category.assoc]
          

Proof state:
case zero.zero.id
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
i : Discrete ι
⊢ c.π.app (op (single i.as)) =
    (Pi.lift fun i => c.π.app (op (single i))) ≫
      𝟙 ((SheafConditionEqualizerProducts.diagram F U).obj WalkingParallelPair.zero) ≫
        limit.π (Discrete.functor fun i => F.obj (op (U i))) i

Next tactic:
dsimp
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app, CategoryTheory.Functor.map_id,
            Category.assoc]
          dsimp
          

Proof state:
case zero.zero.id
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
i : Discrete ι
⊢ c.π.app (op (single i.as)) =
    (Pi.lift fun i => c.π.app (op (single i))) ≫
      𝟙 (SheafConditionEqualizerProducts.piOpens F U) ≫ limit.π (Discrete.functor fun i => F.obj (op (U i))) i

Next tactic:
simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app]
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app, CategoryTheory.Functor.map_id,
            Category.assoc]
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app]
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          

Proof state:
case zero.one.left
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
⊢ ((Functor.const WalkingParallelPair).obj c.pt).map WalkingParallelPairHom.left ≫
      (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.one =
    (fun Z =>
          WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
            (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
        WalkingParallelPair.zero ≫
      (SheafConditionEqualizerProducts.diagram F U).map WalkingParallelPairHom.left

Next tactic:
refine limit.hom_ext fun ⟨i, j⟩ => ?_
/-- Implementation of `SheafConditionPairwiseIntersections.coneEquiv`. -/
@[simps]
def coneEquivFunctorObj (c : Cone ((diagram U).op ⋙ F)) :
    Cone (SheafConditionEqualizerProducts.diagram F U) where
  pt := c.pt
  π :=
    { app := fun Z =>
        WalkingParallelPair.casesOn Z (Pi.lift fun i : ι => c.π.app (op (single i)))
          (Pi.lift fun b : ι × ι => c.π.app (op (pair b.1 b.2)))
      naturality := fun Y Z f => by
        cases Y <;> cases Z <;> cases f
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun i => ?_
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app, CategoryTheory.Functor.map_id,
            Category.assoc]
          dsimp
          simp only [limit.lift_π, Category.id_comp, Fan.mk_π_app]
        · -- Porting note : `ext` can't see `limit.hom_ext` applies here:
          -- See https://github.com/leanprover-community/mathlib4/issues/5229
          refine limit.hom_ext fun ⟨i, j⟩ => ?_
          

Proof state:
case zero.one.left
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasProducts C
X : TopCat
F : Presheaf C X
ι : Type v'
U : ι → Opens ↑X
c : Cone ((diagram U).op ⋙ F)
x✝ : Discrete (ι × ι)
i j : ι
⊢ (((Functor.const WalkingParallelPair).obj c.pt).map WalkingParallelPairHom.left ≫
        (fun Z =>
            WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
              (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
          WalkingParallelPair.one) ≫
      limit.π (Discrete.functor fun p => F.obj (op (U p.1 ⊓ U p.2))) { as := (i, j) } =
    ((fun Z =>
            WalkingParallelPair.casesOn Z (Pi.lift fun i => c.π.app (op (single i)))
              (Pi.lift fun b => c.π.app (op (Pairwise.pair b.1 b.2))))
          WalkingParallelPair.zero ≫
        (SheafConditionEqualizerProducts.diagram F U).map WalkingParallelPairHom.left) ≫
      limit.π (Discrete.functor fun p => F.obj (op (U p.1 ⊓ U p.2))) { as := (i, j) }

Next tactic:
dsimp [SheafConditionEqualizerProducts.leftRes]