# Functoriality of cartesian product types

```agda
module foundation.functoriality-cartesian-product-types where
```

<details><summary>Imports</summary>

```agda
open import foundation.dependent-pair-types
open import foundation.equality-cartesian-product-types
open import foundation.morphisms-arrows
open import foundation.universe-levels

open import foundation-core.cartesian-product-types
open import foundation-core.commuting-squares-of-maps
open import foundation-core.contractible-maps
open import foundation-core.contractible-types
open import foundation-core.equivalences
open import foundation-core.fibers-of-maps
open import foundation-core.function-types
open import foundation-core.homotopies
open import foundation-core.identity-types
```

</details>

## Idea

The **functorial action** of the
[cartesian product](foundation-core.cartesian-product-types.md) takes two maps
`f : A → B` and `g : C → D` and returns a map

```text
  f × g : A × B → C × D`
```

between the cartesian product types. This functorial action is _bifunctorial_ in
the sense that for any two maps `f : A → B` and `g : C → D` the diagram

```text
          f×1
    A × C ---> B × C
      |   \      |
  1×g |    \f×g  | 1×g
      |     \    |
      ∨      ∨   ∨
    A × D ---> B × D
          f×1
```

commutes.

## Definitions

### The functorial action of cartesian product types

```agda
module _
  {l1 l2 l3 l4 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  (f : A  B) (g : C  D)
  where

  map-product : (A × C)  (B × D)

  pr1 (map-product t) = f (pr1 t)
  pr2 (map-product t) = g (pr2 t)

  map-product-pr1 : pr1  map-product ~ f  pr1
  map-product-pr1 (a , c) = refl

  map-product-pr2 : pr2  map-product ~ g  pr2
  map-product-pr2 (a , c) = refl

module _
  {l1 l2 l3 l4 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  (f : A  B) (g : C  D)
  where

  coherence-square-map-product :
    coherence-square-maps
      ( map-product f id)
      ( map-product id g)
      ( map-product id g)
      ( map-product f id)
  coherence-square-map-product t = refl
```

## Properties

### Functoriality of products preserves identity maps

```agda
map-product-id :
  {l1 l2 : Level} {A : UU l1} {B : UU l2} 
  map-product (id {A = A}) (id {A = B}) ~ id
map-product-id (a , b) = refl
```

### Functoriality of products preserves composition

```agda
preserves-comp-map-product :
  {l1 l2 l3 l4 l5 l6 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  {E : UU l5} {F : UU l6} (f : A  C) (g : B  D) (h : C  E) (k : D  F) 
  map-product (h  f) (k  g) ~ map-product h k  map-product f g
preserves-comp-map-product f g h k t = refl
```

### Functoriality of products preserves homotopies

```agda
htpy-map-product :
  {l1 l2 l3 l4 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  {f f' : A  C} (H : f ~ f') {g g' : B  D} (K : g ~ g') 
  map-product f g ~ map-product f' g'
htpy-map-product H K (a , b) = eq-pair (H a) (K b)
```

### Functoriality of products preserves equivalences

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

  map-inv-map-product :
    (f : A  C) (g : B  D)  is-equiv f  is-equiv g  C × D  A × B
  pr1 (map-inv-map-product f g H K (c , d)) = map-inv-is-equiv H c
  pr2 (map-inv-map-product f g H K (c , d)) = map-inv-is-equiv K d

  is-section-map-inv-map-product :
    (f : A  C) (g : B  D) (H : is-equiv f) (K : is-equiv g) 
    map-product f g  map-inv-map-product f g H K ~ id
  is-section-map-inv-map-product f g H K =
    htpy-map-product
      ( is-section-map-inv-is-equiv H)
      ( is-section-map-inv-is-equiv K)

  is-retraction-map-inv-map-product :
    (f : A  C) (g : B  D) (H : is-equiv f) (K : is-equiv g) 
    map-inv-map-product f g H K  map-product f g ~ id
  is-retraction-map-inv-map-product f g H K =
    htpy-map-product
      ( is-retraction-map-inv-is-equiv H)
      ( is-retraction-map-inv-is-equiv K)

  is-equiv-map-product :
    (f : A  C) (g : B  D) 
    is-equiv f  is-equiv g  is-equiv (map-product f g)
  is-equiv-map-product f g H K =
    is-equiv-is-invertible
      ( map-inv-map-product f g H K)
      ( is-section-map-inv-map-product f g H K)
      ( is-retraction-map-inv-map-product f g H K)

  equiv-product : A  C  B  D  A × B  C × D
  pr1 (equiv-product (f , is-equiv-f) (g , is-equiv-g)) = map-product f g
  pr2 (equiv-product (f , is-equiv-f) (g , is-equiv-g)) =
    is-equiv-map-product f g is-equiv-f is-equiv-g
```

### Functoriality of products preserves equivalences in either factor

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

  equiv-product-left : A  C  A × B  C × B
  equiv-product-left f = equiv-product f id-equiv

  equiv-product-right : B  C  A × B  A × C
  equiv-product-right = equiv-product id-equiv
```

### The fibers of `map-product f g`

```agda
module _
  {l1 l2 l3 l4 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  (f : A  C) (g : B  D) (t : C × D)
  where

  map-compute-fiber-map-product :
    fiber (map-product f g) t  fiber f (pr1 t) × fiber g (pr2 t)
  pr1 (pr1 (map-compute-fiber-map-product ((a , b) , refl))) = a
  pr2 (pr1 (map-compute-fiber-map-product ((a , b) , refl))) = refl
  pr1 (pr2 (map-compute-fiber-map-product ((a , b) , refl))) = b
  pr2 (pr2 (map-compute-fiber-map-product ((a , b) , refl))) = refl

  map-inv-compute-fiber-map-product :
    fiber f (pr1 t) × fiber g (pr2 t)  fiber (map-product f g) t
  pr1 (pr1 (map-inv-compute-fiber-map-product ((x , refl) , (y , refl)))) = x
  pr2 (pr1 (map-inv-compute-fiber-map-product ((x , refl) , (y , refl)))) = y
  pr2 (map-inv-compute-fiber-map-product ((x , refl) , (y , refl))) = refl

  is-section-map-inv-compute-fiber-map-product :
    map-compute-fiber-map-product  map-inv-compute-fiber-map-product ~ id
  is-section-map-inv-compute-fiber-map-product ((x , refl) , (y , refl)) = refl

  is-retraction-map-inv-compute-fiber-map-product :
    map-inv-compute-fiber-map-product  map-compute-fiber-map-product ~ id
  is-retraction-map-inv-compute-fiber-map-product ((a , b) , refl) = refl

  is-equiv-map-compute-fiber-map-product :
    is-equiv map-compute-fiber-map-product
  is-equiv-map-compute-fiber-map-product =
    is-equiv-is-invertible
      ( map-inv-compute-fiber-map-product)
      ( is-section-map-inv-compute-fiber-map-product)
      ( is-retraction-map-inv-compute-fiber-map-product)

  compute-fiber-map-product :
    fiber (map-product f g) t  (fiber f (pr1 t) × fiber g (pr2 t))
  pr1 compute-fiber-map-product = map-compute-fiber-map-product
  pr2 compute-fiber-map-product = is-equiv-map-compute-fiber-map-product
```

### If `map-product f g : A × B → C × D` is an equivalence, then we have `D → is-equiv f` and `C → is-equiv g`

```agda
module _
  {l1 l2 l3 l4 : Level} {A : UU l1} {B : UU l2} {C : UU l3} {D : UU l4}
  (f : A  C) (g : B  D)
  where

  is-equiv-left-factor-is-equiv-map-product' :
    D  is-equiv (map-product f g)  is-equiv f
  is-equiv-left-factor-is-equiv-map-product'
    d is-equiv-fg =
    is-equiv-is-contr-map
      ( λ x 
        is-contr-left-factor-product
          ( fiber f x)
          ( fiber g d)
          ( is-contr-is-equiv'
            ( fiber (map-product f g) (x , d))
            ( map-compute-fiber-map-product f g (x , d))
            ( is-equiv-map-compute-fiber-map-product f g (x , d))
            ( is-contr-map-is-equiv is-equiv-fg (x , d))))

  is-equiv-right-factor-is-equiv-map-product' :
    C  is-equiv (map-product f g)  is-equiv g
  is-equiv-right-factor-is-equiv-map-product'
    c is-equiv-fg =
    is-equiv-is-contr-map
      ( λ y 
        is-contr-right-factor-product
          ( fiber f c)
          ( fiber g y)
          ( is-contr-is-equiv'
            ( fiber (map-product f g) (c , y))
            ( map-compute-fiber-map-product f g (c , y))
            ( is-equiv-map-compute-fiber-map-product f g (c , y))
            ( is-contr-map-is-equiv is-equiv-fg (c , y))))
```

### The functorial action of products on arrows

Given a pair of [morphisms of arrows](foundation.morphisms-arrows.md)
`α : f → g` and `β : h → i`, there is an induced morphism of arrows
`α × β : f × h → g × i` and this construction is functorial.

```agda
module _
  {l1 l2 l3 l4 l5 l6 l7 l8 : Level}
  {A : UU l1} {B : UU l2} {X : UU l3} {Y : UU l4}
  {C : UU l5} {D : UU l6} {Z : UU l7} {W : UU l8}
  (f : A  B) (g : X  Y) (h : C  D) (i : Z  W)
  (α : hom-arrow f g) (β : hom-arrow h i)
  where

  product-hom-arrow : hom-arrow (map-product f h) (map-product g i)
  product-hom-arrow =
    ( ( map-product
        ( map-domain-hom-arrow f g α)
        ( map-domain-hom-arrow h i β)) ,
      ( map-product
        ( map-codomain-hom-arrow f g α)
        ( map-codomain-hom-arrow h i β)) ,
      ( htpy-map-product
        ( coh-hom-arrow f g α)
        ( coh-hom-arrow h i β)))
```

## See also

- Arithmetical laws involving cartesian product types are recorded in
  [`foundation.type-arithmetic-cartesian-product-types`](foundation.type-arithmetic-cartesian-product-types.md).
- Equality proofs in cartesian product types are characterized in
  [`foundation.equality-cartesian-product-types`](foundation.equality-cartesian-product-types.md).
- The universal property of cartesian product types is treated in
  [`foundation.universal-property-cartesian-product-types`](foundation.universal-property-cartesian-product-types.md).
- Functorial properties of dependent pair types are recorded in
  [`foundation.functoriality-dependent-pair-types`](foundation.functoriality-dependent-pair-types.md).
- Functorial properties of dependent product types are recorded in
  [`foundation.functoriality-dependent-function-types`](foundation.functoriality-dependent-function-types.md).
- Functorial properties of coproduct types are recorded in
  [`foundation.functoriality-coproduct-types`](foundation.functoriality-coproduct-types.md).