# Yoneda identity types

```agda
module foundation.yoneda-identity-types where
```

<details><summary>Imports</summary>

```agda
open import foundation.action-on-identifications-functions
open import foundation.dependent-pair-types
open import foundation.function-extensionality
open import foundation.multivariable-homotopies
open import foundation.strictly-right-unital-concatenation-identifications
open import foundation.transport-along-identifications
open import foundation.univalence
open import foundation.universal-property-identity-systems
open import foundation.universe-levels

open import foundation-core.contractible-types
open import foundation-core.equivalences
open import foundation-core.function-types
open import foundation-core.functoriality-dependent-pair-types
open import foundation-core.homotopies
open import foundation-core.identity-types
open import foundation-core.retractions
open import foundation-core.sections
open import foundation-core.torsorial-type-families
```

</details>

## Idea

The standard definition of [identity types](foundation-core.identity-types.md)
has the limitation that many of the basic operations only satisfy algebraic laws
_weakly_. On this page, we consider the
{{#concept "Yoneda identity types" Agda=yoneda-Id}}

```text
  (x =ʸ y) := (z : A) → (z = x) → (z = y)
```

Through the interpretation of types as ∞-categories, where the hom-space
`hom(x , y)` is defined to be the identity type `x = y`, we may observe that
this is an instance of the Yoneda embedding. We use a superscript `y` in the
notation of the Yoneda identity types, and similarly we call elements of the
Yoneda identity types for {{#concept "Yoneda identifications" Agda=yoneda-Id}}.

The Yoneda identity types are [equivalent](foundation-core.equivalences.md) to
the standard identity types, but satisfy strict laws

- `(p ∙ʸ q) ∙ʸ r ≐ p ∙ʸ (q ∙ʸ r)`,
- `reflʸ ∙ʸ p ≐ p`, and
- `p ∙ʸ reflʸ ≐ p`.

This is achieved by proxying to function composition and utilizing its
computational properties, and relies heavily on the
[function extensionality axiom](foundation.function-extensionality.md). More
concretely, the reflexivity is given by the identity function, and path
concatenation is given by function composition.

In addition to these strictness laws, we can make the type satisfy the strict
law `invʸ reflʸ ≐ reflʸ`. Moreover, while the induction principle of the Yoneda
identity types does not in general satisfy the computation rule strictly, we can
define its recursion principle such that does.

## Definition

```agda
module _
  {l : Level} {A : UU l}
  where

  yoneda-Id : (x y : A)  UU l
  yoneda-Id x y = (z : A)  z  x  z  y

  infix 6 _=ʸ_
  _=ʸ_ : A  A  UU l
  (a =ʸ b) = yoneda-Id a b
```

We define the reflexivity by the identity function:

```agda
  reflʸ : {x : A}  x =ʸ x
  reflʸ z = id
```

## Properties

### Elements of the Yoneda identity type act like postconcatenation operations

The following is a collection of properties of Yoneda identifications similar to
properties of the postconcatenation operation of identifications.

```agda
module _
  {l : Level} {A : UU l}
  where

  commutative-preconcat-Id-yoneda-Id :
    {x y z w : A} (f : x =ʸ y) (p : w  z) (q : z  x) 
    f w (p  q)  p  f z q
  commutative-preconcat-Id-yoneda-Id f refl q = refl

  commutative-preconcat-refl-Id-yoneda-Id :
    {x y z : A} (f : x =ʸ y) (q : z  x)  f z q  q  f x refl
  commutative-preconcat-refl-Id-yoneda-Id {z = z} f q =
    ap (f z) (inv right-unit)  commutative-preconcat-Id-yoneda-Id f q refl

  commutative-preconcatr-Id-yoneda-Id :
    {x y z w : A} (f : x =ʸ y) (p : w  z) (q : z  x) 
    f w (p ∙ᵣ q)  p ∙ᵣ f z q
  commutative-preconcatr-Id-yoneda-Id {x} {y} {z} {w} f p q =
    ( ap (f w) (eq-concat-right-strict-concat p q)) 
    ( commutative-preconcat-Id-yoneda-Id f p q) 
    ( eq-right-strict-concat-concat p (f z q))

  commutative-preconcatr-refl-Id-yoneda-Id :
    {x y z : A} (f : x =ʸ y) (q : z  x)  f z q  q ∙ᵣ f x refl
  commutative-preconcatr-refl-Id-yoneda-Id f q =
    commutative-preconcatr-Id-yoneda-Id f q refl

  compute-inv-Id-yoneda-Id :
    {x y : A} (f : x =ʸ y)  f y (inv (f x refl))  refl
  compute-inv-Id-yoneda-Id {x} f =
    ( commutative-preconcat-refl-Id-yoneda-Id f (inv (f x refl))) 
    ( left-inv (f x refl))

  inv-distributive-inv-Id-yoneda-Id :
    {x y z : A} (f : x =ʸ y) (g : x =ʸ z) 
    inv (g y (inv (f x refl)))  f z (inv (g x refl))
  inv-distributive-inv-Id-yoneda-Id {x} f g =
    ( ap inv (commutative-preconcat-refl-Id-yoneda-Id g (inv (f x refl)))) 
    ( distributive-inv-concat (inv (f x refl)) (g x refl)) 
    ( ap (inv (g x refl) ∙_) (inv-inv (f x refl))) 
    ( inv (commutative-preconcat-refl-Id-yoneda-Id f (inv (g x refl))))

  distributive-inv-Id-yoneda-Id :
    {x y z : A} (f : x =ʸ y) (g : x =ʸ z) 
    f z (inv (g x refl))  inv (g y (inv (f x refl)))
  distributive-inv-Id-yoneda-Id f g =
    inv (inv-distributive-inv-Id-yoneda-Id f g)
```

### The Yoneda identity types are equivalent to the standard identity types

The equivalence `(x = y) ≃ (x =ʸ y)` is defined from left to right by the
postconcatenation operation

```text
  yoneda-eq-eq := p ↦ (q ↦ q ∙ p)   : x = y → x =ʸ y,
```

and from right to left by evaluation at the reflexivity

```text
  eq-yoneda-eq := f ↦ f refl   : x =ʸ y → x = y.
```

It should be noted that we define the map `x = y → x =ʸ y` using the
[strictly right unital concatenation operation](foundation.strictly-right-unital-concatenation-identifications.md).
While this obstructs us from showing that the
[homotopy](foundation-core.homotopies.md) `eq-yoneda-eq ∘ yoneda-eq-eq ~ id`
holds by reflexivity as demonstrated by the computation

```text
  eq-yoneda-eq ∘ yoneda-eq-eq
  ≐ p ↦ (f ↦ f refl) (q ↦ q ∙ p)
  ≐ p ↦ ((q ↦ q ∙ p) refl)
  ≐ p ↦ refl ∙ p,
```

it allows us to show that reflexivities are preserved strictly in both
directions, and not just from `x =ʸ y` to `x = y`.

From left to right:

```text
  yoneda-eq-eq refl ≐ (p ↦ (q ↦ q ∙ p)) refl ≐ (q ↦ q ∙ refl) ≐ (q ↦ q) ≐ reflʸ
```

and from right to left:

```text
  eq-yoneda-eq reflʸ ≐ (f ↦ f refl) reflʸ ≐ (q ↦ q) refl ≐ refl.
```

```agda
module _
  {l : Level} {A : UU l} {x y : A}
  where

  yoneda-eq-eq : x  y  x =ʸ y
  yoneda-eq-eq p z q = q ∙ᵣ p

  eq-yoneda-eq : x =ʸ y  x  y
  eq-yoneda-eq f = f x refl
```

The construction of the homotopy `yoneda-eq-eq ∘ eq-yoneda-eq ~ id` requires the
[function extensionality axiom](foundation.function-extensionality.md). And
while we could show an analogous induction principle of the Yoneda identity
types without the use of this axiom, function extensionality will become
indispensable regardless when we proceed to proving miscellaneous algebraic laws
of the Yoneda identity type.

```agda
  is-section-eq-yoneda-eq :
    is-section yoneda-eq-eq eq-yoneda-eq
  is-section-eq-yoneda-eq f =
    eq-multivariable-htpy 2
      ( λ _ p  inv (commutative-preconcatr-refl-Id-yoneda-Id f p))

  is-retraction-eq-yoneda-eq :
    is-retraction yoneda-eq-eq eq-yoneda-eq
  is-retraction-eq-yoneda-eq p = left-unit-right-strict-concat

  is-equiv-yoneda-eq-eq : is-equiv yoneda-eq-eq
  pr1 (pr1 is-equiv-yoneda-eq-eq) = eq-yoneda-eq
  pr2 (pr1 is-equiv-yoneda-eq-eq) = is-section-eq-yoneda-eq
  pr1 (pr2 is-equiv-yoneda-eq-eq) = eq-yoneda-eq
  pr2 (pr2 is-equiv-yoneda-eq-eq) = is-retraction-eq-yoneda-eq

  is-equiv-eq-yoneda-eq : is-equiv eq-yoneda-eq
  pr1 (pr1 is-equiv-eq-yoneda-eq) = yoneda-eq-eq
  pr2 (pr1 is-equiv-eq-yoneda-eq) = is-retraction-eq-yoneda-eq
  pr1 (pr2 is-equiv-eq-yoneda-eq) = yoneda-eq-eq
  pr2 (pr2 is-equiv-eq-yoneda-eq) = is-section-eq-yoneda-eq

  equiv-yoneda-eq-eq : (x  y)  (x =ʸ y)
  pr1 equiv-yoneda-eq-eq = yoneda-eq-eq
  pr2 equiv-yoneda-eq-eq = is-equiv-yoneda-eq-eq

  equiv-eq-yoneda-eq : (x =ʸ y)  (x  y)
  pr1 equiv-eq-yoneda-eq = eq-yoneda-eq
  pr2 equiv-eq-yoneda-eq = is-equiv-eq-yoneda-eq
```

This equvialence preserves the reflexivity elements strictly in both directions.

```agda
module _
  {l : Level} {A : UU l} {x : A}
  where

  is-section-eq-yoneda-eq-refl :
    yoneda-eq-eq (eq-yoneda-eq (reflʸ {x = x}))  reflʸ
  is-section-eq-yoneda-eq-refl = refl

  preserves-refl-yoneda-eq-eq :
    yoneda-eq-eq (refl {x = x})  reflʸ
  preserves-refl-yoneda-eq-eq = refl

  preserves-refl-eq-yoneda-eq :
    eq-yoneda-eq (reflʸ {x = x})  refl
  preserves-refl-eq-yoneda-eq = refl
```

Below, we consider the alternative definition of `yoneda-eq-eq` using the
strictly left unital concatenation operation on standard identity types. As we
can see, the retracting homotopy holds strictly, but now `yoneda-eq-eq refl`
does not compute strictly to `reflʸ`.

```agda
module _
  {l : Level} {A : UU l} {x y : A}
  where

  yoneda-eq-eq' : x  y  x =ʸ y
  yoneda-eq-eq' p z q = q  p

  is-section-eq-yoneda-eq' :
    is-section yoneda-eq-eq' eq-yoneda-eq
  is-section-eq-yoneda-eq' f =
    eq-multivariable-htpy 2
      ( λ _ p  inv (commutative-preconcat-refl-Id-yoneda-Id f p))

  is-retraction-eq-yoneda-eq' :
    is-retraction yoneda-eq-eq' eq-yoneda-eq
  is-retraction-eq-yoneda-eq' p = refl

module _
  {l : Level} {A : UU l}
  where

  preserves-refl-yoneda-eq-eq' :
    {x : A}  yoneda-eq-eq' (refl {x = x})  reflʸ
  preserves-refl-yoneda-eq-eq' =
    eq-multivariable-htpy 2  _ p  right-unit)
```

### Torsoriality of the Yoneda identity types

```agda
module _
  {l : Level} {A : UU l} {x : A}
  where

  is-torsorial-yoneda-Id : is-torsorial (yoneda-Id x)
  is-torsorial-yoneda-Id =
    is-contr-equiv
      ( Σ A (x =_))
      ( equiv-tot  y  equiv-eq-yoneda-eq {x = x} {y}))
      ( is-torsorial-Id x)
```

### The dependent universal property of the Yoneda identity types

```agda
module _
  {l : Level} {A : UU l} {x : A}
  where

  dependent-universal-property-identity-system-yoneda-Id :
    dependent-universal-property-identity-system
      ( yoneda-Id x)
      ( reflʸ)
  dependent-universal-property-identity-system-yoneda-Id =
    dependent-universal-property-identity-system-is-torsorial
      ( reflʸ)
      ( is-torsorial-yoneda-Id)
```

### The induction principle for the Yoneda identity types

The Yoneda identity types satisfy the induction principle of the identity types.
This states that given a base point `x : A` and a family of types over the
identity types based at `x`, `B : (y : A) (f : x =ʸ y) → UU l2`, then to
construct a dependent function `g : (y : A) (f : x =ʸ y) → B y p` it suffices
to define it at `g x reflʸ`.

**Note.** As stated before, a drawback of the Yoneda identity types is that they
do not satisfy a strict computation rule for this induction principle.

```agda
module _
  {l1 l2 : Level} {A : UU l1} {x : A}
  (B : (y : A) (f : x =ʸ y)  UU l2)
  where

  ind-yoneda-Id' :
    (b : B x reflʸ) {y : A} (f : x =ʸ y)  B y f
  ind-yoneda-Id' b {y} =
    map-inv-is-equiv
      ( dependent-universal-property-identity-system-yoneda-Id B)
      ( b)
      ( y)

  compute-ind-yoneda-Id' :
    (b : B x reflʸ) 
    ind-yoneda-Id' b reflʸ  b
  compute-ind-yoneda-Id' =
    is-section-map-inv-is-equiv
      ( dependent-universal-property-identity-system-yoneda-Id B)

  uniqueness-ind-yoneda-Id' :
    (b : (y : A) (f : x =ʸ y)  B y f) 
     y  ind-yoneda-Id' (b x reflʸ) {y})  b
  uniqueness-ind-yoneda-Id' =
    is-retraction-map-inv-is-equiv
      ( dependent-universal-property-identity-system-yoneda-Id B)
```

The following is a more concrete construction of the induction principle. We
observe that while `eq-yoneda-eq` and `yoneda-eq-eq` preserve reflexivities
strictly as required, the reduction is obstructed because the proof of
`is-section-eq-yoneda-eq` does not reduce to `refl` when `f ≐ reflʸ`.

```agda
module _
  {l1 l2 : Level} {A : UU l1} {x : A}
  (B : (y : A) (f : x =ʸ y)  UU l2)
  where

  ind-yoneda-Id :
    (b : B x reflʸ) {y : A} (f : x =ʸ y)  B y f
  ind-yoneda-Id b {y} f =
    tr
      ( B y)
      ( is-section-eq-yoneda-eq f)
      ( ind-Id x  y p  B y (yoneda-eq-eq p)) b y (eq-yoneda-eq f))
```

While the induction principle does not have the desired reduction behaviour, the
nondependent eliminator does. This is simply because we no longer need to
[transport](foundation-core.transport-along-identifications.md) along
`is-section-eq-yoneda-eq`.

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

  rec-yoneda-Id :
    (b : B x) {y : A}  x =ʸ y  B y
  rec-yoneda-Id b f = tr B (eq-yoneda-eq f) b

  compute-rec-yoneda-Id :
    (b : B x)  rec-yoneda-Id b reflʸ  b
  compute-rec-yoneda-Id b = refl

  uniqueness-rec-yoneda-Id :
    (b : (y : A)  x =ʸ y  B y) 
     y  rec-yoneda-Id (b x reflʸ) {y})  b
  uniqueness-rec-yoneda-Id b =
    ( inv
      ( uniqueness-ind-yoneda-Id'
        ( λ y _  B y)
        ( λ y  rec-yoneda-Id (b x reflʸ)))) 
    ( uniqueness-ind-yoneda-Id'  y _  B y) b)
```

## Structure

The Yoneda identity types form a strictly compositional weak groupoidal
structure on types.

### Inverting Yoneda identifications

We consider two ways of defining the inversion operation on Yoneda
identifications: by the strictly right unital, and strictly left unital
concatenation operation on the underlying identity type respectively. In
contrast to the latter, the former enjoys the computational property

```text
  invʸ reflʸ ≐ reflʸ,
```

hence it will be preferred going forward.

#### The inversion operation defined by the strictly right unital concatenation operation on identifications

```agda
module _
  {l : Level} {A : UU l}
  where

  invʸ : {x y : A}  x =ʸ y  y =ʸ x
  invʸ {x} f z p = p ∙ᵣ inv (f x refl)

  compute-inv-refl-yoneda-Id :
    {x : A}  invʸ (reflʸ {x = x})  reflʸ
  compute-inv-refl-yoneda-Id = refl

  inv-inv-yoneda-Id :
    {x y : A} (f : x =ʸ y)  invʸ (invʸ f)  f
  inv-inv-yoneda-Id {x} f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap
          ( p ∙ᵣ_)
          ( ap inv left-unit-right-strict-concat  inv-inv (f x refl))) 
        ( inv (commutative-preconcatr-refl-Id-yoneda-Id f p)))
```

The inversion operation corresponds to the standard inversion operation on
identifications:

```agda
module _
  {l : Level} {A : UU l}
  where

  preserves-inv-yoneda-eq-eq' :
    {x y : A} (p : x  y)  yoneda-eq-eq (inv p)  invʸ (yoneda-eq-eq' p)
  preserves-inv-yoneda-eq-eq' p = refl

  preserves-inv-yoneda-eq-eq :
    {x y : A} (p : x  y)  yoneda-eq-eq (inv p)  invʸ (yoneda-eq-eq p)
  preserves-inv-yoneda-eq-eq p =
    eq-multivariable-htpy 2
      ( λ _ q  ap  r  q ∙ᵣ inv r) (inv left-unit-right-strict-concat))

  preserves-inv-eq-yoneda-eq :
    {x y : A} (f : x =ʸ y)  eq-yoneda-eq (invʸ f)  inv (eq-yoneda-eq f)
  preserves-inv-eq-yoneda-eq f = left-unit-right-strict-concat
```

#### The inversion operation defined by the strictly left unital concatenation operation on identifications

```agda
module _
  {l : Level} {A : UU l}
  where

  left-strict-inv-yoneda-Id : {x y : A}  x =ʸ y  y =ʸ x
  left-strict-inv-yoneda-Id {x} f z p = p  inv (f x refl)

  compute-left-strict-inv-yoneda-Id-refl :
    {x : A}  left-strict-inv-yoneda-Id (reflʸ {x = x})  reflʸ
  compute-left-strict-inv-yoneda-Id-refl =
    eq-multivariable-htpy 2  _ p  right-unit)

  left-strict-inv-left-strict-inv-yoneda-Id :
    {x y : A} (f : x =ʸ y) 
    left-strict-inv-yoneda-Id (left-strict-inv-yoneda-Id f)  f
  left-strict-inv-left-strict-inv-yoneda-Id {x} f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap (p ∙_) (inv-inv (f x refl))) 
        ( inv (commutative-preconcat-refl-Id-yoneda-Id f p)))
```

This inversion operation also corresponds to the standard inversion operation on
identifications:

```agda
module _
  {l : Level} {A : UU l}
  where

  preserves-left-strict-inv-yoneda-eq-eq :
    {x y : A} (p : x  y) 
    yoneda-eq-eq (inv p)  left-strict-inv-yoneda-Id (yoneda-eq-eq p)
  preserves-left-strict-inv-yoneda-eq-eq p =
    eq-multivariable-htpy 2
      ( λ _ q 
        ( eq-concat-right-strict-concat q (inv p)) 
        ( ap  r  q  inv r) (inv left-unit-right-strict-concat)))

  preserves-left-strict-inv-eq-yoneda-eq :
    {x y : A} (f : x =ʸ y) 
    eq-yoneda-eq (left-strict-inv-yoneda-Id f)  inv (eq-yoneda-eq f)
  preserves-left-strict-inv-eq-yoneda-eq f = refl
```

### Concatenation of Yoneda identifications

The concatenation operation on Yoneda identifications is defined by function
composition

```text
  f ∙ʸ g := z p ↦ g z (f z p)
```

and is thus strictly associative and two-sided unital (since the reflexivities
are given by the identity functions).

```agda
module _
  {l : Level} {A : UU l}
  where

  infixl 15 _∙ʸ_
  _∙ʸ_ : {x y z : A}  x =ʸ y  y =ʸ z  x =ʸ z
  (f ∙ʸ g) z p = g z (f z p)

  concat-yoneda-Id : {x y : A}  x =ʸ y  (z : A)  y =ʸ z  x =ʸ z
  concat-yoneda-Id f z g = f ∙ʸ g

  concat-yoneda-Id' : (x : A) {y z : A}  y =ʸ z  x =ʸ y  x =ʸ z
  concat-yoneda-Id' x g f = f ∙ʸ g
```

The concatenation operation corresponds to the standard concatenation operation
on identifications:

```agda
module _
  {l : Level} {A : UU l}
  where

  preserves-concat-yoneda-eq-eq :
    {x y z : A} (p : x  y) (q : y  z) 
    yoneda-eq-eq (p  q)  yoneda-eq-eq p ∙ʸ yoneda-eq-eq q
  preserves-concat-yoneda-eq-eq refl refl = refl

  preserves-concat-eq-yoneda-eq :
    {x y z : A} (f : x =ʸ y) (g : y =ʸ z) 
    eq-yoneda-eq (f ∙ʸ g)  eq-yoneda-eq f  eq-yoneda-eq g
  preserves-concat-eq-yoneda-eq {x} f g =
    commutative-preconcat-refl-Id-yoneda-Id g (f x refl)
```

### The groupoidal laws for the Yoneda identity types

As we may now observe, associativity and the unit laws hold by `refl`.

```agda
module _
  {l : Level} {A : UU l} {x y : A}
  where

  assoc-yoneda-Id :
    (f : x =ʸ y) {z w : A} (g : y =ʸ z) (h : z =ʸ w) 
    (f ∙ʸ g) ∙ʸ h  f ∙ʸ (g ∙ʸ h)
  assoc-yoneda-Id f g h = refl

  left-unit-yoneda-Id :
    {f : x =ʸ y}  reflʸ ∙ʸ f  f
  left-unit-yoneda-Id = refl

  right-unit-yoneda-Id :
    {f : x =ʸ y}  f ∙ʸ reflʸ  f
  right-unit-yoneda-Id = refl
```

In addition, we show a range of basic algebraic laws for the Yoneda identity
types.

```agda
  left-inv-yoneda-Id :
    (f : x =ʸ y)  invʸ f ∙ʸ f  reflʸ
  left-inv-yoneda-Id f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( commutative-preconcatr-Id-yoneda-Id f p (inv (f x refl))) 
        ( ap (p ∙ᵣ_) (compute-inv-Id-yoneda-Id f)))

  left-left-strict-inv-yoneda-Id :
    (f : x =ʸ y)  left-strict-inv-yoneda-Id f ∙ʸ f  reflʸ
  left-left-strict-inv-yoneda-Id f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( commutative-preconcat-Id-yoneda-Id f p (inv (f x refl))) 
        ( ap (p ∙_) (compute-inv-Id-yoneda-Id f)  right-unit))

  right-inv-yoneda-Id :
    (f : x =ʸ y)  f ∙ʸ invʸ f  reflʸ
  right-inv-yoneda-Id f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap
          ( _∙ᵣ inv (f x refl))
          ( commutative-preconcatr-refl-Id-yoneda-Id f p)) 
        ( assoc-right-strict-concat p (f x refl) (inv (f x refl))) 
        ( ap (p ∙ᵣ_) (right-inv-right-strict-concat (f x refl))))

  right-left-strict-inv-yoneda-Id :
    (f : x =ʸ y)  f ∙ʸ left-strict-inv-yoneda-Id f  reflʸ
  right-left-strict-inv-yoneda-Id f =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap
          ( _∙ inv (f x refl))
          ( commutative-preconcat-refl-Id-yoneda-Id f p)) 
        ( assoc p (f x refl) (inv (f x refl))) 
        ( ap (p ∙_) (right-inv (f x refl))) 
        ( right-unit))

  distributive-inv-concat-yoneda-Id :
    (f : x =ʸ y) {z : A} (g : y =ʸ z) 
    invʸ (f ∙ʸ g)  invʸ g ∙ʸ invʸ f
  distributive-inv-concat-yoneda-Id f g =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap
          ( p ∙ᵣ_)
          ( ( ap
              ( inv)
              ( commutative-preconcatr-refl-Id-yoneda-Id g (f x refl))) 
            ( distributive-inv-right-strict-concat (f x refl) (g y refl)))) 
          ( inv
            ( assoc-right-strict-concat p (inv (g y refl)) (inv (f x refl)))))

  distributive-left-strict-inv-concat-yoneda-Id :
    (f : x =ʸ y) {z : A} (g : y =ʸ z) 
    left-strict-inv-yoneda-Id (f ∙ʸ g) 
    left-strict-inv-yoneda-Id g ∙ʸ left-strict-inv-yoneda-Id f
  distributive-left-strict-inv-concat-yoneda-Id f g =
    eq-multivariable-htpy 2
      ( λ _ p 
        ( ap
          ( p ∙_)
          ( ( ap
              ( inv)
              ( commutative-preconcat-refl-Id-yoneda-Id g (f x refl))) 
            ( distributive-inv-concat (f x refl) (g y refl)))) 
        ( inv (assoc p (inv (g y refl)) (inv (f x refl)))))
```

## Operations

We can define a range basic operations on the Yoneda identifications that all
enjoy strict computational properties.

### Action of functions on Yoneda identifications

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

  eq-ap-yoneda-Id : {x y : A}  x =ʸ y  f x  f y
  eq-ap-yoneda-Id = ap f  eq-yoneda-eq

  ap-yoneda-Id : {x y : A}  x =ʸ y  f x =ʸ f y
  ap-yoneda-Id = yoneda-eq-eq  eq-ap-yoneda-Id

  compute-ap-refl-yoneda-Id : {x : A}  ap-yoneda-Id (reflʸ {x = x})  reflʸ
  compute-ap-refl-yoneda-Id = refl

module _
  {l1 : Level} {A : UU l1}
  where

  compute-ap-id-yoneda-Id : {x y : A} (p : x =ʸ y)  ap-yoneda-Id id p  p
  compute-ap-id-yoneda-Id {x} p =
    eq-multivariable-htpy 2
      ( λ _ q 
        ( ap (q ∙ᵣ_) (ap-id (p x refl))) 
        ( inv (commutative-preconcatr-refl-Id-yoneda-Id p q)))
```

### Action of binary functions on Yoneda identifications

We obtain an action of binary functions on Yoneda identifications that computes
on both arguments using one of the two sides in the Gray interchanger diagram

```text
                      ap (r ↦ f x r) q
                 f x y -------------> f x y'
                   |                    |
                   |                    |
  ap (r ↦ f r y) p |                    | ap (r ↦ f r y') p
                   |                    |
                   ∨                    ∨
                 f x' y ------------> f x' y'
                      ap (r ↦ f x' r) q
```

and the fact that the concatenation operation on Yoneda identifications is
two-sided strictly unital.

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

  ap-binary-yoneda-Id :
    {x x' : A} (p : x =ʸ x') {y y' : B} (q : y =ʸ y')  f x y =ʸ f x' y'
  ap-binary-yoneda-Id {x} {x'} p {y} {y'} q =
    ap-yoneda-Id  z  f z y) p ∙ʸ ap-yoneda-Id (f x') q

  left-unit-ap-binary-yoneda-Id :
    {x : A} {y y' : B} (q : y =ʸ y') 
    ap-binary-yoneda-Id reflʸ q  ap-yoneda-Id (f x) q
  left-unit-ap-binary-yoneda-Id q = refl

  right-unit-ap-binary-yoneda-Id :
    {x x' : A} (p : x =ʸ x') {y : B} 
    ap-binary-yoneda-Id p reflʸ  ap-yoneda-Id  z  f z y) p
  right-unit-ap-binary-yoneda-Id p = refl
```

### Transport along Yoneda identifications

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

  tr-yoneda-Id : {x y : A}  x =ʸ y  B x  B y
  tr-yoneda-Id = tr B  eq-yoneda-eq

  compute-tr-refl-yoneda-Id : {x : A}  tr-yoneda-Id (reflʸ {x = x})  id
  compute-tr-refl-yoneda-Id = refl
```

### Standard function extensionality with respect to Yoneda identifications

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

  htpy-yoneda-eq : f =ʸ g  f ~ g
  htpy-yoneda-eq = htpy-eq  eq-yoneda-eq

  yoneda-eq-htpy : f ~ g  f =ʸ g
  yoneda-eq-htpy = yoneda-eq-eq  eq-htpy

  equiv-htpy-yoneda-eq : (f =ʸ g)  (f ~ g)
  equiv-htpy-yoneda-eq = equiv-funext ∘e equiv-eq-yoneda-eq

  equiv-yoneda-eq-htpy : (f ~ g)  (f =ʸ g)
  equiv-yoneda-eq-htpy = equiv-yoneda-eq-eq ∘e equiv-eq-htpy

  funext-yoneda-Id : is-equiv htpy-yoneda-eq
  funext-yoneda-Id = is-equiv-map-equiv equiv-htpy-yoneda-eq
```

### Standard univalence with respect to Yoneda identifications

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

  map-yoneda-eq : A =ʸ B  A  B
  map-yoneda-eq = map-eq  eq-yoneda-eq

  equiv-yoneda-eq : A =ʸ B  A  B
  equiv-yoneda-eq = equiv-eq  eq-yoneda-eq

  yoneda-eq-equiv : A  B  A =ʸ B
  yoneda-eq-equiv = yoneda-eq-eq  eq-equiv

  equiv-equiv-yoneda-eq : (A =ʸ B)  (A  B)
  equiv-equiv-yoneda-eq = equiv-univalence ∘e equiv-eq-yoneda-eq

  is-equiv-equiv-yoneda-eq : is-equiv equiv-yoneda-eq
  is-equiv-equiv-yoneda-eq = is-equiv-map-equiv equiv-equiv-yoneda-eq

  equiv-yoneda-eq-equiv : (A  B)  (A =ʸ B)
  equiv-yoneda-eq-equiv = equiv-yoneda-eq-eq ∘e equiv-eq-equiv A B

  is-equiv-yoneda-eq-equiv : is-equiv yoneda-eq-equiv
  is-equiv-yoneda-eq-equiv = is-equiv-map-equiv equiv-yoneda-eq-equiv
```

### Whiskering of Yoneda identifications

```agda
module _
  {l : Level} {A : UU l} {x y z : A}
  where

  left-whisker-concat-yoneda-Id :
    (p : x =ʸ y) {q r : y =ʸ z}  q =ʸ r  p ∙ʸ q =ʸ p ∙ʸ r
  left-whisker-concat-yoneda-Id p β = ap-yoneda-Id (p ∙ʸ_) β

  right-whisker-concat-yoneda-Id :
    {p q : x =ʸ y}  p =ʸ q  (r : y =ʸ z)  p ∙ʸ r =ʸ q ∙ʸ r
  right-whisker-concat-yoneda-Id α r = ap-yoneda-Id (_∙ʸ r) α
```

### Horizontal concatenation of Yoneda identifications

We define horizontal concatenation in such a way that it computes as left
whiskering when the left-hand argument is `refl`, and computes as right
whiskering when the right-hand argument is `refl`.

```agda
module _
  {l : Level} {A : UU l} {x y z : A}
  where

  horizontal-concat-yoneda-Id² :
    {p q : x =ʸ y}  p =ʸ q  {u v : y =ʸ z}  u =ʸ v  p ∙ʸ u =ʸ q ∙ʸ v
  horizontal-concat-yoneda-Id² = ap-binary-yoneda-Id (_∙ʸ_)

  compute-left-horizontal-concat-yoneda-Id² :
    {p : x =ʸ y} {u v : y =ʸ z} (β : u =ʸ v) 
    horizontal-concat-yoneda-Id² reflʸ β 
    left-whisker-concat-yoneda-Id p β
  compute-left-horizontal-concat-yoneda-Id² β = refl

  compute-right-horizontal-concat-yoneda-Id² :
    {p q : x =ʸ y} (α : p =ʸ q) {u : y =ʸ z} 
    horizontal-concat-yoneda-Id² α (reflʸ {x = u}) 
    right-whisker-concat-yoneda-Id α u
  compute-right-horizontal-concat-yoneda-Id² α = refl

module _
  {l : Level} {A : UU l} {x y : A}
  where

  left-unit-horizontal-concat-yoneda-Id² :
    {p q : x =ʸ y} (α : p =ʸ q) 
    horizontal-concat-yoneda-Id² reflʸ α  α
  left-unit-horizontal-concat-yoneda-Id² = compute-ap-id-yoneda-Id

  right-unit-horizontal-concat-yoneda-Id² :
    {p q : x =ʸ y} (α : p =ʸ q) 
    horizontal-concat-yoneda-Id² α (reflʸ {x = reflʸ})  α
  right-unit-horizontal-concat-yoneda-Id² = compute-ap-id-yoneda-Id
```

Since concatenation on Yoneda identifications is strictly associative, the
composites

```text
  horizontal-concat-yoneda-Id² (horizontal-concat-yoneda-Id² α β) γ
```

and

```text
  horizontal-concat-yoneda-Id² α (horizontal-concat-yoneda-Id² β γ)
```

inhabit the same type. Therefore, we can pose the question of whether the
horizontal concatenation operation is associative, which it is, albeit weakly:

```agda
module _
  {l : Level} {A : UU l} {x y z w : A}
  where

  assoc-horizontal-concat-yoneda-Id² :
    {p p' : x =ʸ y} (α : p =ʸ p')
    {q q' : y =ʸ z} (β : q =ʸ q')
    {r r' : z =ʸ w} (γ : r =ʸ r') 
    horizontal-concat-yoneda-Id² (horizontal-concat-yoneda-Id² α β) γ 
    horizontal-concat-yoneda-Id² α (horizontal-concat-yoneda-Id² β γ)
  assoc-horizontal-concat-yoneda-Id² α {q} β {r} =
    ind-yoneda-Id
      ( λ _ γ 
        ( horizontal-concat-yoneda-Id² (horizontal-concat-yoneda-Id² α β) γ) 
        ( horizontal-concat-yoneda-Id² α (horizontal-concat-yoneda-Id² β γ)))
      ( ind-yoneda-Id
        ( λ _ β 
          ( horizontal-concat-yoneda-Id²
            ( horizontal-concat-yoneda-Id² α β)
            ( reflʸ {x = r})) 
          ( horizontal-concat-yoneda-Id²
            ( α)
            ( horizontal-concat-yoneda-Id² β (reflʸ {x = r}))))
        ( ind-yoneda-Id
          ( λ _ α 
            ( horizontal-concat-yoneda-Id²
              ( horizontal-concat-yoneda-Id² α (reflʸ {x = q}))
              ( reflʸ {x = r})) 
            ( horizontal-concat-yoneda-Id²
              ( α)
              ( horizontal-concat-yoneda-Id² (reflʸ {x = q}) (reflʸ {x = r}))))
          ( refl)
          ( α))
        ( β))
```

### Vertical concatenation of Yoneda identifications

```agda
module _
  {l : Level} {A : UU l} {x y : A}
  where

  vertical-concat-yoneda-Id² :
    {p q r : x =ʸ y}  p =ʸ q  q =ʸ r  p =ʸ r
  vertical-concat-yoneda-Id² α β = α ∙ʸ β
```

## See also

- [The strictly involutive identity types](foundation.strictly-involutive-identity-types.md)
  for an identity relation that is strictly involutive, and one-sided unital.
- [The computational identity types](foundation.computational-identity-types.md)
  for an identity relation that is strictly involutive, associative, and
  one-sided unital.

## References

{{#bibliography}} {{#reference Esc19DefinitionsEquivalence}}