l3lab/ntp-mathlib huggingface dataset:
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    

Proof state:
A B : TopCat
⊢ CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ≫ prodToProdTop A B = 𝟙 (π.obj (TopCat.of (↑A × ↑B)))

Next tactic:
change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    

Proof state:
A B : TopCat
⊢ CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B = 𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))

Next tactic:
apply CategoryTheory.Functor.hext
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · 

Proof state:
case h_obj
A B : TopCat
⊢ ∀ (X : ↑(π.obj (TopCat.of (↑A × ↑B)))),
    (CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).obj X =
      (𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).obj X

Next tactic:
intros
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; 

Proof state:
case h_obj
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ (CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).obj X✝ =
    (𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).obj X✝

Next tactic:
apply FundamentalGroupoid.ext
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; 

Proof state:
case h_obj.as
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).obj X✝).as =
    ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).obj X✝).as

Next tactic:
apply Prod.ext
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> 

Proof state:
case h_obj.as.a
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).obj X✝).as.1 =
    ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).obj X✝).as.1

Next tactic:
simp
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> 

Proof state:
case h_obj.as.a
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).obj X✝).as.2 =
    ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).obj X✝).as.2

Next tactic:
simp
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> 

Proof state:
case h_obj.as.a
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ ((projLeft A B).obj X✝).as = X✝.as.1

Next tactic:
rfl
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> 

Proof state:
case h_obj.as.a
A B : TopCat
X✝ : ↑(π.obj (TopCat.of (↑A × ↑B)))
⊢ ((projRight A B).obj X✝).as = X✝.as.2

Next tactic:
rfl
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> rfl
    

Proof state:
case h_map
A B : TopCat
⊢ ∀ (X Y : ↑(π.obj (TopCat.of (↑A × ↑B)))) (f : X ⟶ Y),
    HEq ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).map f)
      ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).map f)

Next tactic:
rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ f
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ f
    

Proof state:
case h_map.mk.mk.mk.mk
A B : TopCat
x₀ : ↑A
x₁ : ↑B
y₀ : ↑A
y₁ : ↑B
f : { as := (x₀, x₁) } ⟶ { as := (y₀, y₁) }
⊢ HEq ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).map f)
    ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).map f)

Next tactic:
have := Path.Homotopic.prod_projLeft_projRight f
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ f
    have := Path.Homotopic.prod_projLeft_projRight f
    -- Porting note: was simpa but TopSpace instances might be getting in the way
    

Proof state:
case h_map.mk.mk.mk.mk
A B : TopCat
x₀ : ↑A
x₁ : ↑B
y₀ : ↑A
y₁ : ↑B
f : { as := (x₀, x₁) } ⟶ { as := (y₀, y₁) }
this : Path.Homotopic.prod (Path.Homotopic.projLeft f) (Path.Homotopic.projRight f) = f
⊢ HEq ((CategoryTheory.Functor.prod' (projLeft A B) (projRight A B) ⋙ prodToProdTop A B).map f)
    ((𝟭 ↑(π.obj (TopCat.of (↑A × ↑B)))).map f)

Next tactic:
simp only [CategoryTheory.Functor.comp_obj, CategoryTheory.Functor.prod'_obj, prodToProdTop_obj,
      CategoryTheory.Functor.comp_map, CategoryTheory.Functor.prod'_map, projLeft_map,
      projRight_map, CategoryTheory.Functor.id_obj, CategoryTheory.Functor.id_map, heq_eq_eq]
/-- Shows `prodToProdTop` is an isomorphism, whose inverse is precisely the product
of the induced left and right projections.
-/
@[simps]
def prodIso : CategoryTheory.Grpd.of (πₓ A × πₓ B) ≅ πₓ (TopCat.of (A × B)) where
  hom := prodToProdTop A B
  inv := (projLeft A B).prod' (projRight A B)
  hom_inv_id := by
    change prodToProdTop A B ⋙ (projLeft A B).prod' (projRight A B) = 𝟭 _
    apply CategoryTheory.Functor.hext; · intros; ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ ⟨f₀, f₁⟩
    have : Path.Homotopic.projLeft ((prodToProdTop A B).map (f₀, f₁)) = f₀ ∧
      Path.Homotopic.projRight ((prodToProdTop A B).map (f₀, f₁)) = f₁ :=
        And.intro (Path.Homotopic.projLeft_prod f₀ f₁) (Path.Homotopic.projRight_prod f₀ f₁)
    simpa
  inv_hom_id := by
    change (projLeft A B).prod' (projRight A B) ⋙ prodToProdTop A B = 𝟭 _
    apply CategoryTheory.Functor.hext
    · intros; apply FundamentalGroupoid.ext; apply Prod.ext <;> simp <;> rfl
    rintro ⟨x₀, x₁⟩ ⟨y₀, y₁⟩ f
    have := Path.Homotopic.prod_projLeft_projRight f
    -- Porting note: was simpa but TopSpace instances might be getting in the way
    simp only [CategoryTheory.Functor.comp_obj, CategoryTheory.Functor.prod'_obj, prodToProdTop_obj,
      CategoryTheory.Functor.comp_map, CategoryTheory.Functor.prod'_map, projLeft_map,
      projRight_map, CategoryTheory.Functor.id_obj, CategoryTheory.Functor.id_map, heq_eq_eq]
    

Proof state:
case h_map.mk.mk.mk.mk
A B : TopCat
x₀ : ↑A
x₁ : ↑B
y₀ : ↑A
y₁ : ↑B
f : { as := (x₀, x₁) } ⟶ { as := (y₀, y₁) }
this : Path.Homotopic.prod (Path.Homotopic.projLeft f) (Path.Homotopic.projRight f) = f
⊢ (prodToProdTop A B).map (Path.Homotopic.projLeft f, Path.Homotopic.projRight f) = f

Next tactic:
apply this
theorem isSheaf_coherent_iff_regular_and_extensive : IsSheaf (coherentTopology C) F ↔
    IsSheaf (extensiveCoverage C).toGrothendieck F ∧
    IsSheaf (regularCoverage C).toGrothendieck F := by
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
F : Cᵒᵖ ⥤ Type (max u v)
inst✝² : Preregular C
inst✝¹ : FinitaryPreExtensive C
inst✝ : Precoherent C
⊢ IsSheaf (coherentTopology C) F ↔
    IsSheaf (Coverage.toGrothendieck C (extensiveCoverage C)) F ∧
      IsSheaf (Coverage.toGrothendieck C (regularCoverage C)) F

Next tactic:
rw [← extensive_regular_generate_coherent]
theorem isSheaf_coherent_iff_regular_and_extensive : IsSheaf (coherentTopology C) F ↔
    IsSheaf (extensiveCoverage C).toGrothendieck F ∧
    IsSheaf (regularCoverage C).toGrothendieck F := by
  rw [← extensive_regular_generate_coherent]
  

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
F : Cᵒᵖ ⥤ Type (max u v)
inst✝² : Preregular C
inst✝¹ : FinitaryPreExtensive C
inst✝ : Precoherent C
⊢ IsSheaf (Coverage.toGrothendieck C (extensiveCoverage C ⊔ regularCoverage C)) F ↔
    IsSheaf (Coverage.toGrothendieck C (extensiveCoverage C)) F ∧
      IsSheaf (Coverage.toGrothendieck C (regularCoverage C)) F

Next tactic:
exact isSheaf_sup (extensiveCoverage C) (regularCoverage C) F
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : CompHaus.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  

Proof state:
F : CompHausᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (coherentTopology CompHaus) F ↔ Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F

Next tactic:
rw [isSheaf_coherent_iff_regular_and_extensive]
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : CompHaus.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  

Proof state:
F : CompHausᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck CompHaus (extensiveCoverage CompHaus)) F ∧
      IsSheaf (Coverage.toGrothendieck CompHaus (regularCoverage CompHaus)) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F

Next tactic:
apply and_congr
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : CompHaus.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  apply and_congr
  · 

Proof state:
case h₁
F : CompHausᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck CompHaus (extensiveCoverage CompHaus)) F ↔ Nonempty (PreservesFiniteProducts F)

Next tactic:
exact isSheaf_iff_preservesFiniteProducts F
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : CompHaus.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  apply and_congr
  · exact isSheaf_iff_preservesFiniteProducts F
  · 

Proof state:
case h₂
F : CompHausᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck CompHaus (regularCoverage CompHaus)) F ↔ EqualizerCondition F

Next tactic:
exact EqualizerCondition.isSheaf_iff F
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition'
    {A : Type (u+2)} [Category.{u+1} A] (G : A ⥤ Type (u+1))
    [HasLimits A] [PreservesLimits G] [ReflectsIsomorphisms G] (F : CompHaus.{u}ᵒᵖ ⥤ A) :
    Presheaf.IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts (F ⋙ G)) ∧ EqualizerCondition (F ⋙ G) := by
  

Proof state:
A : Type (u + 2)
inst✝³ : Category.{u + 1, u + 2} A
G : A ⥤ Type (u + 1)
inst✝² : HasLimits A
inst✝¹ : PreservesLimits G
inst✝ : ReflectsIsomorphisms G
F : CompHausᵒᵖ ⥤ A
⊢ Presheaf.IsSheaf (coherentTopology CompHaus) F ↔
    Nonempty (PreservesFiniteProducts (F ⋙ G)) ∧ EqualizerCondition (F ⋙ G)

Next tactic:
rw [Presheaf.isSheaf_iff_isSheaf_forget (coherentTopology CompHaus) F G,
    isSheaf_iff_isSheaf_of_type, isSheaf_iff_preservesFiniteProducts_and_equalizerCondition]
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : Profinite.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  

Proof state:
F : Profiniteᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (coherentTopology Profinite) F ↔ Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F

Next tactic:
rw [isSheaf_coherent_iff_regular_and_extensive]
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : Profinite.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  

Proof state:
F : Profiniteᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck Profinite (extensiveCoverage Profinite)) F ∧
      IsSheaf (Coverage.toGrothendieck Profinite (regularCoverage Profinite)) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F

Next tactic:
apply and_congr
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : Profinite.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  apply and_congr
  · 

Proof state:
case h₁
F : Profiniteᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck Profinite (extensiveCoverage Profinite)) F ↔ Nonempty (PreservesFiniteProducts F)

Next tactic:
exact isSheaf_iff_preservesFiniteProducts F
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition
    (F : Profinite.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts F) ∧ EqualizerCondition F := by
  rw [isSheaf_coherent_iff_regular_and_extensive]
  apply and_congr
  · exact isSheaf_iff_preservesFiniteProducts F
  · 

Proof state:
case h₂
F : Profiniteᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck Profinite (regularCoverage Profinite)) F ↔ EqualizerCondition F

Next tactic:
exact EqualizerCondition.isSheaf_iff F
theorem isSheaf_iff_preservesFiniteProducts_and_equalizerCondition'
    {A : Type (u+2)} [Category.{u+1} A] (G : A ⥤ Type (u+1))
    [HasLimits A] [PreservesLimits G] [ReflectsIsomorphisms G] (F : Profinite.{u}ᵒᵖ ⥤ A) :
    Presheaf.IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts (F ⋙ G)) ∧ EqualizerCondition (F ⋙ G) := by
  

Proof state:
A : Type (u + 2)
inst✝³ : Category.{u + 1, u + 2} A
G : A ⥤ Type (u + 1)
inst✝² : HasLimits A
inst✝¹ : PreservesLimits G
inst✝ : ReflectsIsomorphisms G
F : Profiniteᵒᵖ ⥤ A
⊢ Presheaf.IsSheaf (coherentTopology Profinite) F ↔
    Nonempty (PreservesFiniteProducts (F ⋙ G)) ∧ EqualizerCondition (F ⋙ G)

Next tactic:
rw [Presheaf.isSheaf_iff_isSheaf_forget (coherentTopology Profinite) F G,
    isSheaf_iff_isSheaf_of_type, isSheaf_iff_preservesFiniteProducts_and_equalizerCondition]
theorem isSheaf_iff_preservesFiniteProducts
    (F : Stonean.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Stonean) F ↔ Nonempty (PreservesFiniteProducts F) := by
  

Proof state:
F : Stoneanᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (coherentTopology Stonean) F ↔ Nonempty (PreservesFiniteProducts F)

Next tactic:
rw [isSheaf_coherent_iff_regular_and_extensive, and_iff_left ?_]
theorem isSheaf_iff_preservesFiniteProducts
    (F : Stonean.{u}ᵒᵖ ⥤ Type (u+1)) :
    IsSheaf (coherentTopology Stonean) F ↔ Nonempty (PreservesFiniteProducts F) := by
  rw [isSheaf_coherent_iff_regular_and_extensive, and_iff_left ?_]
  · 

Proof state:
F : Stoneanᵒᵖ ⥤ Type (u + 1)
⊢ IsSheaf (Coverage.toGrothendieck Stonean (extensiveCoverage Stonean)) F ↔ Nonempty (PreservesFiniteProducts F)

Next tactic:
exact CategoryTheory.isSheaf_iff_preservesFiniteProducts F