l3lab/ntp-mathlib huggingface dataset:
/--
(Implementation). `sheafCoyonedaHom` but the order of the arguments of the functor are swapped.
-/
noncomputable def sheafYonedaHom (α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val) :
    ℱ ⋙ yoneda ⟶ ℱ'.val ⋙ yoneda := by
  let α := sheafCoyonedaHom α
  refine'
    { app := _
      naturality := _ }
  · intro U
    refine'
      { app := fun X => (α.app X).app U
        naturality := fun X Y f => by simpa using congr_app (α.naturality f) U }
  · intro U V i
    ext X x
    

Proof state:
case refine'_2.w.h.h
C : Type u_1
inst✝⁵ : Category.{?u.91921, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.91928, u_2} D
E : Type u_3
inst✝³ : Category.{?u.91935, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.91987, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ : Dᵒᵖ ⥤ A
ℱ' : Sheaf K A
α✝ : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
α : coyoneda ⋙ (whiskeringLeft Dᵒᵖ A (Type ?u.91987)).obj ℱ ⟶
  coyoneda ⋙ (whiskeringLeft Dᵒᵖ A (Type ?u.91987)).obj ℱ'.val :=
  sheafCoyonedaHom α✝
U V : Dᵒᵖ
i : U ⟶ V
X : Aᵒᵖ
x : ((ℱ ⋙ yoneda).obj U).obj X
⊢ ((ℱ ⋙ yoneda).map i ≫ NatTrans.mk fun X => (α.app X).app V).app X x =
    ((NatTrans.mk fun X => (α.app X).app U) ≫ (ℱ'.val ⋙ yoneda).map i).app X x

Next tactic:
exact congr_fun ((α.app X).naturality i) x
/-- Given a natural transformation `G ⋙ ℱ ⟶ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ'` is a sheaf, we may obtain a natural transformation
between presheaves.
-/
noncomputable def sheafHom (α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val) : ℱ ⟶ ℱ'.val :=
  let α' := sheafYonedaHom α
  { app := fun X => yoneda.preimage (α'.app X)
    naturality := fun X Y f => yoneda.map_injective (by 

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.101598, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.101605, u_2} D
E : Type u_3
inst✝³ : Category.{?u.101612, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.101664, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ : Dᵒᵖ ⥤ A
ℱ' : Sheaf K A
α : G.op ⋙ ℱ ⟶ G.op ⋙ ℱ'.val
α' : ℱ ⋙ yoneda ⟶ ℱ'.val ⋙ yoneda := sheafYonedaHom α
X Y : Dᵒᵖ
f : X ⟶ Y
⊢ yoneda.map (ℱ.map f ≫ (fun X => yoneda.preimage (α'.app X)) Y) =
    yoneda.map ((fun X => yoneda.preimage (α'.app X)) X ≫ ℱ'.val.map f)

Next tactic:
simpa using α'.naturality f
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
⊢ ℱ.val ≅ ℱ'.val

Next tactic:
have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
⊢ ∀ (X : Dᵒᵖ), IsIso ((sheafHom i.hom).app X)

Next tactic:
intro X
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
⊢ IsIso ((sheafHom i.hom).app X)

Next tactic:
suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
this : IsIso (yoneda.map ((sheafHom i.hom).app X))
⊢ IsIso ((sheafHom i.hom).app X)

Next tactic:
apply isIso_of_reflects_iso _ yoneda
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
⊢ IsIso (yoneda.map ((sheafHom i.hom).app X))

Next tactic:
use (sheafYonedaHom i.inv).app X
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    

Proof state:
case h
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
⊢ yoneda.map ((sheafHom i.hom).app X) ≫ (sheafYonedaHom i.inv).app X = 𝟙 (yoneda.obj (ℱ.val.obj X)) ∧
    (sheafYonedaHom i.inv).app X ≫ yoneda.map ((sheafHom i.hom).app X) = 𝟙 (yoneda.obj (ℱ'.val.obj X))

Next tactic:
constructor
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> 

Proof state:
case h.left
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
⊢ yoneda.map ((sheafHom i.hom).app X) ≫ (sheafYonedaHom i.inv).app X = 𝟙 (yoneda.obj (ℱ.val.obj X))

Next tactic:
ext x : 2
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> 

Proof state:
case h.right
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
⊢ (sheafYonedaHom i.inv).app X ≫ yoneda.map ((sheafHom i.hom).app X) = 𝟙 (yoneda.obj (ℱ'.val.obj X))

Next tactic:
ext x : 2
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      

Proof state:
case h.left.w.h
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
x : Aᵒᵖ
⊢ (yoneda.map ((sheafHom i.hom).app X) ≫ (sheafYonedaHom i.inv).app X).app x = (𝟙 (yoneda.obj (ℱ.val.obj X))).app x

Next tactic:
simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      

Proof state:
case h.right.w.h
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
x : Aᵒᵖ
⊢ ((sheafYonedaHom i.inv).app X ≫ yoneda.map ((sheafHom i.hom).app X)).app x = (𝟙 (yoneda.obj (ℱ'.val.obj X))).app x

Next tactic:
simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · 

Proof state:
case h.left.w.h
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
x : Aᵒᵖ
⊢ ((sheafYonedaHom i.hom).app X).app x ≫ ((sheafYonedaHom i.inv).app X).app x = 𝟙 ((yoneda.obj (ℱ.val.obj X)).obj x)

Next tactic:
exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
    · 

Proof state:
case h.right.w.h
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
X : Dᵒᵖ
x : Aᵒᵖ
⊢ ((sheafYonedaHom i.inv).app X).app x ≫ ((sheafYonedaHom i.hom).app X).app x = 𝟙 ((yoneda.obj (ℱ'.val.obj X)).obj x)

Next tactic:
exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id
    -- porting note: Lean 4 proof is finished, Lean 3 needed `inferInstance`
  

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
this : ∀ (X : Dᵒᵖ), IsIso ((sheafHom i.hom).app X)
⊢ ℱ.val ≅ ℱ'.val

Next tactic:
haveI : IsIso (sheafHom i.hom) := by apply NatIso.isIso_of_isIso_app
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id
    -- porting note: Lean 4 proof is finished, Lean 3 needed `inferInstance`
  haveI : IsIso (sheafHom i.hom) := by 

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
this : ∀ (X : Dᵒᵖ), IsIso ((sheafHom i.hom).app X)
⊢ IsIso (sheafHom i.hom)

Next tactic:
apply NatIso.isIso_of_isIso_app
/-- Given a natural isomorphism `G ⋙ ℱ ≅ G ⋙ ℱ'` between presheaves of arbitrary category,
where `G` is full and cover-dense, and `ℱ', ℱ` are sheaves,
we may obtain a natural isomorphism between presheaves.
-/
@[simps!]
noncomputable def presheafIso {ℱ ℱ' : Sheaf K A} (i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val) :
    ℱ.val ≅ ℱ'.val := by
  have : ∀ X : Dᵒᵖ, IsIso ((sheafHom i.hom).app X) := by
    intro X
    -- porting note: somehow `apply` in Lean 3 is leaving a typeclass goal,
    -- perhaps due to elaboration order. The corresponding `apply` in Lean 4 fails
    -- because the instance can't yet be synthesized. I hence reorder the proof.
    suffices IsIso (yoneda.map ((sheafHom i.hom).app X)) by
      apply isIso_of_reflects_iso _ yoneda
    use (sheafYonedaHom i.inv).app X
    constructor <;> ext x : 2 <;>
      simp only [sheafHom, NatTrans.comp_app, NatTrans.id_app, Functor.image_preimage]
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).hom_inv_id
    · exact ((Types.presheafIso (isoOver i (unop x))).app X).inv_hom_id
    -- porting note: Lean 4 proof is finished, Lean 3 needed `inferInstance`
  haveI : IsIso (sheafHom i.hom) := by apply NatIso.isIso_of_isIso_app
  

Proof state:
C : Type u_1
inst✝⁵ : Category.{?u.109114, u_1} C
D : Type u_2
inst✝⁴ : Category.{?u.109121, u_2} D
E : Type u_3
inst✝³ : Category.{?u.109128, u_3} E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
A : Type u_4
inst✝² : Category.{?u.109180, u_4} A
G : C ⥤ D
inst✝¹ : IsCoverDense G K
inst✝ : Full G
ℱ✝ : Dᵒᵖ ⥤ A
ℱ'✝ ℱ ℱ' : Sheaf K A
i : G.op ⋙ ℱ.val ≅ G.op ⋙ ℱ'.val
this✝ : ∀ (X : Dᵒᵖ), IsIso ((sheafHom i.hom).app X)
this : IsIso (sheafHom i.hom)
⊢ ℱ.val ≅ ℱ'.val

Next tactic:
apply asIso (sheafHom i.hom)