# Functoriality of the list operation
```agda
module lists.functoriality-lists where
```
<details><summary>Imports</summary>
```agda
open import elementary-number-theory.equality-natural-numbers
open import elementary-number-theory.natural-numbers
open import foundation.action-on-identifications-functions
open import foundation.dependent-pair-types
open import foundation.equality-dependent-pair-types
open import foundation.function-types
open import foundation.homotopies
open import foundation.identity-types
open import foundation.propositions
open import foundation.transport-along-identifications
open import foundation.universe-levels
open import linear-algebra.functoriality-vectors
open import linear-algebra.vectors
open import lists.arrays
open import lists.concatenation-lists
open import lists.lists
```
</details>
## Idea
Given a functiion `f : A → B`, we obtain a function
`map-list f : list A → list B`.
## Definition
```agda
map-list :
{l1 l2 : Level} {A : UU l1} {B : UU l2} (f : A → B) →
list A → list B
map-list f = fold-list nil (λ a → cons (f a))
```
## Properties
### `map-list` preserves the length of a list
```agda
length-map-list :
{l1 l2 : Level} {A : UU l1} {B : UU l2} (f : A → B) (l : list A) →
Id (length-list (map-list f l)) (length-list l)
length-map-list f nil = refl
length-map-list f (cons x l) =
ap succ-ℕ (length-map-list f l)
```
### Link between `map-list` and `map-vec`
```agda
module _
{l1 l2 : Level} {A : UU l1} {B : UU l2}
(f : A → B)
where
map-list-map-vec-list :
(l : list A) →
list-vec (length-list l) (map-vec f (vec-list l)) =
map-list f l
map-list-map-vec-list nil = refl
map-list-map-vec-list (cons x l) =
eq-Eq-list
( list-vec (length-list (cons x l)) (map-vec f (vec-list (cons x l))))
( map-list f (cons x l))
( refl ,
Eq-eq-list
( list-vec (length-list l) (map-vec f (vec-list l)))
( map-list f l)
( map-list-map-vec-list l))
map-vec-map-list-vec :
(n : ℕ) (v : vec A n) →
tr
( vec B)
( length-map-list f (list-vec n v) ∙
compute-length-list-list-vec n v)
( vec-list (map-list f (list-vec n v))) =
map-vec f v
map-vec-map-list-vec 0 empty-vec = refl
map-vec-map-list-vec (succ-ℕ n) (x ∷ v) =
compute-tr-vec
( ap succ-ℕ (length-map-list f (list-vec n v)) ∙
compute-length-list-list-vec (succ-ℕ n) (x ∷ v))
( vec-list (fold-list nil (λ a → cons (f a)) (list-vec n v)))
( f x) ∙
eq-Eq-vec
( succ-ℕ n)
( f x ∷
tr
( vec B)
( is-injective-succ-ℕ
( ap succ-ℕ (length-map-list f (list-vec n v)) ∙
compute-length-list-list-vec (succ-ℕ n) (x ∷ v)))
( vec-list (map-list f (list-vec n v))))
( map-vec f (x ∷ v))
( refl ,
( Eq-eq-vec
( n)
( tr
( vec B)
( is-injective-succ-ℕ
( ap succ-ℕ (length-map-list f (list-vec n v)) ∙
compute-length-list-list-vec (succ-ℕ n) (x ∷ v)))
( vec-list (map-list f (list-vec n v))))
( map-vec f v)
( tr
( λ p →
tr
( vec B)
( p)
( vec-list (map-list f (list-vec n v))) =
map-vec f v)
( eq-is-prop
( is-set-ℕ
( length-list (map-list f (list-vec n v)))
( n)))
( map-vec-map-list-vec n v))))
map-vec-map-list-vec' :
(n : ℕ) (v : vec A n) →
vec-list (map-list f (list-vec n v)) =
tr
( vec B)
( inv
( length-map-list f (list-vec n v) ∙
compute-length-list-list-vec n v))
( map-vec f v)
map-vec-map-list-vec' n v =
eq-transpose-tr'
( length-map-list f (list-vec n v) ∙ compute-length-list-list-vec n v)
( map-vec-map-list-vec n v)
vec-list-map-list-map-vec-list :
(l : list A) →
tr
( vec B)
( length-map-list f l)
( vec-list (map-list f l)) =
map-vec f (vec-list l)
vec-list-map-list-map-vec-list nil = refl
vec-list-map-list-map-vec-list (cons x l) =
compute-tr-vec
( ap succ-ℕ (length-map-list f l))
( vec-list (map-list f l))
( f x) ∙
eq-Eq-vec
( succ-ℕ (length-list l))
( f x ∷
tr
( vec B)
( is-injective-succ-ℕ (ap succ-ℕ (length-map-list f l)))
( vec-list (map-list f l)))
( map-vec f (vec-list (cons x l)))
( refl ,
Eq-eq-vec
( length-list l)
( tr
( vec B)
( is-injective-succ-ℕ (ap succ-ℕ (length-map-list f l)))
( vec-list (map-list f l)))
( map-vec f (vec-list l))
( tr
( λ p →
( tr
( vec B)
( p)
( vec-list (map-list f l))) =
( map-vec f (vec-list l)))
( eq-is-prop
( is-set-ℕ (length-list (map-list f l)) (length-list l)))
( vec-list-map-list-map-vec-list l)))
vec-list-map-list-map-vec-list' :
(l : list A) →
vec-list (map-list f l) =
tr
( vec B)
( inv (length-map-list f l))
( map-vec f (vec-list l))
vec-list-map-list-map-vec-list' l =
eq-transpose-tr'
( length-map-list f l)
( vec-list-map-list-map-vec-list l)
list-vec-map-vec-map-list-vec :
(n : ℕ) (v : vec A n) →
list-vec
( length-list (map-list f (list-vec n v)))
( vec-list (map-list f (list-vec n v))) =
list-vec n (map-vec f v)
list-vec-map-vec-map-list-vec n v =
ap
( λ p → list-vec (pr1 p) (pr2 p))
( eq-pair-Σ
( length-map-list f (list-vec n v) ∙
compute-length-list-list-vec n v)
( map-vec-map-list-vec n v))
```
### `map-list` preserves concatenation
```agda
module _
{l1 l2 : Level} {A : UU l1} {B : UU l2} (f : A → B)
where
preserves-concat-map-list :
(l k : list A) →
Id
( map-list f (concat-list l k))
( concat-list (map-list f l) (map-list f k))
preserves-concat-map-list nil k = refl
preserves-concat-map-list (cons x l) k =
ap (cons (f x)) (preserves-concat-map-list l k)
```
### Functoriality of the list operation
First we introduce the functoriality of the list operation, because it will come
in handy when we try to define and prove more advanced things.
```agda
identity-law-map-list :
{l1 : Level} {A : UU l1} →
map-list (id {A = A}) ~ id
identity-law-map-list nil = refl
identity-law-map-list (cons a x) =
ap (cons a) (identity-law-map-list x)
composition-law-map-list :
{l1 l2 l3 : Level} {A : UU l1} {B : UU l2} {C : UU l3} →
(f : A → B) (g : B → C) →
map-list (g ∘ f) ~ (map-list g ∘ map-list f)
composition-law-map-list f g nil = refl
composition-law-map-list f g (cons a x) =
ap (cons (g (f a))) (composition-law-map-list f g x)
```
### `map-list` applied to lists of the form `snoc x a`
```agda
map-snoc-list :
{l1 l2 : Level} {A : UU l1} {B : UU l2} (f : A → B) (x : list A) (a : A) →
map-list f (snoc x a) = snoc (map-list f x) (f a)
map-snoc-list f nil a = refl
map-snoc-list f (cons b x) a = ap (cons (f b)) (map-snoc-list f x a)
```