l3lab/ntp-mathlib huggingface dataset:
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  

Proof state:
case intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
⊢ IsSheafFor (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)

Next tactic:
intro x hx
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  

Proof state:
case intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
⊢ ∃! t, FamilyOfElements.IsAmalgamation x t

Next tactic:
let x_ext := Presieve.FamilyOfElements.sieveExtend x
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  

Proof state:
case intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
⊢ ∃! t, FamilyOfElements.IsAmalgamation x t

Next tactic:
have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  

Proof state:
case intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
⊢ ∃! t, FamilyOfElements.IsAmalgamation x t

Next tactic:
let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
  

Proof state:
case intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
S : Sieve X :=
  Sieve.generate
    (ofArrows (fun x => Y) fun x =>
      match x with
      | PUnit.unit => f)
⊢ ∃! t, FamilyOfElements.IsAmalgamation x t

Next tactic:
obtain ⟨t, t_amalg, t_uniq⟩ :=
    (Sieve.forallYonedaIsSheaf_iff_colimit S).mpr ⟨h_colim⟩ W x_ext hx_ext
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
  obtain ⟨t, t_amalg, t_uniq⟩ :=
    (Sieve.forallYonedaIsSheaf_iff_colimit S).mpr ⟨h_colim⟩ W x_ext hx_ext
  

Proof state:
case intro.intro.intro.intro.intro
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
S : Sieve X :=
  Sieve.generate
    (ofArrows (fun x => Y) fun x =>
      match x with
      | PUnit.unit => f)
t : (yoneda.obj W).obj (op X)
t_amalg : FamilyOfElements.IsAmalgamation x_ext t
t_uniq : ∀ (y : (yoneda.obj W).obj (op X)), (fun t => FamilyOfElements.IsAmalgamation x_ext t) y → y = t
⊢ ∃! t, FamilyOfElements.IsAmalgamation x t

Next tactic:
refine ⟨t, ?_, ?_⟩
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
  obtain ⟨t, t_amalg, t_uniq⟩ :=
    (Sieve.forallYonedaIsSheaf_iff_colimit S).mpr ⟨h_colim⟩ W x_ext hx_ext
  refine ⟨t, ?_, ?_⟩
  · 

Proof state:
case intro.intro.intro.intro.intro.refine_1
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
S : Sieve X :=
  Sieve.generate
    (ofArrows (fun x => Y) fun x =>
      match x with
      | PUnit.unit => f)
t : (yoneda.obj W).obj (op X)
t_amalg : FamilyOfElements.IsAmalgamation x_ext t
t_uniq : ∀ (y : (yoneda.obj W).obj (op X)), (fun t => FamilyOfElements.IsAmalgamation x_ext t) y → y = t
⊢ (fun t => FamilyOfElements.IsAmalgamation x t) t

Next tactic:
convert Presieve.isAmalgamation_restrict (Sieve.le_generate
      (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))) _ _ t_amalg
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
  obtain ⟨t, t_amalg, t_uniq⟩ :=
    (Sieve.forallYonedaIsSheaf_iff_colimit S).mpr ⟨h_colim⟩ W x_ext hx_ext
  refine ⟨t, ?_, ?_⟩
  · convert Presieve.isAmalgamation_restrict (Sieve.le_generate
      (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))) _ _ t_amalg
    

Proof state:
case h.e.h.e'_6.h.h.h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
S : Sieve X :=
  Sieve.generate
    (ofArrows (fun x => Y) fun x =>
      match x with
      | PUnit.unit => f)
t : (yoneda.obj W).obj (op X)
t_amalg : FamilyOfElements.IsAmalgamation x_ext t
t_uniq : ∀ (y : (yoneda.obj W).obj (op X)), (fun t => FamilyOfElements.IsAmalgamation x_ext t) y → y = t
⊢ x =
    FamilyOfElements.restrict
      (_ :
        (ofArrows (fun x => Y) fun x =>
            match x with
            | PUnit.unit => f) ≤
          (Sieve.generate
              (ofArrows (fun x => Y) fun x =>
                match x with
                | PUnit.unit => f)).arrows)
      x_ext

Next tactic:
exact (Presieve.restrict_extend hx).symm
/-- Every Yoneda-presheaf is a sheaf for the regular topology. -/
theorem isSheaf_yoneda_obj [Preregular C] (W : C)  :
    Presieve.IsSheaf (regularCoverage C).toGrothendieck (yoneda.obj W) := by
  rw [isSheaf_coverage]
  intro X S ⟨_, hS⟩
  have : S.regular := ⟨_, hS⟩
  obtain ⟨Y, f, rfl, hf⟩ := Presieve.regular.single_epi (R := S)
  have h_colim := isColimitOfEffectiveEpiStruct f hf.effectiveEpi.some
  rw [← Sieve.generateSingleton_eq, ← Presieve.ofArrows_pUnit] at h_colim
  intro x hx
  let x_ext := Presieve.FamilyOfElements.sieveExtend x
  have hx_ext := Presieve.FamilyOfElements.Compatible.sieveExtend hx
  let S := Sieve.generate (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))
  obtain ⟨t, t_amalg, t_uniq⟩ :=
    (Sieve.forallYonedaIsSheaf_iff_colimit S).mpr ⟨h_colim⟩ W x_ext hx_ext
  refine ⟨t, ?_, ?_⟩
  · convert Presieve.isAmalgamation_restrict (Sieve.le_generate
      (Presieve.ofArrows (fun () ↦ Y) (fun () ↦ f))) _ _ t_amalg
    exact (Presieve.restrict_extend hx).symm
  · 

Proof state:
case intro.intro.intro.intro.intro.refine_2
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : Preregular C
W X w✝ Y : C
f : Y ⟶ X
hf : EffectiveEpi f
hS : ∃ f_1, ((ofArrows (fun x => Y) fun x => f) = ofArrows (fun x => w✝) fun x => f_1) ∧ EffectiveEpi f_1
this : regular (ofArrows (fun x => Y) fun x => f)
h_colim : IsColimit (cocone (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows)
x : FamilyOfElements (yoneda.obj W) (ofArrows (fun x => Y) fun x => f)
hx : FamilyOfElements.Compatible x
x_ext : FamilyOfElements (yoneda.obj W) (Sieve.generate (ofArrows (fun x => Y) fun x => f)).arrows :=
  FamilyOfElements.sieveExtend x
hx_ext : FamilyOfElements.Compatible (FamilyOfElements.sieveExtend x)
S : Sieve X :=
  Sieve.generate
    (ofArrows (fun x => Y) fun x =>
      match x with
      | PUnit.unit => f)
t : (yoneda.obj W).obj (op X)
t_amalg : FamilyOfElements.IsAmalgamation x_ext t
t_uniq : ∀ (y : (yoneda.obj W).obj (op X)), (fun t => FamilyOfElements.IsAmalgamation x_ext t) y → y = t
⊢ ∀ (y : (yoneda.obj W).obj (op X)), (fun t => FamilyOfElements.IsAmalgamation x t) y → y = t

Next tactic:
exact fun y hy ↦ t_uniq y <| Presieve.isAmalgamation_sieveExtend x y hy
instance {X : C} (S : Presieve X) [S.extensive] : S.hasPullbacks where
  has_pullbacks := by
    

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
X : C
S : Presieve X
inst✝ : Presieve.extensive S
⊢ ∀ {Y Z : C} {f : Y ⟶ X}, S f → ∀ {g : Z ⟶ X}, S g → HasPullback f g

Next tactic:
obtain ⟨_, _, _, _, rfl, ⟨hc⟩⟩ := Presieve.extensive.arrows_nonempty_isColimit (R := S)
instance {X : C} (S : Presieve X) [S.extensive] : S.hasPullbacks where
  has_pullbacks := by
    obtain ⟨_, _, _, _, rfl, ⟨hc⟩⟩ := Presieve.extensive.arrows_nonempty_isColimit (R := S)
    

Proof state:
case intro.intro.intro.intro.intro.intro
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
X : C
w✝³ : Type
w✝² : Fintype w✝³
w✝¹ : w✝³ → C
w✝ : (a : w✝³) → w✝¹ a ⟶ X
inst✝ : Presieve.extensive (Presieve.ofArrows w✝¹ w✝)
hc : IsColimit (Cofan.mk X w✝)
⊢ ∀ {Y Z : C} {f : Y ⟶ X}, Presieve.ofArrows w✝¹ w✝ f → ∀ {g : Z ⟶ X}, Presieve.ofArrows w✝¹ w✝ g → HasPullback f g

Next tactic:
intro _ _ _ _ _ hg
instance {X : C} (S : Presieve X) [S.extensive] : S.hasPullbacks where
  has_pullbacks := by
    obtain ⟨_, _, _, _, rfl, ⟨hc⟩⟩ := Presieve.extensive.arrows_nonempty_isColimit (R := S)
    intro _ _ _ _ _ hg
    

Proof state:
case intro.intro.intro.intro.intro.intro
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
X : C
w✝³ : Type
w✝² : Fintype w✝³
w✝¹ : w✝³ → C
w✝ : (a : w✝³) → w✝¹ a ⟶ X
inst✝ : Presieve.extensive (Presieve.ofArrows w✝¹ w✝)
hc : IsColimit (Cofan.mk X w✝)
Y✝ Z✝ : C
f✝ : Y✝ ⟶ X
x✝ : Presieve.ofArrows w✝¹ w✝ f✝
g✝ : Z✝ ⟶ X
hg : Presieve.ofArrows w✝¹ w✝ g✝
⊢ HasPullback f✝ g✝

Next tactic:
cases hg
instance {X : C} (S : Presieve X) [S.extensive] : S.hasPullbacks where
  has_pullbacks := by
    obtain ⟨_, _, _, _, rfl, ⟨hc⟩⟩ := Presieve.extensive.arrows_nonempty_isColimit (R := S)
    intro _ _ _ _ _ hg
    cases hg
    

Proof state:
case intro.intro.intro.intro.intro.intro.mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
X : C
w✝³ : Type
w✝² : Fintype w✝³
w✝¹ : w✝³ → C
w✝ : (a : w✝³) → w✝¹ a ⟶ X
inst✝ : Presieve.extensive (Presieve.ofArrows w✝¹ w✝)
hc : IsColimit (Cofan.mk X w✝)
Y✝ : C
f✝ : Y✝ ⟶ X
x✝ : Presieve.ofArrows w✝¹ w✝ f✝
i✝ : w✝³
⊢ HasPullback f✝ (w✝ i✝)

Next tactic:
apply FinitaryPreExtensive.hasPullbacks_of_is_coproduct hc
/--
A finite product preserving presheaf is a sheaf for the extensive topology on a category which is
`FinitaryPreExtensive`.
-/
theorem isSheafFor_extensive_of_preservesFiniteProducts {X : C} (S : Presieve X) [S.extensive]
    (F : Cᵒᵖ ⥤ Type max u v) [PreservesFiniteProducts F] : S.IsSheafFor F  := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : FinitaryPreExtensive C
X : C
S : Presieve X
inst✝¹ : extensive S
F : Cᵒᵖ ⥤ Type (max u v)
inst✝ : PreservesFiniteProducts F
⊢ IsSheafFor F S

Next tactic:
obtain ⟨_, _, Z, π, rfl, ⟨hc⟩⟩ := extensive.arrows_nonempty_isColimit (R := S)
/--
A finite product preserving presheaf is a sheaf for the extensive topology on a category which is
`FinitaryPreExtensive`.
-/
theorem isSheafFor_extensive_of_preservesFiniteProducts {X : C} (S : Presieve X) [S.extensive]
    (F : Cᵒᵖ ⥤ Type max u v) [PreservesFiniteProducts F] : S.IsSheafFor F  := by
  obtain ⟨_, _, Z, π, rfl, ⟨hc⟩⟩ := extensive.arrows_nonempty_isColimit (R := S)
  

Proof state:
case intro.intro.intro.intro.intro.intro
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : FinitaryPreExtensive C
X : C
F : Cᵒᵖ ⥤ Type (max u v)
inst✝¹ : PreservesFiniteProducts F
w✝¹ : Type
w✝ : Fintype w✝¹
Z : w✝¹ → C
π : (a : w✝¹) → Z a ⟶ X
inst✝ : extensive (ofArrows Z π)
hc : IsColimit (Cofan.mk X π)
⊢ IsSheafFor F (ofArrows Z π)

Next tactic:
have : (ofArrows Z (Cofan.mk X π).inj).hasPullbacks :=
    (inferInstance : (ofArrows Z π).hasPullbacks)
/--
A finite product preserving presheaf is a sheaf for the extensive topology on a category which is
`FinitaryPreExtensive`.
-/
theorem isSheafFor_extensive_of_preservesFiniteProducts {X : C} (S : Presieve X) [S.extensive]
    (F : Cᵒᵖ ⥤ Type max u v) [PreservesFiniteProducts F] : S.IsSheafFor F  := by
  obtain ⟨_, _, Z, π, rfl, ⟨hc⟩⟩ := extensive.arrows_nonempty_isColimit (R := S)
  have : (ofArrows Z (Cofan.mk X π).inj).hasPullbacks :=
    (inferInstance : (ofArrows Z π).hasPullbacks)
  

Proof state:
case intro.intro.intro.intro.intro.intro
C : Type u
inst✝³ : Category.{v, u} C
inst✝² : FinitaryPreExtensive C
X : C
F : Cᵒᵖ ⥤ Type (max u v)
inst✝¹ : PreservesFiniteProducts F
w✝¹ : Type
w✝ : Fintype w✝¹
Z : w✝¹ → C
π : (a : w✝¹) → Z a ⟶ X
inst✝ : extensive (ofArrows Z π)
hc : IsColimit (Cofan.mk X π)
this : hasPullbacks (ofArrows Z (Cofan.inj (Cofan.mk X π)))
⊢ IsSheafFor F (ofArrows Z π)

Next tactic:
exact isSheafFor_of_preservesProduct _ _ hc
/--
A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products.
-/
theorem isSheaf_iff_preservesFiniteProducts [FinitaryExtensive C] (F : Cᵒᵖ ⥤ Type max u v) :
    Presieve.IsSheaf (extensiveCoverage C).toGrothendieck F ↔
    Nonempty (PreservesFiniteProducts F) := by
  

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
inst✝ : FinitaryExtensive C
F : Cᵒᵖ ⥤ Type (max u v)
⊢ IsSheaf (Coverage.toGrothendieck C (extensiveCoverage C)) F ↔ Nonempty (PreservesFiniteProducts F)

Next tactic:
refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩
/--
A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products.
-/
theorem isSheaf_iff_preservesFiniteProducts [FinitaryExtensive C] (F : Cᵒᵖ ⥤ Type max u v) :
    Presieve.IsSheaf (extensiveCoverage C).toGrothendieck F ↔
    Nonempty (PreservesFiniteProducts F) := by
  refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩
  · 

Proof state:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
inst✝ : FinitaryExtensive C
F : Cᵒᵖ ⥤ Type (max u v)
hF : IsSheaf (Coverage.toGrothendieck C (extensiveCoverage C)) F
α : Type
x✝ : Fintype α
K : Discrete α ⥤ Cᵒᵖ
⊢ PreservesLimit K F

Next tactic:
rw [Presieve.isSheaf_coverage] at hF
/--
A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products.
-/
theorem isSheaf_iff_preservesFiniteProducts [FinitaryExtensive C] (F : Cᵒᵖ ⥤ Type max u v) :
    Presieve.IsSheaf (extensiveCoverage C).toGrothendieck F ↔
    Nonempty (PreservesFiniteProducts F) := by
  refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩
  · rw [Presieve.isSheaf_coverage] at hF
    

Proof state:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
inst✝ : FinitaryExtensive C
F : Cᵒᵖ ⥤ Type (max u v)
hF : ∀ {X : C}, ∀ R ∈ Coverage.covering (extensiveCoverage C) X, IsSheafFor F R
α : Type
x✝ : Fintype α
K : Discrete α ⥤ Cᵒᵖ
⊢ PreservesLimit K F

Next tactic:
let Z : α → C := fun i ↦ unop (K.obj ⟨i⟩)
/--
A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products.
-/
theorem isSheaf_iff_preservesFiniteProducts [FinitaryExtensive C] (F : Cᵒᵖ ⥤ Type max u v) :
    Presieve.IsSheaf (extensiveCoverage C).toGrothendieck F ↔
    Nonempty (PreservesFiniteProducts F) := by
  refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩
  · rw [Presieve.isSheaf_coverage] at hF
    let Z : α → C := fun i ↦ unop (K.obj ⟨i⟩)
    

Proof state:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
inst✝ : FinitaryExtensive C
F : Cᵒᵖ ⥤ Type (max u v)
hF : ∀ {X : C}, ∀ R ∈ Coverage.covering (extensiveCoverage C) X, IsSheafFor F R
α : Type
x✝ : Fintype α
K : Discrete α ⥤ Cᵒᵖ
Z : α → C := fun i => (K.obj { as := i }).unop
⊢ PreservesLimit K F

Next tactic:
have : (Presieve.ofArrows Z (Cofan.mk (∐ Z) (Sigma.ι Z)).inj).hasPullbacks :=
      (inferInstance : (Presieve.ofArrows Z (Sigma.ι Z)).hasPullbacks)
/--
A presheaf on a category which is `FinitaryExtensive` is a sheaf iff it preserves finite products.
-/
theorem isSheaf_iff_preservesFiniteProducts [FinitaryExtensive C] (F : Cᵒᵖ ⥤ Type max u v) :
    Presieve.IsSheaf (extensiveCoverage C).toGrothendieck F ↔
    Nonempty (PreservesFiniteProducts F) := by
  refine ⟨fun hF ↦ ⟨⟨fun α _ ↦ ⟨fun {K} ↦ ?_⟩⟩⟩, fun hF ↦ ?_⟩
  · rw [Presieve.isSheaf_coverage] at hF
    let Z : α → C := fun i ↦ unop (K.obj ⟨i⟩)
    have : (Presieve.ofArrows Z (Cofan.mk (∐ Z) (Sigma.ι Z)).inj).hasPullbacks :=
      (inferInstance : (Presieve.ofArrows Z (Sigma.ι Z)).hasPullbacks)
    

Proof state:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : FinitaryPreExtensive C
inst✝ : FinitaryExtensive C
F : Cᵒᵖ ⥤ Type (max u v)
hF : ∀ {X : C}, ∀ R ∈ Coverage.covering (extensiveCoverage C) X, IsSheafFor F R
α : Type
x✝ : Fintype α
K : Discrete α ⥤ Cᵒᵖ
Z : α → C := fun i => (K.obj { as := i }).unop
this : hasPullbacks (ofArrows Z (Cofan.inj (Cofan.mk (∐ Z) (Sigma.ι Z))))
⊢ PreservesLimit K F

Next tactic:
have : ∀ (i : α), Mono (Cofan.inj (Cofan.mk (∐ Z) (Sigma.ι Z)) i) :=
      (inferInstance : ∀ (i : α), Mono (Sigma.ι Z i))