l3lab/ntp-mathlib huggingface dataset:
/-- If `G` is cocontinuous, then `Ran G.op` pushes sheaves to sheaves.

This result is basically https://stacks.math.columbia.edu/tag/00XK,
but without the condition that `C` or `D` has pullbacks.
-/
theorem ran_isSheaf_of_isCocontinuous (ℱ : Sheaf J A) :
    Presheaf.IsSheaf K ((ran G.op).obj ℱ.val) := by
  intro X U S hS x hx
  constructor; swap
  · apply RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx
  

Proof state:
case h
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
⊢ (fun t => IsAmalgamation x t) (RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx) ∧
    ∀ (y : ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op U)),
      (fun t => IsAmalgamation x t) y → y = RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx

Next tactic:
constructor
/-- If `G` is cocontinuous, then `Ran G.op` pushes sheaves to sheaves.

This result is basically https://stacks.math.columbia.edu/tag/00XK,
but without the condition that `C` or `D` has pullbacks.
-/
theorem ran_isSheaf_of_isCocontinuous (ℱ : Sheaf J A) :
    Presheaf.IsSheaf K ((ran G.op).obj ℱ.val) := by
  intro X U S hS x hx
  constructor; swap
  · apply RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx
  constructor
  · 

Proof state:
case h.left
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
⊢ (fun t => IsAmalgamation x t) (RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx)

Next tactic:
apply RanIsSheafOfIsCocontinuous.gluedSection_isAmalgamation
/-- If `G` is cocontinuous, then `Ran G.op` pushes sheaves to sheaves.

This result is basically https://stacks.math.columbia.edu/tag/00XK,
but without the condition that `C` or `D` has pullbacks.
-/
theorem ran_isSheaf_of_isCocontinuous (ℱ : Sheaf J A) :
    Presheaf.IsSheaf K ((ran G.op).obj ℱ.val) := by
  intro X U S hS x hx
  constructor; swap
  · apply RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx
  constructor
  · apply RanIsSheafOfIsCocontinuous.gluedSection_isAmalgamation
  · 

Proof state:
case h.right
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
⊢ ∀ (y : ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op U)),
    (fun t => IsAmalgamation x t) y → y = RanIsSheafOfIsCocontinuous.gluedSection ℱ hS hx

Next tactic:
apply RanIsSheafOfIsCocontinuous.gluedSection_is_unique
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y
⊢ (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
      ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f) =
    f

Next tactic:
ext1
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        

Proof state:
case h
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y
⊢ ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f)).val =
    f.val

Next tactic:
dsimp
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        

Proof state:
case h
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y
⊢ (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm
      ((Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val) =
    f.val

Next tactic:
rw [Equiv.symm_apply_apply]
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y
⊢ (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
      ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val }) f) =
    f

Next tactic:
ext1
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        

Proof state:
case h
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y
⊢ ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val }) f)).val =
    f.val

Next tactic:
dsimp
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        dsimp
        

Proof state:
case h
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X : Sheaf K A
Y : Sheaf J A
f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y
⊢ (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val)
      ((Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val) =
    f.val

Next tactic:
rw [Equiv.apply_symm_apply]
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.apply_symm_apply] }
  unit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).unit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).unit.naturality f.val }
  counit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).counit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).counit.naturality f.val }
  homEquiv_unit := by
    -- porting note: next line was `ext1`
    

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
⊢ ∀ {X : Sheaf K A} {Y : Sheaf J A} {f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y},
    ((fun X Y =>
            { toFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val },
              invFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val },
              left_inv :=
                (_ :
                  ∀ (f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y),
                    (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f) =
                      f),
              right_inv :=
                (_ :
                  ∀ (f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y),
                    (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
                        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val }) f) =
                      f) })
          X Y)
        f =
      (NatTrans.mk fun X => { val := (Ran.adjunction A G.op).unit.app X.val }).app X ≫
        (sheafPushforwardCocontinuous G A J K).map f

Next tactic:
refine Sheaf.Hom.ext _ _ ?_
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.apply_symm_apply] }
  unit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).unit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).unit.naturality f.val }
  counit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).counit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).counit.naturality f.val }
  homEquiv_unit := by
    -- porting note: next line was `ext1`
    refine Sheaf.Hom.ext _ _ ?_
    

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X✝ : Sheaf K A
Y✝ : Sheaf J A
f✝ : (sheafPushforwardContinuous G A J K).obj X✝ ⟶ Y✝
⊢ (((fun X Y =>
            { toFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val },
              invFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val },
              left_inv :=
                (_ :
                  ∀ (f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y),
                    (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f) =
                      f),
              right_inv :=
                (_ :
                  ∀ (f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y),
                    (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
                        ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val }) f) =
                      f) })
          X✝ Y✝)
        f✝).val =
    ((NatTrans.mk fun X => { val := (Ran.adjunction A G.op).unit.app X.val }).app X✝ ≫
        (sheafPushforwardCocontinuous G A J K).map f✝).val

Next tactic:
apply (Ran.adjunction A G.op).homEquiv_unit
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.apply_symm_apply] }
  unit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).unit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).unit.naturality f.val }
  counit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).counit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).counit.naturality f.val }
  homEquiv_unit := by
    -- porting note: next line was `ext1`
    refine Sheaf.Hom.ext _ _ ?_
    apply (Ran.adjunction A G.op).homEquiv_unit
  homEquiv_counit := by
    -- porting note: next line was `ext1`
    

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
⊢ ∀ {X : Sheaf K A} {Y : Sheaf J A} {g : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y},
    ((fun X Y =>
              { toFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val },
                invFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val },
                left_inv :=
                  (_ :
                    ∀ (f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y),
                      (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                          ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f) =
                        f),
                right_inv :=
                  (_ :
                    ∀ (f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y),
                      (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
                          ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                            f) =
                        f) })
            X Y).symm
        g =
      (sheafPushforwardContinuous G A J K).map g ≫
        (NatTrans.mk fun X => { val := (Ran.adjunction A G.op).counit.app X.val }).app Y

Next tactic:
refine Sheaf.Hom.ext _ _ ?_
/--
Given a functor between sites that is continuous and cocontinuous,
the pushforward for the continuous functor `G` is left adjoint to
the pushforward for the cocontinuous functor `G`. -/
@[simps unit_app_val counit_app_val]
noncomputable def Functor.sheafAdjunctionCocontinuous [G.IsCocontinuous J K]
    [G.IsContinuous J K] :
    G.sheafPushforwardContinuous A J K ⊣ G.sheafPushforwardCocontinuous A J K where
  homEquiv X Y :=
    { toFun := fun f => ⟨(Ran.adjunction A G.op).homEquiv X.val Y.val f.val⟩
      invFun := fun f => ⟨((Ran.adjunction A G.op).homEquiv X.val Y.val).symm f.val⟩
      left_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.symm_apply_apply]
      right_inv := fun f => by
        ext1
        dsimp
        rw [Equiv.apply_symm_apply] }
  unit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).unit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).unit.naturality f.val }
  counit :=
    { app := fun X => ⟨(Ran.adjunction A G.op).counit.app X.val⟩
      naturality := fun _ _ f =>
        Sheaf.Hom.ext _ _ <| (Ran.adjunction A G.op).counit.naturality f.val }
  homEquiv_unit := by
    -- porting note: next line was `ext1`
    refine Sheaf.Hom.ext _ _ ?_
    apply (Ran.adjunction A G.op).homEquiv_unit
  homEquiv_counit := by
    -- porting note: next line was `ext1`
    refine Sheaf.Hom.ext _ _ ?_
    

Proof state:
C D : Type u
inst✝⁶ : Category.{v, u} C
inst✝⁵ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝⁴ : Category.{max u v, w} A
inst✝³ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝² inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
X✝ : Sheaf K A
Y✝ : Sheaf J A
g✝ : X✝ ⟶ (sheafPushforwardCocontinuous G A J K).obj Y✝
⊢ (((fun X Y =>
              { toFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val },
                invFun := fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val },
                left_inv :=
                  (_ :
                    ∀ (f : (sheafPushforwardContinuous G A J K).obj X ⟶ Y),
                      (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                          ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val }) f) =
                        f),
                right_inv :=
                  (_ :
                    ∀ (f : X ⟶ (sheafPushforwardCocontinuous G A J K).obj Y),
                      (fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val) f.val })
                          ((fun f => { val := (Adjunction.homEquiv (Ran.adjunction A G.op) X.val Y.val).symm f.val })
                            f) =
                        f) })
            X✝ Y✝).symm
        g✝).val =
    ((sheafPushforwardContinuous G A J K).map g✝ ≫
        (NatTrans.mk fun X => { val := (Ran.adjunction A G.op).counit.app X.val }).app Y✝).val

Next tactic:
apply (Ran.adjunction A G.op).homEquiv_counit
lemma Functor.toSheafify_pullbackSheafificationCompatibility (F : Dᵒᵖ ⥤ A) :
    J.toSheafify (G.op ⋙ F) ≫
    ((G.pushforwardContinuousSheafificationCompatibility A J K).hom.app F).val =
    whiskerLeft _ (K.toSheafify _) := by
  

Proof state:
C D : Type u
inst✝¹³ : Category.{v, u} C
inst✝¹² : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝¹¹ : Category.{max u v, w} A
inst✝¹⁰ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝⁹ : IsCocontinuous G J K
inst✝⁸ : ConcreteCategory A
inst✝⁷ : PreservesLimits (forget A)
inst✝⁶ : ReflectsIsomorphisms (forget A)
inst✝⁵ : (X : C) → PreservesColimitsOfShape (GrothendieckTopology.Cover J X)ᵒᵖ (forget A)
inst✝⁴ : ∀ (X : C), HasColimitsOfShape (GrothendieckTopology.Cover J X)ᵒᵖ A
inst✝³ : (X : D) → PreservesColimitsOfShape (GrothendieckTopology.Cover K X)ᵒᵖ (forget A)
inst✝² : ∀ (X : D), HasColimitsOfShape (GrothendieckTopology.Cover K X)ᵒᵖ A
inst✝¹ : IsCocontinuous G J K
inst✝ : IsContinuous G J K
F : Dᵒᵖ ⥤ A
⊢ GrothendieckTopology.toSheafify J (G.op ⋙ F) ≫
      ((pushforwardContinuousSheafificationCompatibility G A J K).hom.app F).val =
    whiskerLeft G.op (GrothendieckTopology.toSheafify K F)

Next tactic:
dsimp [pushforwardContinuousSheafificationCompatibility, Adjunction.leftAdjointUniq]