File: Mathlib/CategoryTheory/Closed/Cartesian.lean

full_name: CategoryTheory.Exponentiable
code: /-- An object `X` is *exponentiable* if `(X × -)` is a left adjoint.
We define this as being `Closed` in the cartesian monoidal structure.
-/
abbrev Exponentiable {C : Type u} [Category.{v} C] [HasFiniteProducts C] (X : C) 
goal: Type (max u v)

full_name: CategoryTheory.Exponentiable.mk
code: /-- Constructor for `Exponentiable X` which takes as an input an adjunction
`MonoidalCategory.tensorLeft X ⊣ exp` for some functor `exp : C ⥤ C`. -/
abbrev Exponentiable.mk {C : Type u} [Category.{v} C] [HasFiniteProducts C] (X : C)
    (exp : C ⥤ C) (adj : MonoidalCategory.tensorLeft X ⊣ exp) :
    Exponentiable X 
goal: CategoryTheory.Exponentiable X

full_name: CategoryTheory.binaryProductExponentiable
code: /-- If `X` and `Y` are exponentiable then `X ⨯ Y` is.
This isn't an instance because it's not usually how we want to construct exponentials, we'll usually
prove all objects are exponential uniformly.
-/
def binaryProductExponentiable {C : Type u} [Category.{v} C] [HasFiniteProducts C] {X Y : C}
    (hX : Exponentiable X) (hY : Exponentiable Y) : Exponentiable (X ⨯ Y) 
goal: CategoryTheory.Exponentiable (X ⨯ Y)

full_name: CategoryTheory.terminalExponentiable
code: /-- The terminal object is always exponentiable.
This isn't an instance because most of the time we'll prove cartesian closed for all objects
at once, rather than just for this one.
-/
def terminalExponentiable {C : Type u} [Category.{v} C] [HasFiniteProducts C] :
    Exponentiable (⊤_ C) 
goal: CategoryTheory.Exponentiable (⊤_ C)

full_name: CategoryTheory.CartesianClosed
code: /-- A category `C` is cartesian closed if it has finite products and every object is exponentiable.
We define this as `monoidal_closed` with respect to the cartesian monoidal structure.
-/
abbrev CartesianClosed (C : Type u) [Category.{v} C] [HasFiniteProducts C] 
goal: Type (max u v)

full_name: CategoryTheory.CartesianClosed.mk
code: /-- Constructor for `CartesianClosed C`. -/
def CartesianClosed.mk (C : Type u) [Category.{v} C] [HasFiniteProducts C]
    (exp : ∀ (X : C), Exponentiable X) :
    CartesianClosed C 
goal: CategoryTheory.CartesianClosed C

full_name: CategoryTheory.exp
code: /-- This is (-)^A. -/
abbrev exp : C ⥤ C 
goal: CategoryTheory.Functor C C

full_name: CategoryTheory.exp.adjunction
code: /-- The adjunction between A ⨯ - and (-)^A. -/
abbrev adjunction : prod.functor.obj A ⊣ exp A 
goal: CategoryTheory.Limits.prod.functor.obj A ⊣ CategoryTheory.exp A

full_name: CategoryTheory.exp.ev
code: /-- The evaluation natural transformation. -/
abbrev ev : exp A ⋙ prod.functor.obj A ⟶ 𝟭 C 
goal: (CategoryTheory.exp A).comp (CategoryTheory.Limits.prod.functor.obj A) ⟶ CategoryTheory.Functor.id C

full_name: CategoryTheory.exp.coev
code: /-- The coevaluation natural transformation. -/
abbrev coev : 𝟭 C ⟶ prod.functor.obj A ⋙ exp A 
goal: CategoryTheory.Functor.id C ⟶ (CategoryTheory.Limits.prod.functor.obj A).comp (CategoryTheory.exp A)

full_name: CategoryTheory.exp.«_aux_Mathlib_CategoryTheory_Closed_Cartesian___macroRules_CategoryTheory_exp_term_⟹__1»
code: /-- Morphisms obtained using an exponentiable object. -/
notation:20 A " ⟹ " B:19 => (exp A).obj B
goal: Lean.Macro

full_name: CategoryTheory.exp.delabPrefunctorObjExp
code: /-- Delaborator for `Prefunctor.obj` -/
@[delab app.Prefunctor.obj]
def delabPrefunctorObjExp : Delab 
goal: Lean.PrettyPrinter.Delaborator.Delab

full_name: CategoryTheory.exp.«_aux_Mathlib_CategoryTheory_Closed_Cartesian___macroRules_CategoryTheory_exp_term_^^__1»
code: /-- Morphisms from an exponentiable object. -/
notation:30 B " ^^ " A:30 => (exp A).obj B
goal: Lean.Macro

full_name: CategoryTheory.exp.ev_coev
code: @[simp, reassoc]
theorem ev_coev : Limits.prod.map (𝟙 A) ((coev A).app B) ≫ (ev A).app (A ⨯ B) = 𝟙 (A ⨯ B) 
goal: CategoryTheory.CategoryStruct.comp
    (CategoryTheory.Limits.prod.map (CategoryTheory.CategoryStruct.id A) ((CategoryTheory.exp.coev A).app B))
    ((CategoryTheory.exp.ev A).app (A ⨯ B)) =
  CategoryTheory.CategoryStruct.id (A ⨯ B)

full_name: CategoryTheory.exp.coev_ev
code: @[reassoc]
theorem coev_ev : (coev A).app (A ⟹ B) ≫ (exp A).map ((ev A).app B) = 𝟙 (A ⟹ B) 
goal: CategoryTheory.CategoryStruct.comp ((CategoryTheory.exp.coev A).app (A ⟹ B))
    ((CategoryTheory.exp A).map ((CategoryTheory.exp.ev A).app B)) =
  CategoryTheory.CategoryStruct.id (A ⟹ B)

full_name: CategoryTheory.instPreservesColimitsObjFunctorFunctor
code: instance : PreservesColimits (prod.functor.obj A) 
goal: CategoryTheory.Limits.PreservesColimits (CategoryTheory.Limits.prod.functor.obj A)

full_name: CategoryTheory.CartesianClosed.curry
code: /-- Currying in a cartesian closed category. -/
def curry : (A ⨯ Y ⟶ X) → (Y ⟶ A ⟹ X) 
goal: (A ⨯ Y ⟶ X) → (Y ⟶ A ⟹ X)

full_name: CategoryTheory.CartesianClosed.uncurry
code: /-- Uncurrying in a cartesian closed category. -/
def uncurry : (Y ⟶ A ⟹ X) → (A ⨯ Y ⟶ X) 
goal: (Y ⟶ A ⟹ X) → (A ⨯ Y ⟶ X)

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

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

full_name: CategoryTheory.CartesianClosed.curry_natural_left
code: @[reassoc]
theorem curry_natural_left (f : X ⟶ X') (g : A ⨯ X' ⟶ Y) :
    curry (Limits.prod.map (𝟙 _) f ≫ g) = f ≫ curry g 
goal: CategoryTheory.CartesianClosed.curry
    (CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.prod.map (CategoryTheory.CategoryStruct.id A) f) g) =
  CategoryTheory.CategoryStruct.comp f (CategoryTheory.CartesianClosed.curry g)

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

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

full_name: CategoryTheory.CartesianClosed.uncurry_natural_left
code: @[reassoc]
theorem uncurry_natural_left (f : X ⟶ X') (g : X' ⟶ A ⟹ Y) :
    uncurry (f ≫ g) = Limits.prod.map (𝟙 _) f ≫ uncurry g 
goal: CategoryTheory.CartesianClosed.uncurry (CategoryTheory.CategoryStruct.comp f g) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.prod.map (CategoryTheory.CategoryStruct.id A) f)
    (CategoryTheory.CartesianClosed.uncurry g)

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

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

full_name: CategoryTheory.CartesianClosed.curry_eq_iff
code: theorem curry_eq_iff (f : A ⨯ Y ⟶ X) (g : Y ⟶ A ⟹ X) : curry f = g ↔ f = uncurry g 
goal: CategoryTheory.CartesianClosed.curry f = g ↔ f = CategoryTheory.CartesianClosed.uncurry g

full_name: CategoryTheory.CartesianClosed.eq_curry_iff
code: theorem eq_curry_iff (f : A ⨯ Y ⟶ X) (g : Y ⟶ A ⟹ X) : g = curry f ↔ uncurry g = f 
goal: g = CategoryTheory.CartesianClosed.curry f ↔ CategoryTheory.CartesianClosed.uncurry g = f

full_name: CategoryTheory.CartesianClosed.uncurry_eq
code: theorem uncurry_eq (g : Y ⟶ A ⟹ X) : uncurry g = Limits.prod.map (𝟙 A) g ≫ (exp.ev A).app X 
goal: CategoryTheory.CartesianClosed.uncurry g =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.prod.map (CategoryTheory.CategoryStruct.id A) g)
    ((CategoryTheory.exp.ev A).app X)

full_name: CategoryTheory.CartesianClosed.curry_eq
code: theorem curry_eq (g : A ⨯ Y ⟶ X) : curry g = (exp.coev A).app Y ≫ (exp A).map g 
goal: CategoryTheory.CartesianClosed.curry g =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.exp.coev A).app Y) ((CategoryTheory.exp A).map g)

full_name: CategoryTheory.CartesianClosed.uncurry_id_eq_ev
code: theorem uncurry_id_eq_ev (A X : C) [Exponentiable A] : uncurry (𝟙 (A ⟹ X)) = (exp.ev A).app X 
goal: CategoryTheory.CartesianClosed.uncurry (CategoryTheory.CategoryStruct.id (A ⟹ X)) = (CategoryTheory.exp.ev A).app X

full_name: CategoryTheory.CartesianClosed.curry_id_eq_coev
code: theorem curry_id_eq_coev (A X : C) [Exponentiable A] : curry (𝟙 _) = (exp.coev A).app X 
goal: CategoryTheory.CartesianClosed.curry (CategoryTheory.CategoryStruct.id (A ⨯ (CategoryTheory.Functor.id C).obj X)) =
  (CategoryTheory.exp.coev A).app X

full_name: CategoryTheory.CartesianClosed.curry_injective
code: theorem curry_injective : Function.Injective (curry : (A ⨯ Y ⟶ X) → (Y ⟶ A ⟹ X)) 
goal: Function.Injective CategoryTheory.CartesianClosed.curry

full_name: CategoryTheory.CartesianClosed.uncurry_injective
code: theorem uncurry_injective : Function.Injective (uncurry : (Y ⟶ A ⟹ X) → (A ⨯ Y ⟶ X)) 
goal: Function.Injective CategoryTheory.CartesianClosed.uncurry

full_name: CategoryTheory.expTerminalIsoSelf
code: /-- Show that the exponential of the terminal object is isomorphic to itself, i.e. `X^1 ≅ X`.

The typeclass argument is explicit: any instance can be used.
-/
def expTerminalIsoSelf [Exponentiable (⊤_ C)] : (⊤_ C) ⟹ X ≅ X 
goal: (⊤_ C) ⟹ X ≅ X

full_name: CategoryTheory.internalizeHom
code: /-- The internal element which points at the given morphism. -/
def internalizeHom (f : A ⟶ Y) : ⊤_ C ⟶ A ⟹ Y 
goal: ⊤_ C ⟶ A ⟹ Y

full_name: CategoryTheory.pre
code: /-- Pre-compose an internal hom with an external hom. -/
def pre (f : B ⟶ A) [Exponentiable B] : exp A ⟶ exp B 
goal: CategoryTheory.exp A ⟶ CategoryTheory.exp B

full_name: CategoryTheory.prod_map_pre_app_comp_ev
code: theorem prod_map_pre_app_comp_ev (f : B ⟶ A) [Exponentiable B] (X : C) :
    Limits.prod.map (𝟙 B) ((pre f).app X) ≫ (exp.ev B).app X =
      Limits.prod.map f (𝟙 (A ⟹ X)) ≫ (exp.ev A).app X 
goal: CategoryTheory.CategoryStruct.comp
    (CategoryTheory.Limits.prod.map (CategoryTheory.CategoryStruct.id B) ((CategoryTheory.pre f).app X))
    ((CategoryTheory.exp.ev B).app X) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.prod.map f (CategoryTheory.CategoryStruct.id (A ⟹ X)))
    ((CategoryTheory.exp.ev A).app X)

full_name: CategoryTheory.uncurry_pre
code: theorem uncurry_pre (f : B ⟶ A) [Exponentiable B] (X : C) :
    CartesianClosed.uncurry ((pre f).app X) = Limits.prod.map f (𝟙 _) ≫ (exp.ev A).app X 
goal: CategoryTheory.CartesianClosed.uncurry ((CategoryTheory.pre f).app X) =
  CategoryTheory.CategoryStruct.comp (CategoryTheory.Limits.prod.map f (CategoryTheory.CategoryStruct.id (A ⟹ X)))
    ((CategoryTheory.exp.ev A).app X)

full_name: CategoryTheory.coev_app_comp_pre_app
code: theorem coev_app_comp_pre_app (f : B ⟶ A) [Exponentiable B] :
    (exp.coev A).app X ≫ (pre f).app (A ⨯ X) =
      (exp.coev B).app X ≫ (exp B).map (Limits.prod.map f (𝟙 _)) 
goal: CategoryTheory.CategoryStruct.comp ((CategoryTheory.exp.coev A).app X) ((CategoryTheory.pre f).app (A ⨯ X)) =
  CategoryTheory.CategoryStruct.comp ((CategoryTheory.exp.coev B).app X)
    ((CategoryTheory.exp B).map (CategoryTheory.Limits.prod.map f (CategoryTheory.CategoryStruct.id X)))

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

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

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

full_name: CategoryTheory.zeroMul_inv
code: /-- If an initial object `I` exists in a CCC, then `A ⨯ I ≅ I`. -/
@[simps]
def zeroMul {I : C} (t : IsInitial I) : A ⨯ I ≅ I 
goal: (CategoryTheory.zeroMul t).inv = t.to (A ⨯ I)

full_name: CategoryTheory.zeroMul
code: /-- If an initial object `I` exists in a CCC, then `A ⨯ I ≅ I`. -/
@[simps]
def zeroMul {I : C} (t : IsInitial I) : A ⨯ I ≅ I 
goal: A ⨯ I ≅ I

full_name: CategoryTheory.zeroMul_hom
code: /-- If an initial object `I` exists in a CCC, then `A ⨯ I ≅ I`. -/
@[simps]
def zeroMul {I : C} (t : IsInitial I) : A ⨯ I ≅ I 
goal: (CategoryTheory.zeroMul t).hom = CategoryTheory.Limits.prod.snd

full_name: CategoryTheory.mulZero
code: /-- If an initial object `0` exists in a CCC, then `0 ⨯ A ≅ 0`. -/
def mulZero {I : C} (t : IsInitial I) : I ⨯ A ≅ I 
goal: I ⨯ A ≅ I

full_name: CategoryTheory.powZero
code: /-- If an initial object `0` exists in a CCC then `0^B ≅ 1` for any `B`. -/
def powZero {I : C} (t : IsInitial I) [CartesianClosed C] : I ⟹ B ≅ ⊤_ C 
goal: I ⟹ B ≅ ⊤_ C

full_name: CategoryTheory.prodCoprodDistrib
code: /-- In a CCC with binary coproducts, the distribution morphism is an isomorphism. -/
def prodCoprodDistrib [HasBinaryCoproducts C] [CartesianClosed C] (X Y Z : C) :
    (Z ⨯ X) ⨿ Z ⨯ Y ≅ Z ⨯ X ⨿ Y 
goal: (Z ⨯ X) ⨿ Z ⨯ Y ≅ Z ⨯ X ⨿ Y

full_name: CategoryTheory.strict_initial
code: /-- If an initial object `I` exists in a CCC then it is a strict initial object,
i.e. any morphism to `I` is an iso.
This actually shows a slightly stronger version: any morphism to an initial object from an
exponentiable object is an isomorphism.
-/
theorem strict_initial {I : C} (t : IsInitial I) (f : A ⟶ I) : IsIso f 
goal: CategoryTheory.IsIso f

full_name: CategoryTheory.to_initial_isIso
code: instance to_initial_isIso [HasInitial C] (f : A ⟶ ⊥_ C) : IsIso f 
goal: CategoryTheory.IsIso f

full_name: CategoryTheory.initial_mono
code: /-- If an initial object `0` exists in a CCC then every morphism from it is monic. -/
theorem initial_mono {I : C} (B : C) (t : IsInitial I) [CartesianClosed C] : Mono (t.to B) 
goal: CategoryTheory.Mono (t.to B)

full_name: CategoryTheory.Initial.mono_to
code: instance Initial.mono_to [HasInitial C] (B : C) [CartesianClosed C] : Mono (initial.to B) 
goal: CategoryTheory.Mono (CategoryTheory.Limits.initial.to B)

full_name: CategoryTheory.cartesianClosedOfEquiv
code: /-- Transport the property of being cartesian closed across an equivalence of categories.

Note we didn't require any coherence between the choice of finite products here, since we transport
along the `prodComparison` isomorphism.
-/
def cartesianClosedOfEquiv (e : C ≌ D) [CartesianClosed C] : CartesianClosed D 
goal: CategoryTheory.CartesianClosed D