File: Mathlib/CategoryTheory/Closed/Monoidal.lean

full_name: CategoryTheory.Closed.rightAdj
code: /-- An object `X` is (right) closed if `(X ⊗ -)` is a left adjoint. -/
class Closed {C : Type u} [Category.{v} C] [MonoidalCategory.{v} C] (X : C) where
  /-- a choice of a right adjoint for `tensorLeft X` -/
  rightAdj : C ⥤ C
  /-- `tensorLeft X` is a left adjoint -/
  adj : tensorLeft X ⊣ rightAdj
goal: CategoryTheory.Functor C C

full_name: CategoryTheory.Closed
code: /-- An object `X` is (right) closed if `(X ⊗ -)` is a left adjoint. -/
class Closed {C : Type u} [Category.{v} C] [MonoidalCategory.{v} C] (X : C) where
  /-- a choice of a right adjoint for `tensorLeft X` -/
  rightAdj : C ⥤ C
  /-- `tensorLeft X` is a left adjoint -/
  adj : tensorLeft X ⊣ rightAdj
goal: Type (max u v)

full_name: CategoryTheory.Closed.adj
code: /-- An object `X` is (right) closed if `(X ⊗ -)` is a left adjoint. -/
class Closed {C : Type u} [Category.{v} C] [MonoidalCategory.{v} C] (X : C) where
  /-- a choice of a right adjoint for `tensorLeft X` -/
  rightAdj : C ⥤ C
  /-- `tensorLeft X` is a left adjoint -/
  adj : tensorLeft X ⊣ rightAdj
goal: CategoryTheory.MonoidalCategory.tensorLeft X ⊣ CategoryTheory.Closed.rightAdj X

full_name: CategoryTheory.MonoidalClosed.closed
code: /-- A monoidal category `C` is (right) monoidal closed if every object is (right) closed. -/
class MonoidalClosed (C : Type u) [Category.{v} C] [MonoidalCategory.{v} C] where
  closed (X : C) : Closed X := by infer_instance
goal: CategoryTheory.Closed X

full_name: CategoryTheory.MonoidalClosed
code: /-- A monoidal category `C` is (right) monoidal closed if every object is (right) closed. -/
class MonoidalClosed (C : Type u) [Category.{v} C] [MonoidalCategory.{v} C] where
  closed (X : C) : Closed X := by infer_instance
goal: Type (max u v)

full_name: CategoryTheory.tensorClosed
code: /-- If `X` and `Y` are closed then `X ⊗ Y` is.
This isn't an instance because it's not usually how we want to construct internal homs,
we'll usually prove all objects are closed uniformly.
-/
def tensorClosed {X Y : C} (hX : Closed X) (hY : Closed Y) : Closed (X ⊗ Y) 
goal: CategoryTheory.Closed (CategoryTheory.MonoidalCategory.tensorObj X Y)

full_name: CategoryTheory.unitClosed
code: /-- The unit object is always closed.
This isn't an instance because most of the time we'll prove closedness for all objects at once,
rather than just for this one.
-/
def unitClosed : Closed (𝟙_ C) 
goal: CategoryTheory.Closed (𝟙_ C)

full_name: CategoryTheory.ihom
code: /-- This is the internal hom `A ⟶[C] -`.
-/
def ihom : C ⥤ C 
goal: CategoryTheory.Functor C C

full_name: CategoryTheory.ihom.adjunction
code: /-- The adjunction between `A ⊗ -` and `A ⟹ -`. -/
def adjunction : tensorLeft A ⊣ ihom A 
goal: CategoryTheory.MonoidalCategory.tensorLeft A ⊣ CategoryTheory.ihom A

full_name: CategoryTheory.ihom.ev
code: /-- The evaluation natural transformation. -/
def ev : ihom A ⋙ tensorLeft A ⟶ 𝟭 C 
goal: (CategoryTheory.ihom A).comp (CategoryTheory.MonoidalCategory.tensorLeft A) ⟶ CategoryTheory.Functor.id C

full_name: CategoryTheory.ihom.coev
code: /-- The coevaluation natural transformation. -/
def coev : 𝟭 C ⟶ tensorLeft A ⋙ ihom A 
goal: CategoryTheory.Functor.id C ⟶ (CategoryTheory.MonoidalCategory.tensorLeft A).comp (CategoryTheory.ihom A)

full_name: CategoryTheory.ihom.ihom_adjunction_counit
code: @[simp]
theorem ihom_adjunction_counit : (ihom.adjunction A).counit = ev A 
goal: (CategoryTheory.ihom.adjunction A).counit = CategoryTheory.ihom.ev A

full_name: CategoryTheory.ihom.ihom_adjunction_unit
code: @[simp]
theorem ihom_adjunction_unit : (ihom.adjunction A).unit = coev A 
goal: (CategoryTheory.ihom.adjunction A).unit = CategoryTheory.ihom.coev A

full_name: CategoryTheory.ihom.ev_naturality
code: @[reassoc (attr := simp)]
theorem ev_naturality {X Y : C} (f : X ⟶ Y) :
    A ◁ (ihom A).map f ≫ (ev A).app Y = (ev A).app X ≫ f 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerLeft A ((CategoryTheory.ihom A).map f))
    ((CategoryTheory.ihom.ev A).app Y) =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.ev A).app X) f

full_name: CategoryTheory.ihom.coev_naturality
code: @[reassoc (attr := simp)]
theorem coev_naturality {X Y : C} (f : X ⟶ Y) :
    f ≫ (coev A).app Y = (coev A).app X ≫ (ihom A).map (A ◁ f) 
goal: CategoryTheory.CategoryStruct.comp f ((CategoryTheory.ihom.coev A).app Y) =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.coev A).app X)
    ((CategoryTheory.ihom A).map (CategoryTheory.MonoidalCategory.whiskerLeft A f))

full_name: CategoryTheory.ihom.«_aux_Mathlib_CategoryTheory_Closed_Monoidal___macroRules_CategoryTheory_ihom_term_⟶[_]__1»
code: /-- `A ⟶[C] B` denotes the internal hom from `A` to `B` -/
notation A " ⟶[" C "] " B:10 => (@ihom C _ _ A _).obj B
goal: Lean.Macro

full_name: CategoryTheory.ihom.ev_coev
code: @[reassoc (attr := simp)]
theorem ev_coev : (A ◁ (coev A).app B) ≫ (ev A).app (A ⊗ B) = 𝟙 (A ⊗ B) 
goal: CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerLeft A ((CategoryTheory.ihom.coev A).app B))
    ((CategoryTheory.ihom.ev A).app (CategoryTheory.MonoidalCategory.tensorObj A B)) =
  CategoryTheory.CategoryStruct.id (CategoryTheory.MonoidalCategory.tensorObj A B)

full_name: CategoryTheory.ihom.coev_ev
code: @[reassoc (attr := simp)]
theorem coev_ev : (coev A).app (A ⟶[C] B) ≫ (ihom A).map ((ev A).app B) = 𝟙 (A ⟶[C] B) 
goal: CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.coev A).app ((CategoryTheory.ihom A).obj B))
    ((CategoryTheory.ihom A).map ((CategoryTheory.ihom.ev A).app B)) =
  CategoryTheory.CategoryStruct.id ((CategoryTheory.ihom A).obj B)

full_name: CategoryTheory.instPreservesColimitsTensorLeft
code: instance : PreservesColimits (tensorLeft A) 
goal: CategoryTheory.Limits.PreservesColimits (CategoryTheory.MonoidalCategory.tensorLeft A)

full_name: CategoryTheory.MonoidalClosed.curry
code: /-- Currying in a monoidal closed category. -/
def curry : (A ⊗ Y ⟶ X) → (Y ⟶ A ⟶[C] X) 
goal: (CategoryTheory.MonoidalCategory.tensorObj A Y ⟶ X) → (Y ⟶ (CategoryTheory.ihom A).obj X)

full_name: CategoryTheory.MonoidalClosed.uncurry
code: /-- Uncurrying in a monoidal closed category. -/
def uncurry : (Y ⟶ A ⟶[C] X) → (A ⊗ Y ⟶ X) 
goal: (Y ⟶ (CategoryTheory.ihom A).obj X) → (CategoryTheory.MonoidalCategory.tensorObj A Y ⟶ X)

full_name: CategoryTheory.MonoidalClosed.homEquiv_apply_eq
code: @[simp, nolint simpNF]
theorem homEquiv_apply_eq (f : A ⊗ Y ⟶ X) : (ihom.adjunction A).homEquiv _ _ f = curry f 
goal: ((CategoryTheory.ihom.adjunction A).homEquiv Y X) f = CategoryTheory.MonoidalClosed.curry f

full_name: CategoryTheory.MonoidalClosed.homEquiv_symm_apply_eq
code: @[simp, nolint simpNF]
theorem homEquiv_symm_apply_eq (f : Y ⟶ A ⟶[C] X) :
    ((ihom.adjunction A).homEquiv _ _).symm f = uncurry f 
goal: ((CategoryTheory.ihom.adjunction A).homEquiv Y X).symm f = CategoryTheory.MonoidalClosed.uncurry f

full_name: CategoryTheory.MonoidalClosed.curry_natural_left
code: @[reassoc]
theorem curry_natural_left (f : X ⟶ X') (g : A ⊗ X' ⟶ Y) : curry (_ ◁ f ≫ g) = f ≫ curry g 
goal: CategoryTheory.MonoidalClosed.curry
    (CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerLeft A f) g) =
  CategoryTheory.CategoryStruct.comp f (CategoryTheory.MonoidalClosed.curry g)

full_name: CategoryTheory.MonoidalClosed.curry_natural_right
code: @[reassoc]
theorem curry_natural_right (f : A ⊗ X ⟶ Y) (g : Y ⟶ Y') :
    curry (f ≫ g) = curry f ≫ (ihom _).map g 
goal: CategoryTheory.MonoidalClosed.curry (CategoryTheory.CategoryStruct.comp f g) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalClosed.curry f) ((CategoryTheory.ihom A).map g)

full_name: CategoryTheory.MonoidalClosed.uncurry_natural_right
code: @[reassoc]
theorem uncurry_natural_right (f : X ⟶ A ⟶[C] Y) (g : Y ⟶ Y') :
    uncurry (f ≫ (ihom _).map g) = uncurry f ≫ g 
goal: CategoryTheory.MonoidalClosed.uncurry (CategoryTheory.CategoryStruct.comp f ((CategoryTheory.ihom A).map g)) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalClosed.uncurry f) g

full_name: CategoryTheory.MonoidalClosed.uncurry_natural_left
code: @[reassoc]
theorem uncurry_natural_left (f : X ⟶ X') (g : X' ⟶ A ⟶[C] Y) :
    uncurry (f ≫ g) = _ ◁ f ≫ uncurry g 
goal: CategoryTheory.MonoidalClosed.uncurry (CategoryTheory.CategoryStruct.comp f g) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerLeft A f)
    (CategoryTheory.MonoidalClosed.uncurry g)

full_name: CategoryTheory.MonoidalClosed.uncurry_curry
code: @[simp]
theorem uncurry_curry (f : A ⊗ X ⟶ Y) : uncurry (curry f) = f 
goal: CategoryTheory.MonoidalClosed.uncurry (CategoryTheory.MonoidalClosed.curry f) = f

full_name: CategoryTheory.MonoidalClosed.curry_uncurry
code: @[simp]
theorem curry_uncurry (f : X ⟶ A ⟶[C] Y) : curry (uncurry f) = f 
goal: CategoryTheory.MonoidalClosed.curry (CategoryTheory.MonoidalClosed.uncurry f) = f

full_name: CategoryTheory.MonoidalClosed.curry_eq_iff
code: theorem curry_eq_iff (f : A ⊗ Y ⟶ X) (g : Y ⟶ A ⟶[C] X) : curry f = g ↔ f = uncurry g 
goal: CategoryTheory.MonoidalClosed.curry f = g ↔ f = CategoryTheory.MonoidalClosed.uncurry g

full_name: CategoryTheory.MonoidalClosed.eq_curry_iff
code: theorem eq_curry_iff (f : A ⊗ Y ⟶ X) (g : Y ⟶ A ⟶[C] X) : g = curry f ↔ uncurry g = f 
goal: g = CategoryTheory.MonoidalClosed.curry f ↔ CategoryTheory.MonoidalClosed.uncurry g = f

full_name: CategoryTheory.MonoidalClosed.uncurry_eq
code: theorem uncurry_eq (g : Y ⟶ A ⟶[C] X) : uncurry g = (A ◁ g) ≫ (ihom.ev A).app X 
goal: CategoryTheory.MonoidalClosed.uncurry g =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerLeft A g)
    ((CategoryTheory.ihom.ev A).app X)

full_name: CategoryTheory.MonoidalClosed.curry_eq
code: theorem curry_eq (g : A ⊗ Y ⟶ X) : curry g = (ihom.coev A).app Y ≫ (ihom A).map g 
goal: CategoryTheory.MonoidalClosed.curry g =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.coev A).app Y) ((CategoryTheory.ihom A).map g)

full_name: CategoryTheory.MonoidalClosed.curry_injective
code: theorem curry_injective : Function.Injective (curry : (A ⊗ Y ⟶ X) → (Y ⟶ A ⟶[C] X)) 
goal: Function.Injective CategoryTheory.MonoidalClosed.curry

full_name: CategoryTheory.MonoidalClosed.uncurry_injective
code: theorem uncurry_injective : Function.Injective (uncurry : (Y ⟶ A ⟶[C] X) → (A ⊗ Y ⟶ X)) 
goal: Function.Injective CategoryTheory.MonoidalClosed.uncurry

full_name: CategoryTheory.MonoidalClosed.uncurry_id_eq_ev
code: theorem uncurry_id_eq_ev : uncurry (𝟙 (A ⟶[C] X)) = (ihom.ev A).app X 
goal: CategoryTheory.MonoidalClosed.uncurry (CategoryTheory.CategoryStruct.id ((CategoryTheory.ihom A).obj X)) =
  (CategoryTheory.ihom.ev A).app X

full_name: CategoryTheory.MonoidalClosed.curry_id_eq_coev
code: theorem curry_id_eq_coev : curry (𝟙 _) = (ihom.coev A).app X 
goal: CategoryTheory.MonoidalClosed.curry
    (CategoryTheory.CategoryStruct.id
      (CategoryTheory.MonoidalCategory.tensorObj A ((CategoryTheory.Functor.id C).obj X))) =
  (CategoryTheory.ihom.coev A).app X

full_name: CategoryTheory.MonoidalClosed.pre
code: /-- Pre-compose an internal hom with an external hom. -/
def pre (f : B ⟶ A) : ihom A ⟶ ihom B 
goal: CategoryTheory.ihom A ⟶ CategoryTheory.ihom B

full_name: CategoryTheory.MonoidalClosed.id_tensor_pre_app_comp_ev
code: @[reassoc (attr := simp)]
theorem id_tensor_pre_app_comp_ev (f : B ⟶ A) (X : C) :
    B ◁ (pre f).app X ≫ (ihom.ev B).app X = f ▷ (A ⟶[C] X) ≫ (ihom.ev A).app X 
goal: CategoryTheory.CategoryStruct.comp
    (CategoryTheory.MonoidalCategory.whiskerLeft B ((CategoryTheory.MonoidalClosed.pre f).app X))
    ((CategoryTheory.ihom.ev B).app X) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerRight f ((CategoryTheory.ihom A).obj X))
    ((CategoryTheory.ihom.ev A).app X)

full_name: CategoryTheory.MonoidalClosed.uncurry_pre
code: @[simp]
theorem uncurry_pre (f : B ⟶ A) (X : C) :
    MonoidalClosed.uncurry ((pre f).app X) = f ▷ _ ≫ (ihom.ev A).app X 
goal: CategoryTheory.MonoidalClosed.uncurry ((CategoryTheory.MonoidalClosed.pre f).app X) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalCategory.whiskerRight f ((CategoryTheory.ihom A).obj X))
    ((CategoryTheory.ihom.ev A).app X)

full_name: CategoryTheory.MonoidalClosed.coev_app_comp_pre_app
code: @[reassoc (attr := simp)]
theorem coev_app_comp_pre_app (f : B ⟶ A) :
    (ihom.coev A).app X ≫ (pre f).app (A ⊗ X) = (ihom.coev B).app X ≫ (ihom B).map (f ▷ _) 
goal: CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.coev A).app X)
    ((CategoryTheory.MonoidalClosed.pre f).app (CategoryTheory.MonoidalCategory.tensorObj A X)) =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom.coev B).app X)
    ((CategoryTheory.ihom B).map (CategoryTheory.MonoidalCategory.whiskerRight f X))

full_name: CategoryTheory.MonoidalClosed.pre_id
code: @[simp]
theorem pre_id (A : C) [Closed A] : pre (𝟙 A) = 𝟙 _ 
goal: CategoryTheory.MonoidalClosed.pre (CategoryTheory.CategoryStruct.id A) =
  CategoryTheory.CategoryStruct.id (CategoryTheory.ihom A)

full_name: CategoryTheory.MonoidalClosed.pre_map
code: @[simp]
theorem pre_map {A₁ A₂ A₃ : C} [Closed A₁] [Closed A₂] [Closed A₃] (f : A₁ ⟶ A₂) (g : A₂ ⟶ A₃) :
    pre (f ≫ g) = pre g ≫ pre f 
goal: CategoryTheory.MonoidalClosed.pre (CategoryTheory.CategoryStruct.comp f g) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.MonoidalClosed.pre g) (CategoryTheory.MonoidalClosed.pre f)

full_name: CategoryTheory.MonoidalClosed.pre_comm_ihom_map
code: theorem pre_comm_ihom_map {W X Y Z : C} [Closed W] [Closed X] (f : W ⟶ X) (g : Y ⟶ Z) :
    (pre f).app Y ≫ (ihom W).map g = (ihom X).map g ≫ (pre f).app Z 
goal: CategoryTheory.CategoryStruct.comp ((CategoryTheory.MonoidalClosed.pre f).app Y) ((CategoryTheory.ihom W).map g) =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.ihom X).map g) ((CategoryTheory.MonoidalClosed.pre f).app Z)

full_name: CategoryTheory.MonoidalClosed.internalHom
code: /-- The internal hom functor given by the monoidal closed structure. -/
@[simps]
def internalHom [MonoidalClosed C] : Cᵒᵖ ⥤ C ⥤ C 
goal: CategoryTheory.Functor Cᵒᵖ (CategoryTheory.Functor C C)

full_name: CategoryTheory.MonoidalClosed.internalHom_map
code: /-- The internal hom functor given by the monoidal closed structure. -/
@[simps]
def internalHom [MonoidalClosed C] : Cᵒᵖ ⥤ C ⥤ C 
goal: ∀ {X Y : Cᵒᵖ} (f : X ⟶ Y), CategoryTheory.MonoidalClosed.internalHom.map f = CategoryTheory.MonoidalClosed.pre f.unop

full_name: CategoryTheory.MonoidalClosed.internalHom_obj
code: /-- The internal hom functor given by the monoidal closed structure. -/
@[simps]
def internalHom [MonoidalClosed C] : Cᵒᵖ ⥤ C ⥤ C 
goal: CategoryTheory.MonoidalClosed.internalHom.obj X = CategoryTheory.ihom (Opposite.unop X)

full_name: CategoryTheory.MonoidalClosed.ofEquiv
code: /-- Transport the property of being monoidal closed across a monoidal equivalence of categories -/
noncomputable def ofEquiv : MonoidalClosed C 
goal: CategoryTheory.MonoidalClosed C

full_name: CategoryTheory.MonoidalClosed.ofEquiv_curry_def
code: /-- Suppose we have a monoidal equivalence `F : C ≌ D`, with `D` monoidal closed. We can pull the
monoidal closed instance back along the equivalence. For `X, Y, Z : C`, this lemma describes the
resulting currying map `Hom(X ⊗ Y, Z) → Hom(Y, (X ⟶[C] Z))`. (`X ⟶[C] Z` is defined to be
`F⁻¹(F(X) ⟶[D] F(Z))`, so currying in `C` is given by essentially conjugating currying in
`D` by `F.`) -/
theorem ofEquiv_curry_def {X Y Z : C} (f : X ⊗ Y ⟶ Z) :
    letI := ofEquiv F adj
    MonoidalClosed.curry f =
      adj.homEquiv Y ((ihom (F.obj X)).obj (F.obj Z))
        (MonoidalClosed.curry (adj.toEquivalence.symm.toAdjunction.homEquiv (F.obj X ⊗ F.obj Y) Z
        ((Iso.compInverseIso (H := adj.toEquivalence)
          (MonoidalFunctor.commTensorLeft F X)).hom.app Y ≫ f))) 
goal: CategoryTheory.MonoidalClosed.curry f =
  (adj.homEquiv Y ((CategoryTheory.ihom (F.obj X)).obj (F.obj Z)))
    (CategoryTheory.MonoidalClosed.curry
      ((adj.toEquivalence.symm.toAdjunction.homEquiv (CategoryTheory.MonoidalCategory.tensorObj (F.obj X) (F.obj Y)) Z)
        (CategoryTheory.CategoryStruct.comp ((F.commTensorLeft X).compInverseIso.hom.app Y) f)))

full_name: CategoryTheory.MonoidalClosed.ofEquiv_uncurry_def
code: /-- Suppose we have a monoidal equivalence `F : C ≌ D`, with `D` monoidal closed. We can pull the
monoidal closed instance back along the equivalence. For `X, Y, Z : C`, this lemma describes the
resulting uncurrying map `Hom(Y, (X ⟶[C] Z)) → Hom(X ⊗ Y ⟶ Z)`. (`X ⟶[C] Z` is
defined to be `F⁻¹(F(X) ⟶[D] F(Z))`, so uncurrying in `C` is given by essentially conjugating
uncurrying in `D` by `F.`) -/
theorem ofEquiv_uncurry_def {X Y Z : C} :
    letI := ofEquiv F adj
    ∀ (f : Y ⟶ (ihom X).obj Z), MonoidalClosed.uncurry f =
      ((Iso.compInverseIso (H := adj.toEquivalence)
          (MonoidalFunctor.commTensorLeft F X)).inv.app Y) ≫
            (adj.toEquivalence.symm.toAdjunction.homEquiv _ _).symm
              (MonoidalClosed.uncurry ((adj.homEquiv _ _).symm f)) 
goal: CategoryTheory.MonoidalClosed.uncurry f =
  CategoryTheory.CategoryStruct.comp ((F.commTensorLeft X).compInverseIso.inv.app Y)
    ((adj.toEquivalence.symm.toAdjunction.homEquiv
          ((F.comp (CategoryTheory.MonoidalCategory.tensorLeft (F.obj X))).obj Y) Z).symm
      (CategoryTheory.MonoidalClosed.uncurry
        ((adj.homEquiv Y ((CategoryTheory.ihom (F.obj X)).obj (adj.toEquivalence.symm.inverse.obj Z))).symm f)))