# The universal properties of cartesian product types

```agda
module foundation.universal-property-cartesian-product-types where
```

<details><summary>Imports</summary>

```agda
open import foundation.cones-over-cospan-diagrams
open import foundation.dependent-pair-types
open import foundation.logical-equivalences
open import foundation.standard-pullbacks
open import foundation.unit-type
open import foundation.universal-property-dependent-pair-types
open import foundation.universe-levels

open import foundation-core.cartesian-product-types
open import foundation-core.contractible-types
open import foundation-core.equivalences
open import foundation-core.function-types
open import foundation-core.homotopies
open import foundation-core.identity-types
open import foundation-core.pullbacks
open import foundation-core.retractions
open import foundation-core.sections
open import foundation-core.universal-property-pullbacks
```

</details>

## Idea

[Cartesian products](foundation-core.cartesian-product-types.md) have universal
properties both as limits and as colimits of types. The
{{#concept "universal property of cartesian products as limits"}} states that,
given types `A`, `B` and `X`, maps _into_ the cartesian product `X → A × B` are
in [correspondence](foundation-core.equivalences.md) with pairs of maps `X → A`
and `X → B`. The
{{#concept "universal property of cartesian products as colimits"}} states that
maps _out of_ the cartesian product `A × B → X` are in correspondence with
"curried" maps `A → B → X`.

Observe that the universal property of cartesian products as limits can be
understood as a categorified version of the familiar distributivity of exponents
over products

$$
(A × B)^X ≃ A^X × B^X,
$$

while the universal property of cartesian products as colimits are a
categorified version of the identity

$$
X^{(A × B)} ≃ {(X^B)}^A.
$$

## Theorems

### The universal property of cartesian products as limits

```agda
module _
  {l1 l2 l3 : Level} {X : UU l1} {A : X  UU l2} {B : X  UU l3}
  where

  map-up-product :
    ((x : X)  A x × B x)  ((x : X)  A x) × ((x : X)  B x)
  pr1 (map-up-product f) x = pr1 (f x)
  pr2 (map-up-product f) x = pr2 (f x)

  map-inv-up-product :
    (((x : X)  A x) × ((x : X)  B x))  (x : X)  A x × B x
  pr1 (map-inv-up-product (f , g) x) = f x
  pr2 (map-inv-up-product (f , g) x) = g x

  iff-up-product :
    ((x : X)  A x × B x)  ((x : X)  A x) × ((x : X)  B x)
  iff-up-product = (map-up-product , map-inv-up-product)

  up-product : is-equiv map-up-product
  up-product =
    is-equiv-is-invertible (map-inv-up-product) (refl-htpy) (refl-htpy)

  is-equiv-map-inv-up-product : is-equiv map-inv-up-product
  is-equiv-map-inv-up-product = is-equiv-map-inv-is-equiv up-product

  equiv-up-product :
    ((x : X)  A x × B x)  (((x : X)  A x) × ((x : X)  B x))
  pr1 equiv-up-product = map-up-product
  pr2 equiv-up-product = up-product

  inv-equiv-up-product :
    (((x : X)  A x) × ((x : X)  B x))  ((x : X)  A x × B x)
  inv-equiv-up-product = inv-equiv equiv-up-product
```

#### The universal property of cartesian products as pullbacks

A different way to state the universal property of cartesian products as limits
is to say that the canonical [cone](foundation.cones-over-cospan-diagrams.md)
over the [terminal type `unit`](foundation.unit-type.md)

```text
           pr2
   A × B ------> B
     |           |
 pr1 |           |
     ∨           ∨
     A -------> unit
```

is a [pullback](foundation-core.pullbacks.md). The
[universal property of pullbacks](foundation-core.universal-property-pullbacks.md)
states in this case that maps into `A × B` are in correspondence with pairs of
maps into `A` and `B` such that the square

```text
     X --------> B
     |           |
     |           |
     ∨           ∨
     A -------> unit
```

[commutes](foundation-core.commuting-squares-of-maps.md). However, all parallel
maps into the terminal type are [equal](foundation-core.identity-types.md),
hence the coherence requirement is redundant.

We start by constructing the cone for two maps into the unit type.

```agda
module _
  {l1 l2 : Level} (A : UU l1) (B : UU l2)
  where

  cone-cartesian-product : cone (terminal-map A) (terminal-map B) (A × B)
  pr1 cone-cartesian-product = pr1
  pr1 (pr2 cone-cartesian-product) = pr2
  pr2 (pr2 cone-cartesian-product) = refl-htpy
```

Next, we show that cartesian products are a special case of pullbacks.

```agda
  gap-cartesian-product :
    A × B  standard-pullback (terminal-map A) (terminal-map B)
  gap-cartesian-product =
    gap (terminal-map A) (terminal-map B) cone-cartesian-product

  inv-gap-cartesian-product :
    standard-pullback (terminal-map A) (terminal-map B)  A × B
  pr1 (inv-gap-cartesian-product (a , b , p)) = a
  pr2 (inv-gap-cartesian-product (a , b , p)) = b

  abstract
    is-section-inv-gap-cartesian-product :
      is-section gap-cartesian-product inv-gap-cartesian-product
    is-section-inv-gap-cartesian-product (a , b , p) =
      map-extensionality-standard-pullback
        ( terminal-map A)
        ( terminal-map B)
        ( refl)
        ( refl)
        ( eq-is-contr (is-prop-unit star star))

  is-retraction-inv-gap-cartesian-product :
    is-retraction gap-cartesian-product inv-gap-cartesian-product
  is-retraction-inv-gap-cartesian-product (a , b) = refl

  abstract
    is-pullback-cartesian-product :
      is-pullback (terminal-map A) (terminal-map B) cone-cartesian-product
    is-pullback-cartesian-product =
      is-equiv-is-invertible
        inv-gap-cartesian-product
        is-section-inv-gap-cartesian-product
        is-retraction-inv-gap-cartesian-product
```

We conclude that cartesian products satisfy the universal property of pullbacks.

```agda
  abstract
    universal-property-pullback-cartesian-product :
      universal-property-pullback
        ( terminal-map A)
        ( terminal-map B)
        ( cone-cartesian-product)
    universal-property-pullback-cartesian-product =
      universal-property-pullback-is-pullback
        ( terminal-map A)
        ( terminal-map B)
        ( cone-cartesian-product)
        ( is-pullback-cartesian-product)
```

### The universal property of cartesian products as colimits

```agda
module _
  {l1 l2 l3 : Level} {A : UU l1} {B : UU l2} {C : A × B  UU l3}
  where

  equiv-ind-product : ((x : A) (y : B)  C (x , y))  ((t : A × B)  C t)
  equiv-ind-product = equiv-ind-Σ
```