Local Open Scope morphism_scope.
(** Given two objects a and b the exponential (bᵃ, denoted 'Exponential a b' below) is intuitively the internal representation of homomorphisms from a to b – it is sometimes referred to as the internal hom. The notion of exponential is a generalization of the notion function space from set theory.  Definition: bᵃ is an object equipped with an evaluation function eval: bᵃ×a -> b such that for any other object z with arrow f : z×a -> b, we have a unique arrow f^ that makes the following diagram commute:  # <pre> eval bᵃ×a ——————————> b ↑             ↗ bᵃ     |            / ↑      | <f^,idₐ>  / |      |          / |∃!f̂ ^  |         / |      |        / f z      |       / |      / |     / |    / |   / |  / z×a </pre> # where <f, g> is the arrow map of the product functor. *)
Record Exponential {C : Category} {HP : Has_Products C} (c d : Obj) : Type :=
{
exponential : C;
eval : ((×ᶠⁿᶜ C) _o (exponential, c))%object –≻ d;
Exp_morph_ex : ∀ (z : C), (((×ᶠⁿᶜ C) _o (z, c))%object –≻ d) → (z –≻ exponential);
Exp_morph_com : ∀ (z : C) (f : ((×ᶠⁿᶜ C) _o (z, c))%object –≻ d),
f = (eval ∘ ((×ᶠⁿᶜ C) @_a (_, _) (_, _) (Exp_morph_ex z f, id c)))%morphism;
Exp_morph_unique : ∀ (z : C) (f : ((×ᶠⁿᶜ C) _o (z, c))%object –≻ d)
(u u' : z –≻ exponential),
f = (eval ∘ ((×ᶠⁿᶜ C) @_a (_, _) (_, _) (u, id c)))%morphism →
f = (eval ∘ ((×ᶠⁿᶜ C) @_a (_, _) (_, _) (u', id c)))%morphism →
u = u'
}.
Coercion exponential : Exponential >-> Obj.
Arguments Exponential _ {_} _ _, {_ _} _ _.
Arguments exponential {_ _ _ _} _, {_ _} _ _ {_}.
Arguments eval {_ _ _ _} _, {_ _} _ _ {_}.
Arguments Exp_morph_ex {_ _ _ _} _ _ _, {_ _} _ _ {_} _ _.
Arguments Exp_morph_com {_ _ _ _} _ _ _, {_ _} _ _ {_} _ _.
Arguments Exp_morph_unique {_ _ _ _} _ _ _ _ _ _ _, {_ _} _ _ {_} _ _ _ _ _ _.
Notation "a ⇑ b" := (Exponential a b) : object_scope.

(** Exponentials are unique up to isomorphism. *)
Theorem Exponential_iso {C : Category} {HP : Has_Products C} (c d : C)
(E E' : (c ⇑ d)%object) : (E ≃ E')%isomorphism.