l3lab/ntp-mathlib huggingface dataset:
/-- The composition of left adjoint mates is the adjoint mate of the composition. -/
@[reassoc]
theorem comp_leftAdjointMate {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] [HasLeftDual Z] {f : X ⟶ Y}
    {g : Y ⟶ Z} : (ᘁf ≫ g) = (ᘁg) ≫ ᘁf := by
  rw [leftAdjointMate_comp]
  simp only [leftAdjointMate, id_tensor_comp, Iso.cancel_iso_inv_left, comp_tensor_id,
    Category.assoc]
  symm
  iterate 5
    trans
    rw [← Category.id_comp g, tensor_comp]
  rw [← Category.assoc]
  symm
  iterate 2
    trans
    rw [← Category.assoc]
  apply eq_whisker
  repeat'
    -- Porting note: why do we need to fill in the implicit `C` here, and below?
    rw [← @comp_tensor_id C]
  congr 1
  rw [← tensor_id_comp_id_tensor g (ρ_ (ᘁX)).hom, leftUnitor_inv_tensor_id, Category.assoc,
    Category.assoc, leftUnitor_inv_naturality_assoc, ← associator_inv_naturality_assoc, tensor_id,
    id_tensor_comp_tensor_id_assoc, ← associator_inv_naturality_assoc]
  slice_rhs 2 3 =>
    rw [← tensor_comp, tensor_id, Category.comp_id, ← Category.id_comp (η_ (ᘁY) Y), tensor_comp]
  rw [← tensor_id_comp_id_tensor (η_ (ᘁY) Y), ← tensor_id]
  repeat' rw [@Category.assoc C]
  rw [pentagon_inv_hom_assoc, ← associator_inv_naturality_assoc, associator_naturality_assoc]
  slice_rhs 5 7 => rw [← id_tensor_comp, ← id_tensor_comp, coevaluation_evaluation, id_tensor_comp]
  rw [associator_naturality_assoc]
  slice_rhs 4 5 => rw [← tensor_comp, rightUnitor_naturality, tensor_comp]
  repeat' 

Proof state:
case w.e_f
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
inst✝³ : MonoidalCategory C
X Y Z : C
inst✝² : HasLeftDual X
inst✝¹ : HasLeftDual Y
inst✝ : HasLeftDual Z
f : X ⟶ Y
g : Y ⟶ Z
⊢ η_ (ᘁX) X ≫ (𝟙 ᘁX ⊗ f) ≫ (𝟙 ᘁX ⊗ g) =
    (λ_ (𝟙_ C)).inv ≫
      (η_ (ᘁX) X ⊗ 𝟙 (𝟙_ C)) ≫
        (α_ (ᘁX) X (𝟙_ C)).hom ≫
          ((𝟙 ᘁX ⊗ (ρ_ X).hom) ≫ (𝟙 ᘁX ⊗ f)) ≫
            (𝟙 ᘁX ⊗ (λ_ Y).inv) ≫ (α_ (ᘁX) (𝟙_ C) Y).inv ≫ ((ρ_ ᘁX).hom ⊗ 𝟙 Y) ≫ (𝟙 ᘁX ⊗ g)

Next tactic:
rw [@Category.assoc C]
/-- The composition of left adjoint mates is the adjoint mate of the composition. -/
@[reassoc]
theorem comp_leftAdjointMate {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] [HasLeftDual Z] {f : X ⟶ Y}
    {g : Y ⟶ Z} : (ᘁf ≫ g) = (ᘁg) ≫ ᘁf := by
  rw [leftAdjointMate_comp]
  simp only [leftAdjointMate, id_tensor_comp, Iso.cancel_iso_inv_left, comp_tensor_id,
    Category.assoc]
  symm
  iterate 5
    trans
    rw [← Category.id_comp g, tensor_comp]
  rw [← Category.assoc]
  symm
  iterate 2
    trans
    rw [← Category.assoc]
  apply eq_whisker
  repeat'
    -- Porting note: why do we need to fill in the implicit `C` here, and below?
    rw [← @comp_tensor_id C]
  congr 1
  rw [← tensor_id_comp_id_tensor g (ρ_ (ᘁX)).hom, leftUnitor_inv_tensor_id, Category.assoc,
    Category.assoc, leftUnitor_inv_naturality_assoc, ← associator_inv_naturality_assoc, tensor_id,
    id_tensor_comp_tensor_id_assoc, ← associator_inv_naturality_assoc]
  slice_rhs 2 3 =>
    rw [← tensor_comp, tensor_id, Category.comp_id, ← Category.id_comp (η_ (ᘁY) Y), tensor_comp]
  rw [← tensor_id_comp_id_tensor (η_ (ᘁY) Y), ← tensor_id]
  repeat' rw [@Category.assoc C]
  rw [pentagon_inv_hom_assoc, ← associator_inv_naturality_assoc, associator_naturality_assoc]
  slice_rhs 5 7 => rw [← id_tensor_comp, ← id_tensor_comp, coevaluation_evaluation, id_tensor_comp]
  rw [associator_naturality_assoc]
  slice_rhs 4 5 => rw [← tensor_comp, rightUnitor_naturality, tensor_comp]
  repeat' 

Proof state:
case w.e_f
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
inst✝³ : MonoidalCategory C
X Y Z : C
inst✝² : HasLeftDual X
inst✝¹ : HasLeftDual Y
inst✝ : HasLeftDual Z
f : X ⟶ Y
g : Y ⟶ Z
⊢ η_ (ᘁX) X ≫ (𝟙 ᘁX ⊗ f) ≫ (𝟙 ᘁX ⊗ g) =
    (λ_ (𝟙_ C)).inv ≫
      (η_ (ᘁX) X ⊗ 𝟙 (𝟙_ C)) ≫
        (α_ (ᘁX) X (𝟙_ C)).hom ≫
          (𝟙 ᘁX ⊗ (ρ_ X).hom) ≫
            (𝟙 ᘁX ⊗ f) ≫ (𝟙 ᘁX ⊗ (λ_ Y).inv) ≫ (α_ (ᘁX) (𝟙_ C) Y).inv ≫ ((ρ_ ᘁX).hom ⊗ 𝟙 Y) ≫ (𝟙 ᘁX ⊗ g)

Next tactic:
rw [@Category.assoc C]
/-- The composition of left adjoint mates is the adjoint mate of the composition. -/
@[reassoc]
theorem comp_leftAdjointMate {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] [HasLeftDual Z] {f : X ⟶ Y}
    {g : Y ⟶ Z} : (ᘁf ≫ g) = (ᘁg) ≫ ᘁf := by
  rw [leftAdjointMate_comp]
  simp only [leftAdjointMate, id_tensor_comp, Iso.cancel_iso_inv_left, comp_tensor_id,
    Category.assoc]
  symm
  iterate 5
    trans
    rw [← Category.id_comp g, tensor_comp]
  rw [← Category.assoc]
  symm
  iterate 2
    trans
    rw [← Category.assoc]
  apply eq_whisker
  repeat'
    -- Porting note: why do we need to fill in the implicit `C` here, and below?
    rw [← @comp_tensor_id C]
  congr 1
  rw [← tensor_id_comp_id_tensor g (ρ_ (ᘁX)).hom, leftUnitor_inv_tensor_id, Category.assoc,
    Category.assoc, leftUnitor_inv_naturality_assoc, ← associator_inv_naturality_assoc, tensor_id,
    id_tensor_comp_tensor_id_assoc, ← associator_inv_naturality_assoc]
  slice_rhs 2 3 =>
    rw [← tensor_comp, tensor_id, Category.comp_id, ← Category.id_comp (η_ (ᘁY) Y), tensor_comp]
  rw [← tensor_id_comp_id_tensor (η_ (ᘁY) Y), ← tensor_id]
  repeat' rw [@Category.assoc C]
  rw [pentagon_inv_hom_assoc, ← associator_inv_naturality_assoc, associator_naturality_assoc]
  slice_rhs 5 7 => rw [← id_tensor_comp, ← id_tensor_comp, coevaluation_evaluation, id_tensor_comp]
  rw [associator_naturality_assoc]
  slice_rhs 4 5 => rw [← tensor_comp, rightUnitor_naturality, tensor_comp]
  repeat' rw [@Category.assoc C]
  

Proof state:
case w.e_f
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
inst✝³ : MonoidalCategory C
X Y Z : C
inst✝² : HasLeftDual X
inst✝¹ : HasLeftDual Y
inst✝ : HasLeftDual Z
f : X ⟶ Y
g : Y ⟶ Z
⊢ η_ (ᘁX) X ≫ (𝟙 ᘁX ⊗ f) ≫ (𝟙 ᘁX ⊗ g) =
    (λ_ (𝟙_ C)).inv ≫
      (η_ (ᘁX) X ⊗ 𝟙 (𝟙_ C)) ≫
        (α_ (ᘁX) X (𝟙_ C)).hom ≫
          (𝟙 ᘁX ⊗ (ρ_ X).hom) ≫
            (𝟙 ᘁX ⊗ f) ≫ (𝟙 ᘁX ⊗ (λ_ Y).inv) ≫ (α_ (ᘁX) (𝟙_ C) Y).inv ≫ ((ρ_ ᘁX).hom ⊗ 𝟙 Y) ≫ (𝟙 ᘁX ⊗ g)

Next tactic:
rw [triangle_assoc_comp_left_inv_assoc, ← rightUnitor_tensor_assoc,
    rightUnitor_naturality_assoc, ← unitors_equal, ← Category.assoc, ← Category.assoc]
/-- The composition of left adjoint mates is the adjoint mate of the composition. -/
@[reassoc]
theorem comp_leftAdjointMate {X Y Z : C} [HasLeftDual X] [HasLeftDual Y] [HasLeftDual Z] {f : X ⟶ Y}
    {g : Y ⟶ Z} : (ᘁf ≫ g) = (ᘁg) ≫ ᘁf := by
  rw [leftAdjointMate_comp]
  simp only [leftAdjointMate, id_tensor_comp, Iso.cancel_iso_inv_left, comp_tensor_id,
    Category.assoc]
  symm
  iterate 5
    trans
    rw [← Category.id_comp g, tensor_comp]
  rw [← Category.assoc]
  symm
  iterate 2
    trans
    rw [← Category.assoc]
  apply eq_whisker
  repeat'
    -- Porting note: why do we need to fill in the implicit `C` here, and below?
    rw [← @comp_tensor_id C]
  congr 1
  rw [← tensor_id_comp_id_tensor g (ρ_ (ᘁX)).hom, leftUnitor_inv_tensor_id, Category.assoc,
    Category.assoc, leftUnitor_inv_naturality_assoc, ← associator_inv_naturality_assoc, tensor_id,
    id_tensor_comp_tensor_id_assoc, ← associator_inv_naturality_assoc]
  slice_rhs 2 3 =>
    rw [← tensor_comp, tensor_id, Category.comp_id, ← Category.id_comp (η_ (ᘁY) Y), tensor_comp]
  rw [← tensor_id_comp_id_tensor (η_ (ᘁY) Y), ← tensor_id]
  repeat' rw [@Category.assoc C]
  rw [pentagon_inv_hom_assoc, ← associator_inv_naturality_assoc, associator_naturality_assoc]
  slice_rhs 5 7 => rw [← id_tensor_comp, ← id_tensor_comp, coevaluation_evaluation, id_tensor_comp]
  rw [associator_naturality_assoc]
  slice_rhs 4 5 => rw [← tensor_comp, rightUnitor_naturality, tensor_comp]
  repeat' rw [@Category.assoc C]
  rw [triangle_assoc_comp_left_inv_assoc, ← rightUnitor_tensor_assoc,
    rightUnitor_naturality_assoc, ← unitors_equal, ← Category.assoc, ← Category.assoc]
  

Proof state:
case w.e_f
C : Type u₁
inst✝⁴ : Category.{v₁, u₁} C
inst✝³ : MonoidalCategory C
X Y Z : C
inst✝² : HasLeftDual X
inst✝¹ : HasLeftDual Y
inst✝ : HasLeftDual Z
f : X ⟶ Y
g : Y ⟶ Z
⊢ (η_ (ᘁX) X ≫ (𝟙 ᘁX ⊗ f)) ≫ (𝟙 ᘁX ⊗ g) =
    ((λ_ (𝟙_ C)).inv ≫ (λ_ (𝟙_ C)).hom) ≫
      η_ (ᘁX) X ≫ (𝟙 ᘁX ⊗ f) ≫ ((ρ_ ᘁX).inv ⊗ 𝟙 Y) ≫ ((ρ_ ᘁX).hom ⊗ 𝟙 Y) ≫ (𝟙 ᘁX ⊗ g)

Next tactic:
simp
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (fun f => (𝟙 Y' ⊗ f) ≫ (α_ Y' Y Z).inv ≫ (ε_ Y Y' ⊗ 𝟙 Z) ≫ (λ_ Z).hom)
      ((fun f => (λ_ X).inv ≫ (η_ Y Y' ⊗ 𝟙 X) ≫ (α_ Y Y' X).hom ≫ (𝟙 Y ⊗ f)) f) =
    f

Next tactic:
dsimp
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (𝟙 Y' ⊗ (λ_ X).inv ≫ (η_ Y Y' ⊗ 𝟙 X) ≫ (α_ Y Y' X).hom ≫ (𝟙 Y ⊗ f)) ≫ (α_ Y' Y Z).inv ≫ (ε_ Y Y' ⊗ 𝟙 Z) ≫ (λ_ Z).hom =
    f

Next tactic:
simp only [id_tensor_comp]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ ((𝟙 Y' ⊗ (λ_ X).inv) ≫ (𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X) ≫ (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (𝟙 Y' ⊗ 𝟙 Y ⊗ f)) ≫
      (α_ Y' Y Z).inv ≫ (ε_ Y Y' ⊗ 𝟙 Z) ≫ (λ_ Z).hom =
    f

Next tactic:
slice_lhs 4 5 => rw [associator_inv_naturality]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => 

Proof state:
case a.a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (𝟙 Y' ⊗ 𝟙 Y ⊗ f) ≫ (α_ Y' Y Z).inv
case a.a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| ε_ Y Y' ⊗ 𝟙 Z
case a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (λ_ Z).hom
case a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ (λ_ X).inv
case a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X
case a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ (α_ Y Y' X).hom

Next tactic:
rw [associator_inv_naturality]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (𝟙 Y' ⊗ (λ_ X).inv) ≫
      (𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X) ≫
        (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (((α_ Y' Y (Y' ⊗ X)).inv ≫ ((𝟙 Y' ⊗ 𝟙 Y) ⊗ f)) ≫ (ε_ Y Y' ⊗ 𝟙 Z)) ≫ (λ_ Z).hom =
    f

Next tactic:
slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => 

Proof state:
case a.a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| ((𝟙 Y' ⊗ 𝟙 Y) ⊗ f) ≫ (ε_ Y Y' ⊗ 𝟙 Z)
case a.a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (λ_ Z).hom
case a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ (λ_ X).inv
case a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X
case a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ (α_ Y Y' X).hom
case a.a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (α_ Y' Y (Y' ⊗ X)).inv

Next tactic:
rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (𝟙 Y' ⊗ (λ_ X).inv) ≫
      (𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X) ≫
        (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ ((ε_ Y Y' ⊗ 𝟙 (Y' ⊗ X)) ≫ (𝟙 (𝟙_ C) ⊗ f)) ≫ (λ_ Z).hom =
    f

Next tactic:
slice_lhs 2 5 => simp only [← tensor_id, associator_inv_conjugation]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
    slice_lhs 2 5 => 

Proof state:
case a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (𝟙 Y' ⊗ η_ Y Y' ⊗ 𝟙 X) ≫ (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (ε_ Y Y' ⊗ 𝟙 (Y' ⊗ X))
case a.a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 (𝟙_ C) ⊗ f
case a.a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| (λ_ Z).hom
case a
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
| 𝟙 Y' ⊗ (λ_ X).inv

Next tactic:
simp only [← tensor_id, associator_inv_conjugation]
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
    slice_lhs 2 5 => simp only [← tensor_id, associator_inv_conjugation]
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (𝟙 Y' ⊗ (λ_ X).inv) ≫
      ((((α_ Y' (𝟙_ C) X).inv ≫ ((𝟙 Y' ⊗ η_ Y Y') ⊗ 𝟙 X) ≫ (α_ Y' (Y ⊗ Y') X).hom) ≫
            (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫
              (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv ≫ ((ε_ Y Y' ⊗ 𝟙 Y') ⊗ 𝟙 X) ≫ (α_ (𝟙_ C) Y' X).hom) ≫
          (𝟙 (𝟙_ C) ⊗ f)) ≫
        (λ_ Z).hom =
    f

Next tactic:
have c :
      (α_ Y' (Y ⊗ Y') X).hom ≫
          (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv =
        (α_ _ _ _).inv ⊗ 𝟙 _ := by pure_coherence
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
    slice_lhs 2 5 => simp only [← tensor_id, associator_inv_conjugation]
    have c :
      (α_ Y' (Y ⊗ Y') X).hom ≫
          (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv =
        (α_ _ _ _).inv ⊗ 𝟙 _ := by 

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
⊢ (α_ Y' (Y ⊗ Y') X).hom ≫ (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv =
    (α_ Y' Y Y').inv ⊗ 𝟙 X

Next tactic:
pure_coherence
/-- Given an exact pairing on `Y Y'`,
we get a bijection on hom-sets `(Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z)`
by "pulling the string on the left" up or down.

This gives the adjunction `tensorLeftAdjunction Y Y' : tensorLeft Y' ⊣ tensorLeft Y`.

This adjunction is often referred to as "Frobenius reciprocity" in the
fusion categories / planar algebras / subfactors literature.
-/
def tensorLeftHomEquiv (X Y Y' Z : C) [ExactPairing Y Y'] : (Y' ⊗ X ⟶ Z) ≃ (X ⟶ Y ⊗ Z) where
  toFun f := (λ_ _).inv ≫ (η_ _ _ ⊗ 𝟙 _) ≫ (α_ _ _ _).hom ≫ (𝟙 _ ⊗ f)
  invFun f := (𝟙 Y' ⊗ f) ≫ (α_ _ _ _).inv ≫ (ε_ _ _ ⊗ 𝟙 _) ≫ (λ_ _).hom
  left_inv f := by
    dsimp
    simp only [id_tensor_comp]
    slice_lhs 4 5 => rw [associator_inv_naturality]
    slice_lhs 5 6 => rw [tensor_id, id_tensor_comp_tensor_id, ← tensor_id_comp_id_tensor]
    slice_lhs 2 5 => simp only [← tensor_id, associator_inv_conjugation]
    have c :
      (α_ Y' (Y ⊗ Y') X).hom ≫
          (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv =
        (α_ _ _ _).inv ⊗ 𝟙 _ := by pure_coherence
    

Proof state:
C : Type u₁
inst✝² : Category.{v₁, u₁} C
inst✝¹ : MonoidalCategory C
X Y Y' Z : C
inst✝ : ExactPairing Y Y'
f : Y' ⊗ X ⟶ Z
c :
  (α_ Y' (Y ⊗ Y') X).hom ≫ (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫ (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv =
    (α_ Y' Y Y').inv ⊗ 𝟙 X
⊢ (𝟙 Y' ⊗ (λ_ X).inv) ≫
      ((((α_ Y' (𝟙_ C) X).inv ≫ ((𝟙 Y' ⊗ η_ Y Y') ⊗ 𝟙 X) ≫ (α_ Y' (Y ⊗ Y') X).hom) ≫
            (𝟙 Y' ⊗ (α_ Y Y' X).hom) ≫
              (α_ Y' Y (Y' ⊗ X)).inv ≫ (α_ (Y' ⊗ Y) Y' X).inv ≫ ((ε_ Y Y' ⊗ 𝟙 Y') ⊗ 𝟙 X) ≫ (α_ (𝟙_ C) Y' X).hom) ≫
          (𝟙 (𝟙_ C) ⊗ f)) ≫
        (λ_ Z).hom =
    f

Next tactic:
slice_lhs 4 7 => rw [c]