Theorem: CategoryTheory.Presheaf.subsingleton_iff_isSeparatedFor
File: Mathlib/CategoryTheory/Sites/Sheaf.lean

tactic: constructor
state_before: C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : x.SieveCompatible
⊢ (∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)) ↔
    ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
state_after: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : x.SieveCompatible
⊢ (∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)) →
    ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows

case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : x.SieveCompatible
⊢ (∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows) →
    ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)

tactic: intro hs E x t₁ t₂ h₁ h₂
state_before: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : x.SieveCompatible
⊢ (∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)) →
    ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
state_after: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
⊢ t₁ = t₂

tactic: have hx := is_compatible_of_exists_amalgamation x ⟨t₁, h₁⟩
state_before: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
⊢ t₁ = t₂
state_after: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.Compatible
⊢ t₁ = t₂

tactic: rw [compatible_iff_sieveCompatible] at hx
state_before: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.Compatible
⊢ t₁ = t₂
state_after: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
⊢ t₁ = t₂

tactic: specialize hs hx.cone
state_before: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
hs : ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
⊢ t₁ = t₂
state_after: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
hs : Subsingleton (hx.cone ⟶ P.mapCone S.arrows.cocone.op)
⊢ t₁ = t₂

tactic: rcases hs with ⟨hs⟩
state_before: case mp
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
hs : Subsingleton (hx.cone ⟶ P.mapCone S.arrows.cocone.op)
⊢ t₁ = t₂
state_after: case mp.intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
hs : ∀ (a b : hx.cone ⟶ P.mapCone S.arrows.cocone.op), a = b
⊢ t₁ = t₂

tactic: simpa only [Subtype.mk.injEq] using (show Subtype.mk t₁ h₁ = ⟨t₂, h₂⟩ from
  (homEquivAmalgamation hx).symm.injective (hs _ _))
state_before: case mp.intro
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x✝ : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx✝ : x✝.SieveCompatible
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
t₁ t₂ : (P ⋙ coyoneda.obj E).obj { unop := X }
h₁ : x.IsAmalgamation t₁
h₂ : x.IsAmalgamation t₂
hx : x.SieveCompatible
hs : ∀ (a b : hx.cone ⟶ P.mapCone S.arrows.cocone.op), a = b
⊢ t₁ = t₂
state_after: no goals

tactic: rintro h ⟨E, π⟩
state_before: case mpr
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E) S.arrows
hx : x.SieveCompatible
⊢ (∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows) →
    ∀ (c : Cone (S.arrows.diagram.op ⋙ P)), Subsingleton (c ⟶ P.mapCone S.arrows.cocone.op)
state_after: case mpr.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
⊢ Subsingleton ({ pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op)

tactic: let eqv := conesEquivSieveCompatibleFamily P S (op E)
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
⊢ Subsingleton ({ pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op)
state_after: case mpr.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ Subsingleton ({ pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op)

tactic: constructor
state_before: case mpr.mk
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ Subsingleton ({ pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op)
state_after: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ ∀ (a b : { pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op), a = b

tactic: rw [← eqv.left_inv π]
state_before: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ ∀ (a b : { pt := E, π := π } ⟶ P.mapCone S.arrows.cocone.op), a = b
state_after: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ ∀ (a b : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op), a = b

tactic: intro f₁ f₂
state_before: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
⊢ ∀ (a b : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op), a = b
state_after: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
⊢ f₁ = f₂

tactic: let eqv' := homEquivAmalgamation (eqv π).2
state_before: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
⊢ f₁ = f₂
state_after: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ f₁ = f₂

tactic: apply eqv'.injective
state_before: case mpr.mk.allEq
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ f₁ = f₂
state_after: case mpr.mk.allEq.a
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ eqv' f₁ = eqv' f₂

tactic: ext
state_before: case mpr.mk.allEq.a
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ eqv' f₁ = eqv' f₂
state_after: case mpr.mk.allEq.a.a
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ ↑(eqv' f₁) = ↑(eqv' f₂)

tactic: apply h _ (eqv π).1 <;> exact (eqv' _).2
state_before: case mpr.mk.allEq.a.a
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
A : Type u₂
inst✝ : Category.{v₂, u₂} A
J : GrothendieckTopology C
P : Cᵒᵖ ⥤ A
X : C
S : Sieve X
R : Presieve X
E✝ : Aᵒᵖ
x : FamilyOfElements (P ⋙ coyoneda.obj E✝) S.arrows
hx : x.SieveCompatible
h : ∀ (E : Aᵒᵖ), IsSeparatedFor (P ⋙ coyoneda.obj E) S.arrows
E : A
π : (Functor.const S.arrows.categoryᵒᵖ).obj E ⟶ S.arrows.diagram.op ⋙ P
eqv : (S.arrows.diagram.op ⋙ P).cones.obj { unop := E } ≃ { x // x.SieveCompatible } :=
  conesEquivSieveCompatibleFamily P S { unop := E }
f₁ f₂ : { pt := E, π := eqv.invFun (eqv.toFun π) } ⟶ P.mapCone S.arrows.cocone.op
eqv' : (⋯.cone ⟶ P.mapCone S.arrows.cocone.op) ≃ { t // (↑(eqv π)).IsAmalgamation t } := homEquivAmalgamation ⋯
⊢ ↑(eqv' f₁) = ↑(eqv' f₂)
state_after: no goals