l3lab/ntp-mathlib huggingface dataset:
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  

Proof state:
case h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
hh : ∀ (I : Cover.Arrow S), Meq.refine (Meq.pullback x I.f) (h1 I) = Meq.refine (Meq.pullback y I.f) (h2 I)
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
⊢ Meq.refine x ex = Meq.refine y ey

Next tactic:
ext1 I
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  

Proof state:
case h.h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
hh : ∀ (I : Cover.Arrow S), Meq.refine (Meq.pullback x I.f) (h1 I) = Meq.refine (Meq.pullback y I.f) (h2 I)
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
⊢ ↑(Meq.refine x ex) I = ↑(Meq.refine y ey) I

Next tactic:
let IS : S.Arrow := I.fromMiddle
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  let IS : S.Arrow := I.fromMiddle
  

Proof state:
case h.h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
hh : ∀ (I : Cover.Arrow S), Meq.refine (Meq.pullback x I.f) (h1 I) = Meq.refine (Meq.pullback y I.f) (h2 I)
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
IS : Cover.Arrow S := Cover.Arrow.fromMiddle I
⊢ ↑(Meq.refine x ex) I = ↑(Meq.refine y ey) I

Next tactic:
specialize hh IS
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  let IS : S.Arrow := I.fromMiddle
  specialize hh IS
  

Proof state:
case h.h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
IS : Cover.Arrow S := Cover.Arrow.fromMiddle I
hh : Meq.refine (Meq.pullback x IS.f) (h1 IS) = Meq.refine (Meq.pullback y IS.f) (h2 IS)
⊢ ↑(Meq.refine x ex) I = ↑(Meq.refine y ey) I

Next tactic:
let IW : (W IS).Arrow := I.toMiddle
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  let IS : S.Arrow := I.fromMiddle
  specialize hh IS
  let IW : (W IS).Arrow := I.toMiddle
  

Proof state:
case h.h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
IS : Cover.Arrow S := Cover.Arrow.fromMiddle I
hh : Meq.refine (Meq.pullback x IS.f) (h1 IS) = Meq.refine (Meq.pullback y IS.f) (h2 IS)
IW : Cover.Arrow (W IS) := Cover.Arrow.toMiddle I
⊢ ↑(Meq.refine x ex) I = ↑(Meq.refine y ey) I

Next tactic:
apply_fun fun e => e IW at hh
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  let IS : S.Arrow := I.fromMiddle
  specialize hh IS
  let IW : (W IS).Arrow := I.toMiddle
  apply_fun fun e => e IW at hh
  

Proof state:
case h.h
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
IS : Cover.Arrow S := Cover.Arrow.fromMiddle I
IW : Cover.Arrow (W IS) := Cover.Arrow.toMiddle I
hh : ↑(Meq.refine (Meq.pullback x IS.f) (h1 IS)) IW = ↑(Meq.refine (Meq.pullback y IS.f) (h2 IS)) IW
⊢ ↑(Meq.refine x ex) I = ↑(Meq.refine y ey) I

Next tactic:
convert hh using 1
/-- `P⁺` is always separated. -/
theorem sep {X : C} (P : Cᵒᵖ ⥤ D) (S : J.Cover X) (x y : (J.plusObj P).obj (op X))
    (h : ∀ I : S.Arrow, (J.plusObj P).map I.f.op x = (J.plusObj P).map I.f.op y) : x = y := by
  -- First, we choose representatives for x and y.
  obtain ⟨Sx, x, rfl⟩ := exists_rep x
  obtain ⟨Sy, y, rfl⟩ := exists_rep y
  simp only [res_mk_eq_mk_pullback] at h
  -- Next, using our assumption,
  -- choose covers over which the pullbacks of these representatives become equal.
  choose W h1 h2 hh using fun I : S.Arrow => (eq_mk_iff_exists _ _).mp (h I)
  -- To prove equality, it suffices to prove that there exists a cover over which
  -- the representatives become equal.
  rw [eq_mk_iff_exists]
  -- Construct the cover over which the representatives become equal by combining the various
  -- covers chosen above.
  let B : J.Cover X := S.bind W
  use B
  -- Prove that this cover refines the two covers over which our representatives are defined
  -- and use these proofs.
  let ex : B ⟶ Sx :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h1 ⟨_, _, he2⟩)
        exact he1)
  let ey : B ⟶ Sy :=
    homOfLE
      (by
        rintro Y f ⟨Z, e1, e2, he2, he1, hee⟩
        rw [← hee]
        apply leOfHom (h2 ⟨_, _, he2⟩)
        exact he1)
  use ex, ey
  -- Now prove that indeed the representatives become equal over `B`.
  -- This will follow by using the fact that our representatives become
  -- equal over the chosen covers.
  ext1 I
  let IS : S.Arrow := I.fromMiddle
  specialize hh IS
  let IW : (W IS).Arrow := I.toMiddle
  apply_fun fun e => e IW at hh
  convert hh using 1
  · let Rx : Sx.Relation :=
      ⟨I.Y, I.Y, I.Y, 𝟙 _, 𝟙 _, I.f, I.toMiddleHom ≫ I.fromMiddleHom, leOfHom ex _ I.hf,
        by 

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
X : C
P : Cᵒᵖ ⥤ D
S Sx : Cover J X
x : Meq P Sx
Sy : Cover J X
y : Meq P Sy
h : ∀ (I : Cover.Arrow S), mk (Meq.pullback x I.f) = mk (Meq.pullback y I.f)
W : (I : Cover.Arrow S) → Cover J I.Y
h1 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sx
h2 : (I : Cover.Arrow S) → W I ⟶ (pullback J I.f).obj Sy
B : Cover J X := Cover.bind S W
ex : B ⟶ Sx := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sx).arrows f)
ey : B ⟶ Sy := homOfLE (_ : ∀ ⦃Y : C⦄ (f : Y ⟶ X), ((fun a => ↑a) B).arrows f → ((fun a => ↑a) Sy).arrows f)
I : Cover.Arrow B
IS : Cover.Arrow S := Cover.Arrow.fromMiddle I
IW : Cover.Arrow (W IS) := Cover.Arrow.toMiddle I
hh : ↑(Meq.refine (Meq.pullback x IS.f) (h1 IS)) IW = ↑(Meq.refine (Meq.pullback y IS.f) (h2 IS)) IW
e_1✝ : (forget D).obj (P.obj (op I.Y)) = (forget D).obj (P.obj (op IW.Y))
⊢ (Cover.sieve Sx).arrows (Cover.Arrow.toMiddleHom I ≫ Cover.Arrow.fromMiddleHom I)

Next tactic:
simpa only [I.middle_spec] using leOfHom ex _ I.hf
theorem inj_of_sep (P : Cᵒᵖ ⥤ D)
    (hsep :
      ∀ (X : C) (S : J.Cover X) (x y : P.obj (op X)),
        (∀ I : S.Arrow, P.map I.f.op x = P.map I.f.op y) → x = y)
    (X : C) : Function.Injective ((J.toPlus P).app (op X)) := by
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
P : Cᵒᵖ ⥤ D
hsep :
  ∀ (X : C) (S : Cover J X) (x y : (forget D).obj (P.obj (op X))),
    (∀ (I : Cover.Arrow S), (P.map I.f.op) x = (P.map I.f.op) y) → x = y
X : C
⊢ Function.Injective ⇑((toPlus J P).app (op X))

Next tactic:
intro x y h
theorem inj_of_sep (P : Cᵒᵖ ⥤ D)
    (hsep :
      ∀ (X : C) (S : J.Cover X) (x y : P.obj (op X)),
        (∀ I : S.Arrow, P.map I.f.op x = P.map I.f.op y) → x = y)
    (X : C) : Function.Injective ((J.toPlus P).app (op X)) := by
  intro x y h
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
P : Cᵒᵖ ⥤ D
hsep :
  ∀ (X : C) (S : Cover J X) (x y : (forget D).obj (P.obj (op X))),
    (∀ (I : Cover.Arrow S), (P.map I.f.op) x = (P.map I.f.op) y) → x = y
X : C
x y : (forget D).obj (P.obj (op X))
h : ((toPlus J P).app (op X)) x = ((toPlus J P).app (op X)) y
⊢ x = y

Next tactic:
simp only [toPlus_eq_mk] at h
theorem inj_of_sep (P : Cᵒᵖ ⥤ D)
    (hsep :
      ∀ (X : C) (S : J.Cover X) (x y : P.obj (op X)),
        (∀ I : S.Arrow, P.map I.f.op x = P.map I.f.op y) → x = y)
    (X : C) : Function.Injective ((J.toPlus P).app (op X)) := by
  intro x y h
  simp only [toPlus_eq_mk] at h
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
P : Cᵒᵖ ⥤ D
hsep :
  ∀ (X : C) (S : Cover J X) (x y : (forget D).obj (P.obj (op X))),
    (∀ (I : Cover.Arrow S), (P.map I.f.op) x = (P.map I.f.op) y) → x = y
X : C
x y : (forget D).obj (P.obj (op X))
h : mk (Meq.mk ⊤ x) = mk (Meq.mk ⊤ y)
⊢ x = y

Next tactic:
rw [eq_mk_iff_exists] at h
theorem inj_of_sep (P : Cᵒᵖ ⥤ D)
    (hsep :
      ∀ (X : C) (S : J.Cover X) (x y : P.obj (op X)),
        (∀ I : S.Arrow, P.map I.f.op x = P.map I.f.op y) → x = y)
    (X : C) : Function.Injective ((J.toPlus P).app (op X)) := by
  intro x y h
  simp only [toPlus_eq_mk] at h
  rw [eq_mk_iff_exists] at h
  

Proof state:
C : Type u
inst✝⁶ : Category.{v, u} C
J : GrothendieckTopology C
D : Type w
inst✝⁵ : Category.{max v u, w} D
inst✝⁴ : ConcreteCategory D
inst✝³ : PreservesLimits (forget D)
inst✝² : ∀ (X : C), HasColimitsOfShape (Cover J X)ᵒᵖ D
inst✝¹ : ∀ (P : Cᵒᵖ ⥤ D) (X : C) (S : Cover J X), HasMultiequalizer (Cover.index S P)
inst✝ : (X : C) → PreservesColimitsOfShape (Cover J X)ᵒᵖ (forget D)
P : Cᵒᵖ ⥤ D
hsep :
  ∀ (X : C) (S : Cover J X) (x y : (forget D).obj (P.obj (op X))),
    (∀ (I : Cover.Arrow S), (P.map I.f.op) x = (P.map I.f.op) y) → x = y
X : C
x y : (forget D).obj (P.obj (op X))
h : ∃ W h1 h2, Meq.refine (Meq.mk ⊤ x) h1 = Meq.refine (Meq.mk ⊤ y) h2
⊢ x = y

Next tactic:
obtain ⟨W, h1, h2, hh⟩ := h