l3lab/ntp-mathlib huggingface dataset:
/-- The sum of two functors. -/
def sum (F : A ⥤ B) (G : C ⥤ D) : Sum A C ⥤ Sum B D
    where
  obj X :=
    match X with
    | inl X => inl (F.obj X)
    | inr X => inr (G.obj X)
  map := @fun X Y f =>
    match X, Y, f with
    | inl X, inl Y, f => F.map f
    | inr X, inr Y, f => G.map f
  map_id := @fun X => by cases X <;> (erw [Functor.map_id]; rfl)
  map_comp := @fun X Y Z f g =>
    match X, Y, Z, f, g with
    | inl X, inl Y, inl Z, f, g => by 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F : A ⥤ B
G : C ⥤ D
X✝ Y✝ Z✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
X Y Z : A
f : inl X ⟶ inl Y
g : inl Y ⟶ inl Z
⊢ {
          obj := fun X =>
            match X with
            | inl X => inl (F.obj X)
            | inr X => inr (G.obj X),
          map := fun X Y f =>
            match X, Y, f with
            | inl X, inl Y, f => F.map f
            | inr X, inr Y, f => G.map f }.map
      (f ≫ g) =
    {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        f ≫
      {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        g

Next tactic:
erw [F.map_comp]
/-- The sum of two functors. -/
def sum (F : A ⥤ B) (G : C ⥤ D) : Sum A C ⥤ Sum B D
    where
  obj X :=
    match X with
    | inl X => inl (F.obj X)
    | inr X => inr (G.obj X)
  map := @fun X Y f =>
    match X, Y, f with
    | inl X, inl Y, f => F.map f
    | inr X, inr Y, f => G.map f
  map_id := @fun X => by cases X <;> (erw [Functor.map_id]; rfl)
  map_comp := @fun X Y Z f g =>
    match X, Y, Z, f, g with
    | inl X, inl Y, inl Z, f, g => by erw [F.map_comp]; 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F : A ⥤ B
G : C ⥤ D
X✝ Y✝ Z✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
X Y Z : A
f : inl X ⟶ inl Y
g : inl Y ⟶ inl Z
⊢ F.map f ≫ F.map g =
    {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        f ≫
      {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        g

Next tactic:
rfl
/-- The sum of two functors. -/
def sum (F : A ⥤ B) (G : C ⥤ D) : Sum A C ⥤ Sum B D
    where
  obj X :=
    match X with
    | inl X => inl (F.obj X)
    | inr X => inr (G.obj X)
  map := @fun X Y f =>
    match X, Y, f with
    | inl X, inl Y, f => F.map f
    | inr X, inr Y, f => G.map f
  map_id := @fun X => by cases X <;> (erw [Functor.map_id]; rfl)
  map_comp := @fun X Y Z f g =>
    match X, Y, Z, f, g with
    | inl X, inl Y, inl Z, f, g => by erw [F.map_comp]; rfl
    | inr X, inr Y, inr Z, f, g => by 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F : A ⥤ B
G : C ⥤ D
X✝ Y✝ Z✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
X Y Z : C
f : inr X ⟶ inr Y
g : inr Y ⟶ inr Z
⊢ {
          obj := fun X =>
            match X with
            | inl X => inl (F.obj X)
            | inr X => inr (G.obj X),
          map := fun X Y f =>
            match X, Y, f with
            | inl X, inl Y, f => F.map f
            | inr X, inr Y, f => G.map f }.map
      (f ≫ g) =
    {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        f ≫
      {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        g

Next tactic:
erw [G.map_comp]
/-- The sum of two functors. -/
def sum (F : A ⥤ B) (G : C ⥤ D) : Sum A C ⥤ Sum B D
    where
  obj X :=
    match X with
    | inl X => inl (F.obj X)
    | inr X => inr (G.obj X)
  map := @fun X Y f =>
    match X, Y, f with
    | inl X, inl Y, f => F.map f
    | inr X, inr Y, f => G.map f
  map_id := @fun X => by cases X <;> (erw [Functor.map_id]; rfl)
  map_comp := @fun X Y Z f g =>
    match X, Y, Z, f, g with
    | inl X, inl Y, inl Z, f, g => by erw [F.map_comp]; rfl
    | inr X, inr Y, inr Z, f, g => by erw [G.map_comp]; 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F : A ⥤ B
G : C ⥤ D
X✝ Y✝ Z✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
X Y Z : C
f : inr X ⟶ inr Y
g : inr Y ⟶ inr Z
⊢ G.map f ≫ G.map g =
    {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        f ≫
      {
            obj := fun X =>
              match X with
              | inl X => inl (F.obj X)
              | inr X => inr (G.obj X),
            map := fun X Y f =>
              match X, Y, f with
              | inl X, inl Y, f => F.map f
              | inr X, inr Y, f => G.map f }.map
        g

Next tactic:
rfl
/-- The sum of two natural transformations. -/
def sum {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.sum H ⟶ G.sum I
    where
  app X :=
    match X with
    | inl X => α.app X
    | inr X => β.app X
  naturality X Y f :=
    match X, Y, f with
    | inl X, inl Y, f => by 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
X✝ Y✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
X Y : A
f : inl X ⟶ inl Y
⊢ (Functor.sum F H).map f ≫
      (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inl Y) =
    (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inl X) ≫
      (Functor.sum G I).map f

Next tactic:
erw [α.naturality]
/-- The sum of two natural transformations. -/
def sum {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.sum H ⟶ G.sum I
    where
  app X :=
    match X with
    | inl X => α.app X
    | inr X => β.app X
  naturality X Y f :=
    match X, Y, f with
    | inl X, inl Y, f => by erw [α.naturality]; 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
X✝ Y✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
X Y : A
f : inl X ⟶ inl Y
⊢ α.app X ≫ G.map f =
    (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inl X) ≫
      (Functor.sum G I).map f

Next tactic:
rfl
/-- The sum of two natural transformations. -/
def sum {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.sum H ⟶ G.sum I
    where
  app X :=
    match X with
    | inl X => α.app X
    | inr X => β.app X
  naturality X Y f :=
    match X, Y, f with
    | inl X, inl Y, f => by erw [α.naturality]; rfl
    | inr X, inr Y, f => by 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
X✝ Y✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
X Y : C
f : inr X ⟶ inr Y
⊢ (Functor.sum F H).map f ≫
      (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inr Y) =
    (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inr X) ≫
      (Functor.sum G I).map f

Next tactic:
erw [β.naturality]
/-- The sum of two natural transformations. -/
def sum {F G : A ⥤ B} {H I : C ⥤ D} (α : F ⟶ G) (β : H ⟶ I) : F.sum H ⟶ G.sum I
    where
  app X :=
    match X with
    | inl X => α.app X
    | inr X => β.app X
  naturality X Y f :=
    match X, Y, f with
    | inl X, inl Y, f => by erw [α.naturality]; rfl
    | inr X, inr Y, f => by erw [β.naturality]; 

Proof state:
A : Type u₁
inst✝³ : Category.{v₁, u₁} A
B : Type u₁
inst✝² : Category.{v₁, u₁} B
C : Type u₁
inst✝¹ : Category.{v₁, u₁} C
D : Type u₁
inst✝ : Category.{v₁, u₁} D
F G : A ⥤ B
H I : C ⥤ D
α : F ⟶ G
β : H ⟶ I
X✝ Y✝ : A ⊕ C
f✝ : X✝ ⟶ Y✝
X Y : C
f : inr X ⟶ inr Y
⊢ β.app X ≫ I.map f =
    (fun X =>
          match X with
          | inl X => α.app X
          | inr X => β.app X)
        (inr X) ≫
      (Functor.sum G I).map f

Next tactic:
rfl
theorem countP_of (x : α) : countP p (of x) = if p x = true then 1 else 0 := by
  

Proof state:
α : Type u_1
p : α → Prop
inst✝ : DecidablePred p
x : α
⊢ (countP p) (of x) = if p x = (true = true) then 1 else 0

Next tactic:
simp [countP, List.countP, List.countP.go]
theorem count_of [DecidableEq α] (x y : α) : count x (of y) = (Pi.single x 1 : α → ℕ) y := by
  

Proof state:
α : Type u_1
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidableEq α
x y : α
⊢ (count x) (of y) = Pi.single x 1 y

Next tactic:
simp [Pi.single, Function.update, count, countP, List.countP, List.countP.go,
    Bool.beq_eq_decide_eq]
theorem countP_of' (x : α) :
    countP p (of x) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0 := by
    

Proof state:
α : Type u_1
p : α → Prop
inst✝ : DecidablePred p
x : α
⊢ (countP p) (of x) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0

Next tactic:
erw [FreeAddMonoid.countP_of]
theorem countP_of' (x : α) :
    countP p (of x) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0 := by
    erw [FreeAddMonoid.countP_of]
    

Proof state:
α : Type u_1
p : α → Prop
inst✝ : DecidablePred p
x : α
⊢ (if p x = (true = true) then 1 else 0) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0

Next tactic:
simp only [eq_iff_iff, iff_true, ofAdd_zero]
theorem countP_of' (x : α) :
    countP p (of x) = if p x then Multiplicative.ofAdd 1 else Multiplicative.ofAdd 0 := by
    erw [FreeAddMonoid.countP_of]
    simp only [eq_iff_iff, iff_true, ofAdd_zero]; 

Proof state:
α : Type u_1
p : α → Prop
inst✝ : DecidablePred p
x : α
⊢ (if p x then 1 else 0) = if p x then Multiplicative.ofAdd 1 else 1

Next tactic:
rfl
theorem countP_of (x : α) : countP p (of x) = if p x then Multiplicative.ofAdd 1 else 1 := by
  

Proof state:
α : Type u_1
p : α → Prop
inst✝ : DecidablePred p
x : α
⊢ (countP p) (of x) = if p x then Multiplicative.ofAdd 1 else 1

Next tactic:
rw [countP_of', ofAdd_zero]
theorem count_of [DecidableEq α] (x y : α) :
    count x (of y) = @Pi.mulSingle α (fun _ => Multiplicative ℕ) _ _ x (Multiplicative.ofAdd 1) y :=
  by 

Proof state:
α : Type u_1
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : DecidableEq α
x y : α
⊢ (count x) (of y) = Pi.mulSingle x (Multiplicative.ofAdd 1) y

Next tactic:
simp [count, countP_of, Pi.mulSingle_apply, eq_comm, Bool.beq_eq_decide_eq]
/-- `Nat.shrink' n` creates a list of smaller natural numbers by
successively dividing `n` by 2 . For example, `Nat.shrink 5 = [2, 1, 0]`. -/
def Nat.shrink (n : Nat) : List Nat :=
  if h : 0 < n then
    let m := n/2
    have : m < n := by
      

Proof state:
n : ℕ
h : 0 < n
m : ℕ := n / 2
⊢ m < n

Next tactic:
apply Nat.div_lt_self h
/-- `Nat.shrink' n` creates a list of smaller natural numbers by
successively dividing `n` by 2 . For example, `Nat.shrink 5 = [2, 1, 0]`. -/
def Nat.shrink (n : Nat) : List Nat :=
  if h : 0 < n then
    let m := n/2
    have : m < n := by
      apply Nat.div_lt_self h
      

Proof state:
n : ℕ
h : 0 < n
m : ℕ := n / 2
⊢ 1 < 2

Next tactic:
decide
instance Fin.sampleableExt {n : Nat} : SampleableExt (Fin (n.succ)) :=
  mkSelfContained (do choose (Fin n.succ) (Fin.ofNat 0) (Fin.ofNat (← getSize)) (by
    

Proof state:
n : ℕ
⊢ Fin.ofNat 0 ≤ Fin.ofNat __do_lift✝

Next tactic:
simp only [LE.le, Fin.ofNat, Nat.zero_mod, Fin.zero_eta, Fin.val_zero, Nat.le_eq]
instance Fin.sampleableExt {n : Nat} : SampleableExt (Fin (n.succ)) :=
  mkSelfContained (do choose (Fin n.succ) (Fin.ofNat 0) (Fin.ofNat (← getSize)) (by
    simp only [LE.le, Fin.ofNat, Nat.zero_mod, Fin.zero_eta, Fin.val_zero, Nat.le_eq]
    

Proof state:
n : ℕ
⊢ 0 ≤ __do_lift✝ % (n + 1)

Next tactic:
exact Nat.zero_le _
instance Char.sampleableDefault : SampleableExt Char :=
  Char.sampleable 3 " 0123abcABC:,;`\\/".toList (by 

Proof state:
⊢ 0 < List.length (String.toList " 0123abcABC:,;`\\/")

Next tactic:
decide
/-- If the left adjoint is fully faithful, then the unit is an isomorphism.

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨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
X : C
⊢ (yoneda.map (h.unit.app X) ≫ NatTrans.mk fun Y f => L.preimage ((Adjunction.homEquiv h Y.unop (L.obj X)).symm f)) =
    𝟙 (yoneda.obj ((𝟭 C).obj X))

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

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((𝟭 C).obj X)).obj x
⊢ (yoneda.map (h.unit.app X) ≫ NatTrans.mk fun Y f => L.preimage ((Adjunction.homEquiv h Y.unop (L.obj X)).symm f)).app
      x a✝ =
    (𝟙 (yoneda.obj ((𝟭 C).obj X))).app x a✝

Next tactic:
apply L.map_injective
/-- If the left adjoint is fully faithful, then the unit is an isomorphism.

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((𝟭 C).obj X)).obj x
⊢ L.map
      ((yoneda.map (h.unit.app X) ≫
            NatTrans.mk fun Y f => L.preimage ((Adjunction.homEquiv h Y.unop (L.obj X)).symm f)).app
        x a✝) =
    L.map ((𝟙 (yoneda.obj ((𝟭 C).obj X))).app x a✝)

Next tactic:
aesop_cat
/-- If the left adjoint is fully faithful, then the unit is an isomorphism.

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.map_injective
            aesop_cat,
           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
X : C
⊢ (NatTrans.mk fun Y f => L.preimage ((Adjunction.homEquiv h Y.unop (L.obj X)).symm f)) ≫ yoneda.map (h.unit.app X) =
    𝟙 (yoneda.obj ((L ⋙ R).obj X))

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

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.map_injective
            aesop_cat,
           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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((L ⋙ R).obj X)).obj x
⊢ ((NatTrans.mk fun Y f => L.preimage ((Adjunction.homEquiv h Y.unop (L.obj X)).symm f)) ≫
          yoneda.map (h.unit.app X)).app
      x a✝ =
    (𝟙 (yoneda.obj ((L ⋙ R).obj X))).app x a✝

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

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.map_injective
            aesop_cat,
           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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((L ⋙ R).obj X)).obj x
⊢ L.preimage ((Adjunction.homEquiv h x.unop (L.obj X)).symm a✝) ≫ h.unit.app X = a✝

Next tactic:
simp only [Adjunction.homEquiv_counit, preimage_comp, preimage_map, Category.assoc]
/-- If the left adjoint is fully faithful, then the unit is an isomorphism.

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.map_injective
            aesop_cat,
           by
            ext x
            dsimp
            simp only [Adjunction.homEquiv_counit, preimage_comp, preimage_map, Category.assoc]
            

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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((L ⋙ R).obj X)).obj x
⊢ a✝ ≫ L.preimage (h.counit.app (L.obj X)) ≫ h.unit.app X = a✝

Next tactic:
rw [← h.unit_naturality]
/-- If the left adjoint is fully faithful, then the unit is an isomorphism.

See
* Lemma 4.5.13 from [Riehl][riehl2017]
* https://math.stackexchange.com/a/2727177
* https://stacks.math.columbia.edu/tag/07RB (we only prove the forward direction!)
-/
instance unit_isIso_of_L_fully_faithful [Full L] [Faithful L] : IsIso (Adjunction.unit h) :=
  @NatIso.isIso_of_isIso_app _ _ _ _ _ _ (Adjunction.unit h) fun X =>
    @Yoneda.isIso _ _ _ _ ((Adjunction.unit h).app X)
      ⟨⟨{ app := fun Y f => L.preimage ((h.homEquiv (unop Y) (L.obj X)).symm f) },
          ⟨by
            ext x
            apply L.map_injective
            aesop_cat,
           by
            ext x
            dsimp
            simp only [Adjunction.homEquiv_counit, preimage_comp, preimage_map, Category.assoc]
            rw [← h.unit_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 L
inst✝ : Faithful L
X : C
x : Cᵒᵖ
a✝ : (yoneda.obj ((L ⋙ R).obj X)).obj x
⊢ a✝ ≫ h.unit.app (R.obj (L.obj X)) ≫ R.map (L.map (L.preimage (h.counit.app (L.obj 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
              

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
⊢ (coyoneda.map (h.counit.app X).op ≫ NatTrans.mk fun Y f => R.preimage ((Adjunction.homEquiv h (R.obj X) Y) f)) =
    𝟙 (coyoneda.obj (op ((𝟭 D).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
              

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 ((𝟭 D).obj X))).obj x
⊢ (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✝ =
    (𝟙 (coyoneda.obj (op ((𝟭 D).obj X)))).app x a✝

Next tactic:
apply R.map_injective