l3lab/ntp-mathlib huggingface dataset:
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · exact h _ cpt.sectionPairwise.prop
  · specialize h (fun i ↦ s <| op <| Pairwise.single i) fun i j ↦
      (hs <| op <| Pairwise.Hom.left i j).trans (hs <| op <| Pairwise.Hom.right i j).symm
    convert h; ext (i|⟨i,j⟩)
    · rfl
    · 

Proof state:
case h.e'_2.h.h.h.h.e'_3.h.e.h.mk.pair
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
s : (j : (CategoryTheory.Pairwise ι)ᵒᵖ) → ((Pairwise.diagram U).op ⋙ F).obj j
hs : s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)
h :
  ∃! s_1,
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s_1 =
        objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) i
e_1✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt = (forget (Type u)).obj (F.obj (op (iSup U)))
x✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt
a✝ : (CategoryTheory.Pairwise ι)ᵒᵖ
i j : ι
⊢ s { unop := Pairwise.pair i j } =
    objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) { unop := Pairwise.pair i j }

Next tactic:
exact (hs <| op <| Pairwise.Hom.left i j).symm
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
⊢ ∃! s, ∀ (i : ι), (F.val.map (iUV i).op) s = sf i

Next tactic:
have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
⊢ ∃! s, ∀ (i : ι), (F.val.map (iUV i).op) s = sf i

Next tactic:
obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  

Proof state:
case intro.intro
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
⊢ ∃! s, ∀ (i : ι), (F.val.map (iUV i).op) s = sf i

Next tactic:
refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · 

Proof state:
case intro.intro.refine'_1
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
⊢ (fun s => ∀ (i : ι), (F.val.map (iUV i).op) s = sf i) ((F.val.map (eqToHom V_eq_supr_U).op) gl)

Next tactic:
intro i
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    

Proof state:
case intro.intro.refine'_1
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
i : ι
⊢ (F.val.map (iUV i).op) ((F.val.map (eqToHom V_eq_supr_U).op) gl) = sf i

Next tactic:
rw [← comp_apply, ← F.1.map_comp]
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    

Proof state:
case intro.intro.refine'_1
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
i : ι
⊢ (F.val.map ((eqToHom V_eq_supr_U).op ≫ (iUV i).op)) gl = sf i

Next tactic:
exact gl_spec i
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · 

Proof state:
case intro.intro.refine'_2
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
⊢ ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op V))),
    (fun s => ∀ (i : ι), (F.val.map (iUV i).op) s = sf i) y → y = (F.val.map (eqToHom V_eq_supr_U).op) gl

Next tactic:
intro gl' gl'_spec
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · intro gl' gl'_spec
    

Proof state:
case intro.intro.refine'_2
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
gl' : (CategoryTheory.forget C).obj (F.val.obj (op V))
gl'_spec : ∀ (i : ι), (F.val.map (iUV i).op) gl' = sf i
⊢ gl' = (F.val.map (eqToHom V_eq_supr_U).op) gl

Next tactic:
convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _)
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · intro gl' gl'_spec
    convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _) <;>
      

Proof state:
case h.e'_2
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
gl' : (CategoryTheory.forget C).obj (F.val.obj (op V))
gl'_spec : ∀ (i : ι), (F.val.map (iUV i).op) gl' = sf i
⊢ gl' = (F.val.map (eqToHom V_eq_supr_U).op) ((F.val.map (eqToHom (_ : iSup U = V)).op) gl')

Next tactic:
rw [← comp_apply, ← F.1.map_comp]
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · intro gl' gl'_spec
    convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _) <;>
      

Proof state:
case intro.intro.refine'_2.convert_3
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
gl' : (CategoryTheory.forget C).obj (F.val.obj (op V))
gl'_spec : ∀ (i : ι), (F.val.map (iUV i).op) gl' = sf i
i : ι
⊢ (F.val.map (leSupr U i).op) ((F.val.map (eqToHom (_ : iSup U = V)).op) gl') = sf i

Next tactic:
rw [← comp_apply, ← F.1.map_comp]
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · intro gl' gl'_spec
    convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _) <;>
      rw [← comp_apply, ← F.1.map_comp]
    · 

Proof state:
case h.e'_2
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
gl' : (CategoryTheory.forget C).obj (F.val.obj (op V))
gl'_spec : ∀ (i : ι), (F.val.map (iUV i).op) gl' = sf i
⊢ gl' = (F.val.map ((eqToHom (_ : iSup U = V)).op ≫ (eqToHom V_eq_supr_U).op)) gl'

Next tactic:
rw [eqToHom_op, eqToHom_op, eqToHom_trans, eqToHom_refl, F.1.map_id, id_apply]
/-- In this version of the lemma, the inclusion homs `iUV` can be specified directly by the user,
which can be more convenient in practice.
-/
theorem existsUnique_gluing' (V : Opens X) (iUV : ∀ i : ι, U i ⟶ V) (hcover : V ≤ iSup U)
    (sf : ∀ i : ι, F.1.obj (op (U i))) (h : IsCompatible F.1 U sf) :
    ∃! s : F.1.obj (op V), ∀ i : ι, F.1.map (iUV i).op s = sf i := by
  have V_eq_supr_U : V = iSup U := le_antisymm hcover (iSup_le fun i => (iUV i).le)
  obtain ⟨gl, gl_spec, gl_uniq⟩ := F.existsUnique_gluing U sf h
  refine' ⟨F.1.map (eqToHom V_eq_supr_U).op gl, _, _⟩
  · intro i
    rw [← comp_apply, ← F.1.map_comp]
    exact gl_spec i
  · intro gl' gl'_spec
    convert congr_arg _ (gl_uniq (F.1.map (eqToHom V_eq_supr_U.symm).op gl') fun i => _) <;>
      rw [← comp_apply, ← F.1.map_comp]
    · rw [eqToHom_op, eqToHom_op, eqToHom_trans, eqToHom_refl, F.1.map_id, id_apply]
    · 

Proof state:
case intro.intro.refine'_2.convert_3
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
V : Opens ↑X
iUV : (i : ι) → U i ⟶ V
hcover : V ≤ iSup U
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i)))
h : IsCompatible F.val U sf
V_eq_supr_U : V = iSup U
gl : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
gl_spec : IsGluing F.val U sf gl
gl_uniq : ∀ (y : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))), (fun s => IsGluing F.val U sf s) y → y = gl
gl' : (CategoryTheory.forget C).obj (F.val.obj (op V))
gl'_spec : ∀ (i : ι), (F.val.map (iUV i).op) gl' = sf i
i : ι
⊢ (F.val.map ((eqToHom (_ : iSup U = V)).op ≫ (leSupr U i).op)) gl' = sf i

Next tactic:
convert gl'_spec i
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
⊢ s = t

Next tactic:
let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i))) := fun i => (F.val.map (leSupr U i).op) s
⊢ s = t

Next tactic:
have sf_compatible : IsCompatible _ U sf := by
    intro i j
    simp_rw [← comp_apply, ← F.1.map_comp]
    rfl
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
  have sf_compatible : IsCompatible _ U sf := by
    

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i))) := fun i => (F.val.map (leSupr U i).op) s
⊢ IsCompatible F.val U sf

Next tactic:
intro i j
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
  have sf_compatible : IsCompatible _ U sf := by
    intro i j
    

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i))) := fun i => (F.val.map (leSupr U i).op) s
i j : ι
⊢ (F.val.map (infLELeft (U i) (U j)).op) (sf i) = (F.val.map (infLERight (U i) (U j)).op) (sf j)

Next tactic:
simp_rw [← comp_apply, ← F.1.map_comp]
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
  have sf_compatible : IsCompatible _ U sf := by
    intro i j
    simp_rw [← comp_apply, ← F.1.map_comp]
    

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i))) := fun i => (F.val.map (leSupr U i).op) s
i j : ι
⊢ (F.val.map ((leSupr U i).op ≫ (infLELeft (U i) (U j)).op)) s =
    (F.val.map ((leSupr U j).op ≫ (infLERight (U i) (U j)).op)) s

Next tactic:
rfl
@[ext]
theorem eq_of_locally_eq (s t : F.1.obj (op (iSup U)))
    (h : ∀ i, F.1.map (Opens.leSupr U i).op s = F.1.map (Opens.leSupr U i).op t) : s = t := by
  let sf : ∀ i : ι, F.1.obj (op (U i)) := fun i => F.1.map (Opens.leSupr U i).op s
  have sf_compatible : IsCompatible _ U sf := by
    intro i j
    simp_rw [← comp_apply, ← F.1.map_comp]
    rfl
  

Proof state:
C : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : ConcreteCategory C
inst✝² : HasLimits C
inst✝¹ : ReflectsIsomorphisms ConcreteCategory.forget
inst✝ : PreservesLimits ConcreteCategory.forget
X : TopCat
F : Sheaf C X
ι : Type v
U : ι → Opens ↑X
s t : (CategoryTheory.forget C).obj (F.val.obj (op (iSup U)))
h : ∀ (i : ι), (F.val.map (leSupr U i).op) s = (F.val.map (leSupr U i).op) t
sf : (i : ι) → (CategoryTheory.forget C).obj (F.val.obj (op (U i))) := fun i => (F.val.map (leSupr U i).op) s
sf_compatible : IsCompatible F.val U sf
⊢ s = t

Next tactic:
obtain ⟨gl, -, gl_uniq⟩ := F.existsUnique_gluing U sf sf_compatible