l3lab/ntp-mathlib huggingface dataset:
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              

Proof state:
case w.h.h.a
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X x : D
a✝ : (coyoneda.obj (op ((𝟭 D).obj X))).obj x
⊢ R.map
      ((coyoneda.map (h.counit.app X).op ≫
            NatTrans.mk fun Y f => R.preimage ((Adjunction.homEquiv h (R.obj X) Y) f)).app
        x a✝) =
    R.map ((𝟙 (coyoneda.obj (op ((𝟭 D).obj X)))).app x a✝)

Next tactic:
simp
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              simp,
             by
              

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X : D
⊢ (NatTrans.mk fun Y f => R.preimage ((Adjunction.homEquiv h (R.obj X) Y) f)) ≫ coyoneda.map (h.counit.app X).op =
    𝟙 (coyoneda.obj (op ((R ⋙ L).obj X)))

Next tactic:
ext x
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              simp,
             by
              ext x
              

Proof state:
case w.h.h
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X x : D
a✝ : (coyoneda.obj (op ((R ⋙ L).obj X))).obj x
⊢ ((NatTrans.mk fun Y f => R.preimage ((Adjunction.homEquiv h (R.obj X) Y) f)) ≫ coyoneda.map (h.counit.app X).op).app x
      a✝ =
    (𝟙 (coyoneda.obj (op ((R ⋙ L).obj X)))).app x a✝

Next tactic:
dsimp
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              simp,
             by
              ext x
              dsimp
              

Proof state:
case w.h.h
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X x : D
a✝ : (coyoneda.obj (op ((R ⋙ L).obj X))).obj x
⊢ h.counit.app X ≫ R.preimage ((Adjunction.homEquiv h (R.obj X) x) a✝) = a✝

Next tactic:
simp only [Adjunction.homEquiv_unit, preimage_comp, preimage_map]
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              simp,
             by
              ext x
              dsimp
              simp only [Adjunction.homEquiv_unit, preimage_comp, preimage_map]
              

Proof state:
case w.h.h
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X x : D
a✝ : (coyoneda.obj (op ((R ⋙ L).obj X))).obj x
⊢ h.counit.app X ≫ R.preimage (h.unit.app (R.obj X)) ≫ a✝ = a✝

Next tactic:
rw [← h.counit_naturality]
/-- If the right adjoint is fully faithful, then the counit is an isomorphism.

See <https://stacks.math.columbia.edu/tag/07RB> (we only prove the forward direction!)
-/
instance counit_isIso_of_R_fully_faithful [Full R] [Faithful R] : IsIso (Adjunction.counit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.counit h) fun X =>
    @isIso_of_op _ _ _ _ _ <|
      @Coyoneda.isIso _ _ _ _ ((Adjunction.counit h).app X).op
        ⟨⟨{ app := fun Y f => R.preimage ((h.homEquiv (R.obj X) Y) f) },
            ⟨by
              ext x
              apply R.map_injective
              simp,
             by
              ext x
              dsimp
              simp only [Adjunction.homEquiv_unit, preimage_comp, preimage_map]
              rw [← h.counit_naturality]
              

Proof state:
case w.h.h
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
X x : D
a✝ : (coyoneda.obj (op ((R ⋙ L).obj X))).obj x
⊢ L.map (R.map (R.preimage (h.unit.app (R.obj X)) ≫ a✝)) ≫ h.counit.app x = a✝

Next tactic:
simp
/-- If the unit is an isomorphism, then the left adjoint is faithful-/
theorem L_faithful_of_unit_isIso [IsIso h.unit] : Faithful L :=
  ⟨fun {X Y f g} H => by
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝ : IsIso h.unit
X Y : C
f g : X ⟶ Y
H : L.map f = L.map g
⊢ f = g

Next tactic:
rw [← (h.homEquiv X (L.obj Y)).apply_eq_iff_eq] at H
/-- If the unit is an isomorphism, then the left adjoint is faithful-/
theorem L_faithful_of_unit_isIso [IsIso h.unit] : Faithful L :=
  ⟨fun {X Y f g} H => by
    rw [← (h.homEquiv X (L.obj Y)).apply_eq_iff_eq] at H
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝ : IsIso h.unit
X Y : C
f g : X ⟶ Y
H : (Adjunction.homEquiv h X (L.obj Y)) (L.map f) = (Adjunction.homEquiv h X (L.obj Y)) (L.map g)
⊢ f = g

Next tactic:
simpa using H =≫ inv (h.unit.app Y)
/-- If the counit is an isomorphism, then the right adjoint is faithful-/
theorem R_faithful_of_counit_isIso [IsIso h.counit] : Faithful R :=
  ⟨fun {X Y f g} H => by
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝ : IsIso h.counit
X Y : D
f g : X ⟶ Y
H : R.map f = R.map g
⊢ f = g

Next tactic:
rw [← (h.homEquiv (R.obj X) Y).symm.apply_eq_iff_eq] at H
/-- If the counit is an isomorphism, then the right adjoint is faithful-/
theorem R_faithful_of_counit_isIso [IsIso h.counit] : Faithful R :=
  ⟨fun {X Y f g} H => by
    rw [← (h.homEquiv (R.obj X) Y).symm.apply_eq_iff_eq] at H
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
D : Type u₂
inst✝¹ : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝ : IsIso h.counit
X Y : D
f g : X ⟶ Y
H : (Adjunction.homEquiv h (R.obj X) Y).symm (R.map f) = (Adjunction.homEquiv h (R.obj X) Y).symm (R.map g)
⊢ f = g

Next tactic:
simpa using inv (h.counit.app X) ≫= H
instance whiskerLeft_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerLeft L h.counit) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
⊢ IsIso (whiskerLeft L h.counit)

Next tactic:
have := h.left_triangle
instance whiskerLeft_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerLeft L h.counit) := by
  have := h.left_triangle
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerRight h.unit L ≫ whiskerLeft L h.counit = 𝟙 (𝟭 C ⋙ L)
⊢ IsIso (whiskerLeft L h.counit)

Next tactic:
rw [← IsIso.eq_inv_comp] at this
instance whiskerLeft_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerLeft L h.counit) := by
  have := h.left_triangle
  rw [← IsIso.eq_inv_comp] at this
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerLeft L h.counit = inv (whiskerRight h.unit L) ≫ 𝟙 (𝟭 C ⋙ L)
⊢ IsIso (whiskerLeft L h.counit)

Next tactic:
rw [this]
instance whiskerLeft_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerLeft L h.counit) := by
  have := h.left_triangle
  rw [← IsIso.eq_inv_comp] at this
  rw [this]
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerLeft L h.counit = inv (whiskerRight h.unit L) ≫ 𝟙 (𝟭 C ⋙ L)
⊢ IsIso (inv (whiskerRight h.unit L) ≫ 𝟙 (𝟭 C ⋙ L))

Next tactic:
infer_instance
instance whiskerRight_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerRight h.counit R) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
⊢ IsIso (whiskerRight h.counit R)

Next tactic:
have := h.right_triangle
instance whiskerRight_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerRight h.counit R) := by
  have := h.right_triangle
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerLeft R h.unit ≫ whiskerRight h.counit R = 𝟙 (R ⋙ 𝟭 C)
⊢ IsIso (whiskerRight h.counit R)

Next tactic:
rw [← IsIso.eq_inv_comp] at this
instance whiskerRight_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerRight h.counit R) := by
  have := h.right_triangle
  rw [← IsIso.eq_inv_comp] at this
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerRight h.counit R = inv (whiskerLeft R h.unit) ≫ 𝟙 (R ⋙ 𝟭 C)
⊢ IsIso (whiskerRight h.counit R)

Next tactic:
rw [this]
instance whiskerRight_counit_iso_of_L_fully_faithful [Full L] [Faithful L] :
    IsIso (whiskerRight h.counit R) := by
  have := h.right_triangle
  rw [← IsIso.eq_inv_comp] at this
  rw [this]
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full L
inst✝ : Faithful L
this : whiskerRight h.counit R = inv (whiskerLeft R h.unit) ≫ 𝟙 (R ⋙ 𝟭 C)
⊢ IsIso (inv (whiskerLeft R h.unit) ≫ 𝟙 (R ⋙ 𝟭 C))

Next tactic:
infer_instance
instance whiskerLeft_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerLeft R h.unit) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
⊢ IsIso (whiskerLeft R h.unit)

Next tactic:
have := h.right_triangle
instance whiskerLeft_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerLeft R h.unit) := by
  have := h.right_triangle
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerLeft R h.unit ≫ whiskerRight h.counit R = 𝟙 (R ⋙ 𝟭 C)
⊢ IsIso (whiskerLeft R h.unit)

Next tactic:
rw [← IsIso.eq_comp_inv] at this
instance whiskerLeft_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerLeft R h.unit) := by
  have := h.right_triangle
  rw [← IsIso.eq_comp_inv] at this
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerLeft R h.unit = 𝟙 (R ⋙ 𝟭 C) ≫ inv (whiskerRight h.counit R)
⊢ IsIso (whiskerLeft R h.unit)

Next tactic:
rw [this]
instance whiskerLeft_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerLeft R h.unit) := by
  have := h.right_triangle
  rw [← IsIso.eq_comp_inv] at this
  rw [this]
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerLeft R h.unit = 𝟙 (R ⋙ 𝟭 C) ≫ inv (whiskerRight h.counit R)
⊢ IsIso (𝟙 (R ⋙ 𝟭 C) ≫ inv (whiskerRight h.counit R))

Next tactic:
infer_instance
instance whiskerRight_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerRight h.unit L) := by
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
⊢ IsIso (whiskerRight h.unit L)

Next tactic:
have := h.left_triangle
instance whiskerRight_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerRight h.unit L) := by
  have := h.left_triangle
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerRight h.unit L ≫ whiskerLeft L h.counit = 𝟙 (𝟭 C ⋙ L)
⊢ IsIso (whiskerRight h.unit L)

Next tactic:
rw [← IsIso.eq_comp_inv] at this
instance whiskerRight_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerRight h.unit L) := by
  have := h.left_triangle
  rw [← IsIso.eq_comp_inv] at this
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerRight h.unit L = 𝟙 (𝟭 C ⋙ L) ≫ inv (whiskerLeft L h.counit)
⊢ IsIso (whiskerRight h.unit L)

Next tactic:
rw [this]
instance whiskerRight_unit_iso_of_R_fully_faithful [Full R] [Faithful R] :
    IsIso (whiskerRight h.unit L) := by
  have := h.left_triangle
  rw [← IsIso.eq_comp_inv] at this
  rw [this]
  

Proof state:
C : Type u₁
inst✝³ : Category.{v₁, u₁} C
D : Type u₂
inst✝² : Category.{v₂, u₂} D
L : C ⥤ D
R : D ⥤ C
h : L ⊣ R
inst✝¹ : Full R
inst✝ : Faithful R
this : whiskerRight h.unit L = 𝟙 (𝟭 C ⋙ L) ≫ inv (whiskerLeft L h.counit)
⊢ IsIso (𝟙 (𝟭 C ⋙ L) ≫ inv (whiskerLeft L h.counit))

Next tactic:
infer_instance
/-- If `C` is a full subcategory of `C'` and `D` is a full subcategory of `D'`, then we can restrict
an adjunction `L' ⊣ R'` where `L' : C' ⥤ D'` and `R' : D' ⥤ C'` to `C` and `D`.
The construction here is slightly more general, in that `C` is required only to have a full and
faithful "inclusion" functor `iC : C ⥤ C'` (and similarly `iD : D ⥤ D'`) which commute (up to
natural isomorphism) with the proposed restrictions.
-/
def Adjunction.restrictFullyFaithful (iC : C ⥤ C') (iD : D ⥤ D') {L' : C' ⥤ D'} {R' : D' ⥤ C'}
    (adj : L' ⊣ R') {L : C ⥤ D} {R : D ⥤ C} (comm1 : iC ⋙ L' ≅ L ⋙ iD) (comm2 : iD ⋙ R' ≅ R ⋙ iC)
    [Full iC] [Faithful iC] [Full iD] [Faithful iD] : L ⊣ R :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        calc
          (L.obj X ⟶ Y) ≃ (iD.obj (L.obj X) ⟶ iD.obj Y) := equivOfFullyFaithful iD
          _ ≃ (L'.obj (iC.obj X) ⟶ iD.obj Y) := Iso.homCongr (comm1.symm.app X) (Iso.refl _)
          _ ≃ (iC.obj X ⟶ R'.obj (iD.obj Y)) := adj.homEquiv _ _
          _ ≃ (iC.obj X ⟶ iC.obj (R.obj Y)) := Iso.homCongr (Iso.refl _) (comm2.app Y)
          _ ≃ (X ⟶ R.obj Y) := (equivOfFullyFaithful iC).symm

      homEquiv_naturality_left_symm := fun {X' X Y} f g => by
        

Proof state:
C : Type u₁
inst✝⁷ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
L✝ : C ⥤ D
R✝ : D ⥤ C
h : L✝ ⊣ R✝
C' : Type u₃
inst✝⁵ : Category.{v₃, u₃} C'
D' : Type u₄
inst✝⁴ : Category.{v₄, u₄} D'
iC : C ⥤ C'
iD : D ⥤ D'
L' : C' ⥤ D'
R' : D' ⥤ C'
adj : L' ⊣ R'
L : C ⥤ D
R : D ⥤ C
comm1 : iC ⋙ L' ≅ L ⋙ iD
comm2 : iD ⋙ R' ≅ R ⋙ iC
inst✝³ : Full iC
inst✝² : Faithful iC
inst✝¹ : Full iD
inst✝ : Faithful iD
X' X : C
Y : D
f : X' ⟶ X
g : X ⟶ R.obj Y
⊢ ((fun X Y =>
            Trans.trans
              (Trans.trans
                (Trans.trans
                  (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                  (homEquiv adj (iC.obj X) (iD.obj Y)))
                (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
              (equivOfFullyFaithful iC).symm)
          X' Y).symm
      (f ≫ g) =
    L.map f ≫
      ((fun X Y =>
              Trans.trans
                (Trans.trans
                  (Trans.trans
                    (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                    (homEquiv adj (iC.obj X) (iD.obj Y)))
                  (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
                (equivOfFullyFaithful iC).symm)
            X Y).symm
        g

Next tactic:
apply iD.map_injective
/-- If `C` is a full subcategory of `C'` and `D` is a full subcategory of `D'`, then we can restrict
an adjunction `L' ⊣ R'` where `L' : C' ⥤ D'` and `R' : D' ⥤ C'` to `C` and `D`.
The construction here is slightly more general, in that `C` is required only to have a full and
faithful "inclusion" functor `iC : C ⥤ C'` (and similarly `iD : D ⥤ D'`) which commute (up to
natural isomorphism) with the proposed restrictions.
-/
def Adjunction.restrictFullyFaithful (iC : C ⥤ C') (iD : D ⥤ D') {L' : C' ⥤ D'} {R' : D' ⥤ C'}
    (adj : L' ⊣ R') {L : C ⥤ D} {R : D ⥤ C} (comm1 : iC ⋙ L' ≅ L ⋙ iD) (comm2 : iD ⋙ R' ≅ R ⋙ iC)
    [Full iC] [Faithful iC] [Full iD] [Faithful iD] : L ⊣ R :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        calc
          (L.obj X ⟶ Y) ≃ (iD.obj (L.obj X) ⟶ iD.obj Y) := equivOfFullyFaithful iD
          _ ≃ (L'.obj (iC.obj X) ⟶ iD.obj Y) := Iso.homCongr (comm1.symm.app X) (Iso.refl _)
          _ ≃ (iC.obj X ⟶ R'.obj (iD.obj Y)) := adj.homEquiv _ _
          _ ≃ (iC.obj X ⟶ iC.obj (R.obj Y)) := Iso.homCongr (Iso.refl _) (comm2.app Y)
          _ ≃ (X ⟶ R.obj Y) := (equivOfFullyFaithful iC).symm

      homEquiv_naturality_left_symm := fun {X' X Y} f g => by
        apply iD.map_injective
        

Proof state:
case a
C : Type u₁
inst✝⁷ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
L✝ : C ⥤ D
R✝ : D ⥤ C
h : L✝ ⊣ R✝
C' : Type u₃
inst✝⁵ : Category.{v₃, u₃} C'
D' : Type u₄
inst✝⁴ : Category.{v₄, u₄} D'
iC : C ⥤ C'
iD : D ⥤ D'
L' : C' ⥤ D'
R' : D' ⥤ C'
adj : L' ⊣ R'
L : C ⥤ D
R : D ⥤ C
comm1 : iC ⋙ L' ≅ L ⋙ iD
comm2 : iD ⋙ R' ≅ R ⋙ iC
inst✝³ : Full iC
inst✝² : Faithful iC
inst✝¹ : Full iD
inst✝ : Faithful iD
X' X : C
Y : D
f : X' ⟶ X
g : X ⟶ R.obj Y
⊢ iD.map
      (((fun X Y =>
              Trans.trans
                (Trans.trans
                  (Trans.trans
                    (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                    (homEquiv adj (iC.obj X) (iD.obj Y)))
                  (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
                (equivOfFullyFaithful iC).symm)
            X' Y).symm
        (f ≫ g)) =
    iD.map
      (L.map f ≫
        ((fun X Y =>
                Trans.trans
                  (Trans.trans
                    (Trans.trans
                      (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                      (homEquiv adj (iC.obj X) (iD.obj Y)))
                    (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
                  (equivOfFullyFaithful iC).symm)
              X Y).symm
          g)

Next tactic:
simpa [Trans.trans] using (comm1.inv.naturality_assoc f _).symm
/-- If `C` is a full subcategory of `C'` and `D` is a full subcategory of `D'`, then we can restrict
an adjunction `L' ⊣ R'` where `L' : C' ⥤ D'` and `R' : D' ⥤ C'` to `C` and `D`.
The construction here is slightly more general, in that `C` is required only to have a full and
faithful "inclusion" functor `iC : C ⥤ C'` (and similarly `iD : D ⥤ D'`) which commute (up to
natural isomorphism) with the proposed restrictions.
-/
def Adjunction.restrictFullyFaithful (iC : C ⥤ C') (iD : D ⥤ D') {L' : C' ⥤ D'} {R' : D' ⥤ C'}
    (adj : L' ⊣ R') {L : C ⥤ D} {R : D ⥤ C} (comm1 : iC ⋙ L' ≅ L ⋙ iD) (comm2 : iD ⋙ R' ≅ R ⋙ iC)
    [Full iC] [Faithful iC] [Full iD] [Faithful iD] : L ⊣ R :=
  Adjunction.mkOfHomEquiv
    { homEquiv := fun X Y =>
        calc
          (L.obj X ⟶ Y) ≃ (iD.obj (L.obj X) ⟶ iD.obj Y) := equivOfFullyFaithful iD
          _ ≃ (L'.obj (iC.obj X) ⟶ iD.obj Y) := Iso.homCongr (comm1.symm.app X) (Iso.refl _)
          _ ≃ (iC.obj X ⟶ R'.obj (iD.obj Y)) := adj.homEquiv _ _
          _ ≃ (iC.obj X ⟶ iC.obj (R.obj Y)) := Iso.homCongr (Iso.refl _) (comm2.app Y)
          _ ≃ (X ⟶ R.obj Y) := (equivOfFullyFaithful iC).symm

      homEquiv_naturality_left_symm := fun {X' X Y} f g => by
        apply iD.map_injective
        simpa [Trans.trans] using (comm1.inv.naturality_assoc f _).symm
      homEquiv_naturality_right := fun {X Y' Y} f g => by
        

Proof state:
C : Type u₁
inst✝⁷ : Category.{v₁, u₁} C
D : Type u₂
inst✝⁶ : Category.{v₂, u₂} D
L✝ : C ⥤ D
R✝ : D ⥤ C
h : L✝ ⊣ R✝
C' : Type u₃
inst✝⁵ : Category.{v₃, u₃} C'
D' : Type u₄
inst✝⁴ : Category.{v₄, u₄} D'
iC : C ⥤ C'
iD : D ⥤ D'
L' : C' ⥤ D'
R' : D' ⥤ C'
adj : L' ⊣ R'
L : C ⥤ D
R : D ⥤ C
comm1 : iC ⋙ L' ≅ L ⋙ iD
comm2 : iD ⋙ R' ≅ R ⋙ iC
inst✝³ : Full iC
inst✝² : Faithful iC
inst✝¹ : Full iD
inst✝ : Faithful iD
X : C
Y' Y : D
f : L.obj X ⟶ Y'
g : Y' ⟶ Y
⊢ ((fun X Y =>
          Trans.trans
            (Trans.trans
              (Trans.trans
                (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                (homEquiv adj (iC.obj X) (iD.obj Y)))
              (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
            (equivOfFullyFaithful iC).symm)
        X Y)
      (f ≫ g) =
    ((fun X Y =>
            Trans.trans
              (Trans.trans
                (Trans.trans
                  (Trans.trans (equivOfFullyFaithful iD) (Iso.homCongr (comm1.symm.app X) (Iso.refl (iD.obj Y))))
                  (homEquiv adj (iC.obj X) (iD.obj Y)))
                (Iso.homCongr (Iso.refl (iC.obj X)) (comm2.app Y)))
              (equivOfFullyFaithful iC).symm)
          X Y')
        f ≫
      R.map g

Next tactic:
apply iC.map_injective