l3lab/ntp-mathlib huggingface dataset:
theorem compatiblePreservingOfFlat {C : Type u₁} [Category.{v₁} C] {D : Type u₁} [Category.{v₁} D]
    (K : GrothendieckTopology D) (G : C ⥤ D) [RepresentablyFlat G] : CompatiblePreserving K G := by
  constructor
  intro ℱ Z T x hx Y₁ Y₂ X f₁ f₂ g₁ g₂ hg₁ hg₂ e
  -- First, `f₁` and `f₂` form a cone over `cospan g₁ g₂ ⋙ u`.
  let c : Cone (cospan g₁ g₂ ⋙ G) :=
    (Cones.postcompose (diagramIsoCospan (cospan g₁ g₂ ⋙ G)).inv).obj (PullbackCone.mk f₁ f₂ e)
  /-
    This can then be viewed as a cospan of structured arrows, and we may obtain an arbitrary cone
    over it since `StructuredArrow W u` is cofiltered.
    Then, it suffices to prove that it is compatible when restricted onto `u(c'.X.right)`.
    -/
  let c' := IsCofiltered.cone (c.toStructuredArrow ⋙ StructuredArrow.pre _ _ _)
  have eq₁ : f₁ = (c'.pt.hom ≫ G.map (c'.π.app left).right) ≫ eqToHom (by simp) := by
    erw [← (c'.π.app left).w]
    dsimp
    simp
  have eq₂ : f₂ = (c'.pt.hom ≫ G.map (c'.π.app right).right) ≫ eqToHom (by simp) := by
    erw [← (c'.π.app right).w]
    dsimp
    simp
  conv_lhs => rw [eq₁]
  

Proof state:
case compatible
C✝ : Type u₁
inst✝⁵ : Category.{v₁, u₁} C✝
D✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} D✝
F : C✝ ⥤ D✝
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
J : GrothendieckTopology C✝
K✝ : GrothendieckTopology D✝
L : GrothendieckTopology A
G✝ : C✝ ⥤ D✝
hG : CompatiblePreserving K✝ G✝
ℱ✝ : SheafOfTypes K✝
Z✝ : C✝
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G✝.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₁
inst✝¹ : Category.{v₁, u₁} D
K : GrothendieckTopology D
G : C ⥤ D
inst✝ : RepresentablyFlat G
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ G.obj Y₁
f₂ : X ⟶ G.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
e : f₁ ≫ G.map g₁ = f₂ ≫ G.map g₂
c : Cone (cospan g₁ g₂ ⋙ G) :=
  (Cones.postcompose (diagramIsoCospan (cospan g₁ g₂ ⋙ G)).inv).obj (PullbackCone.mk f₁ f₂ e)
c' : Cone (Cone.toStructuredArrow c ⋙ StructuredArrow.pre c.pt (cospan g₁ g₂) G) :=
  IsCofiltered.cone (Cone.toStructuredArrow c ⋙ StructuredArrow.pre c.pt (cospan g₁ g₂) G)
eq₁ :
  f₁ =
    (c'.pt.hom ≫ G.map (c'.π.app left).right) ≫
      eqToHom
        (_ :
          G.obj ((StructuredArrow.pre X (cospan g₁ g₂) G).obj (StructuredArrow.mk (f₁ ≫ 𝟙 (G.obj Y₁)))).right =
            G.obj Y₁)
eq₂ :
  f₂ =
    (c'.pt.hom ≫ G.map (c'.π.app right).right) ≫
      eqToHom
        (_ :
          G.obj ((StructuredArrow.pre X (cospan g₁ g₂) G).obj (StructuredArrow.mk (f₂ ≫ 𝟙 (G.obj Y₂)))).right =
            G.obj Y₂)
⊢ ℱ.val.map
      ((c'.pt.hom ≫ G.map (c'.π.app left).right) ≫
          eqToHom
            (_ :
              G.obj ((StructuredArrow.pre X (cospan g₁ g₂) G).obj (StructuredArrow.mk (f₁ ≫ 𝟙 (G.obj Y₁)))).right =
                G.obj Y₁)).op
      (x g₁ hg₁) =
    ℱ.val.map f₂.op (x g₂ hg₂)

Next tactic:
conv_rhs => rw [eq₂]
theorem compatiblePreservingOfFlat {C : Type u₁} [Category.{v₁} C] {D : Type u₁} [Category.{v₁} D]
    (K : GrothendieckTopology D) (G : C ⥤ D) [RepresentablyFlat G] : CompatiblePreserving K G := by
  constructor
  intro ℱ Z T x hx Y₁ Y₂ X f₁ f₂ g₁ g₂ hg₁ hg₂ e
  -- First, `f₁` and `f₂` form a cone over `cospan g₁ g₂ ⋙ u`.
  let c : Cone (cospan g₁ g₂ ⋙ G) :=
    (Cones.postcompose (diagramIsoCospan (cospan g₁ g₂ ⋙ G)).inv).obj (PullbackCone.mk f₁ f₂ e)
  /-
    This can then be viewed as a cospan of structured arrows, and we may obtain an arbitrary cone
    over it since `StructuredArrow W u` is cofiltered.
    Then, it suffices to prove that it is compatible when restricted onto `u(c'.X.right)`.
    -/
  let c' := IsCofiltered.cone (c.toStructuredArrow ⋙ StructuredArrow.pre _ _ _)
  have eq₁ : f₁ = (c'.pt.hom ≫ G.map (c'.π.app left).right) ≫ eqToHom (by simp) := by
    erw [← (c'.π.app left).w]
    dsimp
    simp
  have eq₂ : f₂ = (c'.pt.hom ≫ G.map (c'.π.app right).right) ≫ eqToHom (by simp) := by
    erw [← (c'.π.app right).w]
    dsimp
    simp
  conv_lhs => rw [eq₁]
  conv_rhs => 

Proof state:
C✝ : Type u₁
inst✝⁵ : Category.{v₁, u₁} C✝
D✝ : Type u₂
inst✝⁴ : Category.{v₂, u₂} D✝
F : C✝ ⥤ D✝
A : Type u₃
inst✝³ : Category.{v₃, u₃} A
J : GrothendieckTopology C✝
K✝ : GrothendieckTopology D✝
L : GrothendieckTopology A
G✝ : C✝ ⥤ D✝
hG : CompatiblePreserving K✝ G✝
ℱ✝ : SheafOfTypes K✝
Z✝ : C✝
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G✝.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₁
inst✝¹ : Category.{v₁, u₁} D
K : GrothendieckTopology D
G : C ⥤ D
inst✝ : RepresentablyFlat G
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ G.obj Y₁
f₂ : X ⟶ G.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
e : f₁ ≫ G.map g₁ = f₂ ≫ G.map g₂
c : Cone (cospan g₁ g₂ ⋙ G) :=
  (Cones.postcompose (diagramIsoCospan (cospan g₁ g₂ ⋙ G)).inv).obj (PullbackCone.mk f₁ f₂ e)
c' : Cone (Cone.toStructuredArrow c ⋙ StructuredArrow.pre c.pt (cospan g₁ g₂) G) :=
  IsCofiltered.cone (Cone.toStructuredArrow c ⋙ StructuredArrow.pre c.pt (cospan g₁ g₂) G)
eq₁ :
  f₁ =
    (c'.pt.hom ≫ G.map (c'.π.app left).right) ≫
      eqToHom
        (_ :
          G.obj ((StructuredArrow.pre X (cospan g₁ g₂) G).obj (StructuredArrow.mk (f₁ ≫ 𝟙 (G.obj Y₁)))).right =
            G.obj Y₁)
eq₂ :
  f₂ =
    (c'.pt.hom ≫ G.map (c'.π.app right).right) ≫
      eqToHom
        (_ :
          G.obj ((StructuredArrow.pre X (cospan g₁ g₂) G).obj (StructuredArrow.mk (f₂ ≫ 𝟙 (G.obj Y₂)))).right =
            G.obj Y₂)
| ℱ.val.map f₂.op (x g₂ hg₂)

Next tactic:
rw [eq₂]
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
h : Compatible x
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
⊢ CompatiblePreserving K F

Next tactic:
constructor
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  

Proof state:
case compatible
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
h : Compatible x
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
⊢ ∀ (ℱ : SheafOfTypes K) {Z : C} {T : Presieve Z} {x : FamilyOfElements (F.op ⋙ ℱ.val) T},
    Compatible x →
      ∀ {Y₁ Y₂ : C} {X : D} (f₁ : X ⟶ F.obj Y₁) (f₂ : X ⟶ F.obj Y₂) {g₁ : Y₁ ⟶ Z} {g₂ : Y₂ ⟶ Z} (hg₁ : T g₁)
        (hg₂ : T g₂), f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂ → ℱ.val.map f₁.op (x g₁ hg₁) = ℱ.val.map f₂.op (x g₂ hg₂)

Next tactic:
introv hx he
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  introv hx he
  

Proof state:
case compatible
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ✝ : SheafOfTypes K
Z✝ : C
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (F.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ F.obj Y₁
f₂ : X ⟶ F.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
he : f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂
⊢ ℱ.val.map f₁.op (x g₁ hg₁) = ℱ.val.map f₂.op (x g₂ hg₂)

Next tactic:
obtain ⟨X', e⟩ := hF f₁
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  introv hx he
  obtain ⟨X', e⟩ := hF f₁
  

Proof state:
case compatible.mk
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ✝ : SheafOfTypes K
Z✝ : C
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (F.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ F.obj Y₁
f₂ : X ⟶ F.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
he : f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂
X' : C
e : F.obj X' ≅ X
⊢ ℱ.val.map f₁.op (x g₁ hg₁) = ℱ.val.map f₂.op (x g₂ hg₂)

Next tactic:
apply (ℱ.1.mapIso e.op).toEquiv.injective
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  introv hx he
  obtain ⟨X', e⟩ := hF f₁
  apply (ℱ.1.mapIso e.op).toEquiv.injective
  

Proof state:
case compatible.mk.a
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ✝ : SheafOfTypes K
Z✝ : C
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (F.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ F.obj Y₁
f₂ : X ⟶ F.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
he : f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂
X' : C
e : F.obj X' ≅ X
⊢ (ℱ.val.mapIso (Iso.op e)).toEquiv (ℱ.val.map f₁.op (x g₁ hg₁)) =
    (ℱ.val.mapIso (Iso.op e)).toEquiv (ℱ.val.map f₂.op (x g₂ hg₂))

Next tactic:
simp only [Iso.op_hom, Iso.toEquiv_fun, ℱ.1.mapIso_hom, ← FunctorToTypes.map_comp_apply]
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  introv hx he
  obtain ⟨X', e⟩ := hF f₁
  apply (ℱ.1.mapIso e.op).toEquiv.injective
  simp only [Iso.op_hom, Iso.toEquiv_fun, ℱ.1.mapIso_hom, ← FunctorToTypes.map_comp_apply]
  

Proof state:
case compatible.mk.a
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ✝ : SheafOfTypes K
Z✝ : C
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (F.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ F.obj Y₁
f₂ : X ⟶ F.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
he : f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂
X' : C
e : F.obj X' ≅ X
⊢ ℱ.val.map (f₁.op ≫ e.hom.op) (x g₁ hg₁) = ℱ.val.map (f₂.op ≫ e.hom.op) (x g₂ hg₂)

Next tactic:
simpa using
    hx (F.preimage <| e.hom ≫ f₁) (F.preimage <| e.hom ≫ f₂) hg₁ hg₂
      (F.map_injective <| by simpa using he)
theorem compatiblePreservingOfDownwardsClosed (F : C ⥤ D) [Full F] [Faithful F]
    (hF : ∀ {c : C} {d : D} (_ : d ⟶ F.obj c), Σc', F.obj c' ≅ d) : CompatiblePreserving K F := by
  constructor
  introv hx he
  obtain ⟨X', e⟩ := hF f₁
  apply (ℱ.1.mapIso e.op).toEquiv.injective
  simp only [Iso.op_hom, Iso.toEquiv_fun, ℱ.1.mapIso_hom, ← FunctorToTypes.map_comp_apply]
  simpa using
    hx (F.preimage <| e.hom ≫ f₁) (F.preimage <| e.hom ≫ f₂) hg₁ hg₂
      (F.map_injective <| by 

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F✝ : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K G
ℱ✝ : SheafOfTypes K
Z✝ : C
T✝ : Presieve Z✝
x✝ : FamilyOfElements (G.op ⋙ ℱ✝.val) T✝
h : Compatible x✝
F : C ⥤ D
inst✝¹ : Full F
inst✝ : Faithful F
hF : {c : C} → {d : D} → (d ⟶ F.obj c) → (c' : C) × (F.obj c' ≅ d)
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x : FamilyOfElements (F.op ⋙ ℱ.val) T
hx : Compatible x
Y₁ Y₂ : C
X : D
f₁ : X ⟶ F.obj Y₁
f₂ : X ⟶ F.obj Y₂
g₁ : Y₁ ⟶ Z
g₂ : Y₂ ⟶ Z
hg₁ : T g₁
hg₂ : T g₂
he : f₁ ≫ F.map g₁ = f₂ ≫ F.map g₂
X' : C
e : F.obj X' ≅ X
⊢ F.map (F.preimage (e.hom ≫ f₁) ≫ g₁) = F.map (F.preimage (e.hom ≫ f₂) ≫ g₂)

Next tactic:
simpa using he
lemma Functor.isContinuous_comp' {F₁ : C ⥤ D} {F₂ : D ⥤ A} {F₁₂ : C ⥤ A}
    (e : F₁ ⋙ F₂ ≅ F₁₂) (J : GrothendieckTopology C)
    (K : GrothendieckTopology D) (L : GrothendieckTopology A)
    [Functor.IsContinuous.{w} F₁ J K] [Functor.IsContinuous.{w} F₂ K L] :
    Functor.IsContinuous.{w} F₁₂ J L := by
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J✝ : GrothendieckTopology C
K✝ : GrothendieckTopology D
L✝ : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K✝ G
ℱ : SheafOfTypes K✝
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
h : Compatible x
F₁ : C ⥤ D
F₂ : D ⥤ A
F₁₂ : C ⥤ A
e : F₁ ⋙ F₂ ≅ F₁₂
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
inst✝¹ : IsContinuous F₁ J K
inst✝ : IsContinuous F₂ K L
⊢ IsContinuous F₁₂ J L

Next tactic:
have := Functor.isContinuous_comp F₁ F₂ J K L
lemma Functor.isContinuous_comp' {F₁ : C ⥤ D} {F₂ : D ⥤ A} {F₁₂ : C ⥤ A}
    (e : F₁ ⋙ F₂ ≅ F₁₂) (J : GrothendieckTopology C)
    (K : GrothendieckTopology D) (L : GrothendieckTopology A)
    [Functor.IsContinuous.{w} F₁ J K] [Functor.IsContinuous.{w} F₂ K L] :
    Functor.IsContinuous.{w} F₁₂ J L := by
  have := Functor.isContinuous_comp F₁ F₂ J K L
  

Proof state:
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
D : Type u₂
inst✝³ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝² : Category.{v₃, u₃} A
J✝ : GrothendieckTopology C
K✝ : GrothendieckTopology D
L✝ : GrothendieckTopology A
G : C ⥤ D
hG : CompatiblePreserving K✝ G
ℱ : SheafOfTypes K✝
Z : C
T : Presieve Z
x : FamilyOfElements (G.op ⋙ ℱ.val) T
h : Compatible x
F₁ : C ⥤ D
F₂ : D ⥤ A
F₁₂ : C ⥤ A
e : F₁ ⋙ F₂ ≅ F₁₂
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
inst✝¹ : IsContinuous F₁ J K
inst✝ : IsContinuous F₂ K L
this : IsContinuous (F₁ ⋙ F₂) J L
⊢ IsContinuous F₁₂ J L

Next tactic:
apply Functor.isContinuous_of_iso e
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
⊢ ∃! t, IsAmalgamation x t

Next tactic:
apply exists_unique_of_exists_of_unique
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    apply exists_unique_of_exists_of_unique
    · 

Proof state:
case hex
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
⊢ ∃ x_1, IsAmalgamation x x_1

Next tactic:
have H := G.2 _ (hF₂.cover_preserve hS)
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    apply exists_unique_of_exists_of_unique
    · have H := G.2 _ (hF₂.cover_preserve hS)
      

Proof state:
case hex
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
H : IsSheafFor G.val (Sieve.functorPushforward F S).arrows
⊢ ∃ x_1, IsAmalgamation x x_1

Next tactic:
exact ⟨H.amalgamate (x.functorPushforward F) (hx.functorPushforward hF₁),
        fun V f hf => (H.isAmalgamation (hx.functorPushforward hF₁) (F.map f) _).trans
          (hF₁.apply_map _ hx hf)⟩
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    apply exists_unique_of_exists_of_unique
    · have H := G.2 _ (hF₂.cover_preserve hS)
      exact ⟨H.amalgamate (x.functorPushforward F) (hx.functorPushforward hF₁),
        fun V f hf => (H.isAmalgamation (hx.functorPushforward hF₁) (F.map f) _).trans
          (hF₁.apply_map _ hx hf)⟩
    · 

Proof state:
case hunique
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
⊢ ∀ (y₁ y₂ : (F.op ⋙ G.val).obj (op X)), IsAmalgamation x y₁ → IsAmalgamation x y₂ → y₁ = y₂

Next tactic:
intro y₁ y₂ hy₁ hy₂
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    apply exists_unique_of_exists_of_unique
    · have H := G.2 _ (hF₂.cover_preserve hS)
      exact ⟨H.amalgamate (x.functorPushforward F) (hx.functorPushforward hF₁),
        fun V f hf => (H.isAmalgamation (hx.functorPushforward hF₁) (F.map f) _).trans
          (hF₁.apply_map _ hx hf)⟩
    · intro y₁ y₂ hy₁ hy₂
      

Proof state:
case hunique
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
y₁ y₂ : (F.op ⋙ G.val).obj (op X)
hy₁ : IsAmalgamation x y₁
hy₂ : IsAmalgamation x y₂
⊢ y₁ = y₂

Next tactic:
apply (Presieve.isSeparated_of_isSheaf _ _ G.cond _ (hF₂.cover_preserve hS)).ext
/-- If `F` is cover-preserving and compatible-preserving,
then `F` is a continuous functor.

This result is basically <https://stacks.math.columbia.edu/tag/00WW>.
-/
lemma Functor.isContinuous_of_coverPreserving (hF₁ : CompatiblePreserving.{w} K F)
    (hF₂ : CoverPreserving J K F) : Functor.IsContinuous.{w} F J K where
  op_comp_isSheafOfTypes G X S hS x hx := by
    apply exists_unique_of_exists_of_unique
    · have H := G.2 _ (hF₂.cover_preserve hS)
      exact ⟨H.amalgamate (x.functorPushforward F) (hx.functorPushforward hF₁),
        fun V f hf => (H.isAmalgamation (hx.functorPushforward hF₁) (F.map f) _).trans
          (hF₁.apply_map _ hx hf)⟩
    · intro y₁ y₂ hy₁ hy₂
      apply (Presieve.isSeparated_of_isSheaf _ _ G.cond _ (hF₂.cover_preserve hS)).ext
      

Proof state:
case hunique
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
F : C ⥤ D
A : Type u₃
inst✝ : Category.{v₃, u₃} A
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology A
G✝ : C ⥤ D
hG : CompatiblePreserving K G✝
ℱ : SheafOfTypes K
Z : C
T : Presieve Z
x✝ : FamilyOfElements (G✝.op ⋙ ℱ.val) T
h : Compatible x✝
hF₁ : CompatiblePreserving K F
hF₂ : CoverPreserving J K F
G : SheafOfTypes K
X : C
S : Sieve X
hS : S ∈ GrothendieckTopology.sieves J X
x : FamilyOfElements (F.op ⋙ G.val) S.arrows
hx : Compatible x
y₁ y₂ : (F.op ⋙ G.val).obj (op X)
hy₁ : IsAmalgamation x y₁
hy₂ : IsAmalgamation x y₂
⊢ ∀ ⦃Y : D⦄ ⦃f : Y ⟶ F.obj X⦄, (Sieve.functorPushforward F S).arrows f → G.val.map f.op y₁ = G.val.map f.op y₂

Next tactic:
rintro Y _ ⟨Z, g, h, hg, rfl⟩