-- Mathlib/CategoryTheory/Sites/PreservesSheafification.lean
lemma GrothendieckTopology.preservesSheafification_iff_of_adjunctions_of_hasSheafCompose :
    J.PreservesSheafification F ↔ IsIso (sheafComposeNatTrans J F adj₁ adj₂)

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
⊢ (∀ (P : Cᵒᵖ ⥤ A), IsIso (G₂.map (whiskerRight (adj₁.unit.app P) F))) ↔
    ∀ (X : Cᵒᵖ ⥤ A), IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app X)

Tactic:
apply forall_congr'

Result:
case h
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
⊢ ∀ (a : Cᵒᵖ ⥤ A),
    IsIso (G₂.map (whiskerRight (adj₁.unit.app a) F)) ↔ IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app a)

Proof state:
case h
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
⊢ ∀ (a : Cᵒᵖ ⥤ A),
    IsIso (G₂.map (whiskerRight (adj₁.unit.app a) F)) ↔ IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app a)

Tactic:
intro P

Result:
case h
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
P : Cᵒᵖ ⥤ A
⊢ IsIso (G₂.map (whiskerRight (adj₁.unit.app P) F)) ↔ IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app P)

Proof state:
case h
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
P : Cᵒᵖ ⥤ A
⊢ IsIso (G₂.map (whiskerRight (adj₁.unit.app P) F)) ↔ IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app P)

Tactic:
rw [← J.W_iff_isIso_map_of_adjunction adj₂, ← J.W_sheafToPreheaf_map_iff_isIso,
  ← sheafComposeNatTrans_fac J F adj₁ adj₂,
  (W _).precomp_iff _ _ (J.W_adj_unit_app adj₂ (P ⋙ F))]

Result:
no goals

Proof state:
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
⊢ J.PreservesSheafification F ↔ IsIso (sheafComposeNatTrans J F adj₁ adj₂)

Tactic:
rw [J.preservesSheafification_iff_of_adjunctions F adj₁ adj₂,
  NatTrans.isIso_iff_isIso_app]

Result:
C : Type u
inst✝³ : Category.{v, u} C
J : GrothendieckTopology C
A : Type u_1
B : Type u_2
inst✝² : Category.{u_3, u_1} A
inst✝¹ : Category.{u_4, u_2} B
F : A ⥤ B
G₁ : (Cᵒᵖ ⥤ A) ⥤ Sheaf J A
adj₁ : G₁ ⊣ sheafToPresheaf J A
G₂ : (Cᵒᵖ ⥤ B) ⥤ Sheaf J B
adj₂ : G₂ ⊣ sheafToPresheaf J B
inst✝ : J.HasSheafCompose F
⊢ (∀ (P : Cᵒᵖ ⥤ A), IsIso (G₂.map (whiskerRight (adj₁.unit.app P) F))) ↔
    ∀ (X : Cᵒᵖ ⥤ A), IsIso ((sheafComposeNatTrans J F adj₁ adj₂).app X)