# Equivalences on `Maybe`

```agda
module foundation.equivalences-maybe where
```

<details><summary>Imports</summary>

```agda
open import foundation.action-on-identifications-functions
open import foundation.dependent-pair-types
open import foundation.equality-coproduct-types
open import foundation.equivalence-extensionality
open import foundation.equivalences
open import foundation.functoriality-coproduct-types
open import foundation.maybe
open import foundation.unit-type
open import foundation.universal-property-maybe
open import foundation.universe-levels

open import foundation-core.coproduct-types
open import foundation-core.embeddings
open import foundation-core.empty-types
open import foundation-core.equality-dependent-pair-types
open import foundation-core.function-types
open import foundation-core.homotopies
open import foundation-core.identity-types
open import foundation-core.injective-maps
open import foundation-core.propositions
open import foundation-core.sets
```

</details>

## Idea

For any two types `X` and `Y`, we have `(X ≃ Y) ↔ (Maybe X ≃ Maybe Y)`.

## Definition

### The action of the Maybe modality on equivalences

```agda
equiv-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : X  Y)  Maybe X  Maybe Y
equiv-Maybe e = equiv-coproduct e id-equiv
```

### Equivalences of Maybe-structures on a type

```agda
equiv-maybe-structure :
  {l1 : Level} {X : UU l1} (Y Z : maybe-structure X)  UU l1
equiv-maybe-structure Y Z =
  Σ (pr1 Y  pr1 Z)  e  htpy-equiv (pr2 Y) (pr2 Z ∘e equiv-Maybe e))

id-equiv-maybe-structure :
  {l1 : Level} {X : UU l1} (Y : maybe-structure X)  equiv-maybe-structure Y Y
id-equiv-maybe-structure Y =
  pair id-equiv (ind-Maybe (pair refl-htpy refl))

equiv-eq-maybe-structure :
  {l1 : Level} {X : UU l1} (Y Z : maybe-structure X) 
  Y  Z  equiv-maybe-structure Y Z
equiv-eq-maybe-structure Y .Y refl = id-equiv-maybe-structure Y
```

## Properties

### If `f : Maybe X → Maybe Y` is an injective map and `f (inl x)` is an exception, then `f exception` is not an exception

```agda
abstract
  is-not-exception-injective-map-exception-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
    is-injective f  (x : X)  is-exception-Maybe (f (inl x)) 
    is-not-exception-Maybe (f exception-Maybe)
  is-not-exception-injective-map-exception-Maybe is-inj-f x p q =
    is-not-exception-unit-Maybe x (is-inj-f (p  inv q))

abstract
  is-not-exception-map-equiv-exception-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
    is-exception-Maybe (map-equiv e (inl x)) 
    is-not-exception-Maybe (map-equiv e exception-Maybe)
  is-not-exception-map-equiv-exception-Maybe e =
    is-not-exception-injective-map-exception-Maybe (is-injective-equiv e)

abstract
  is-not-exception-emb-exception-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y)
    (x : X)  is-exception-Maybe (map-emb e (inl x)) 
    is-not-exception-Maybe (map-emb e exception-Maybe)
  is-not-exception-emb-exception-Maybe e =
    is-not-exception-injective-map-exception-Maybe (is-injective-emb e)
```

### If `f` is injective and `f (inl x)` is an exception, then `f exception` is a value

```agda
is-value-injective-map-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  is-injective f  (x : X)  is-exception-Maybe (f (inl x)) 
  is-value-Maybe (f exception-Maybe)
is-value-injective-map-exception-Maybe {f = f} is-inj-f x H =
  is-value-is-not-exception-Maybe
    ( f exception-Maybe)
    ( is-not-exception-injective-map-exception-Maybe is-inj-f x H)

value-injective-map-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  is-injective f  (x : X)  is-exception-Maybe (f (inl x))  Y
value-injective-map-exception-Maybe {f = f} is-inj-f x H =
  value-is-value-Maybe
    ( f exception-Maybe)
    ( is-value-injective-map-exception-Maybe is-inj-f x H)

comp-injective-map-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  (is-inj-f : is-injective f) (x : X) (H : is-exception-Maybe (f (inl x))) 
  inl (value-injective-map-exception-Maybe is-inj-f x H) 
  f exception-Maybe
comp-injective-map-exception-Maybe {f = f} is-inj-f x H =
  eq-is-value-Maybe
    ( f exception-Maybe)
    ( is-value-injective-map-exception-Maybe is-inj-f x H)
```

### For any equivalence `e : Maybe X ≃ Maybe Y`, if `e (inl x)` is an exception, then `e exception` is a value

```agda
is-value-map-equiv-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  is-exception-Maybe (map-equiv e (inl x)) 
  is-value-Maybe (map-equiv e exception-Maybe)
is-value-map-equiv-exception-Maybe e x H =
  is-value-is-not-exception-Maybe
    ( map-equiv e exception-Maybe)
    ( is-not-exception-map-equiv-exception-Maybe e x H)

value-map-equiv-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  is-exception-Maybe (map-equiv e (inl x))  Y
value-map-equiv-exception-Maybe e x H =
  value-is-value-Maybe
    ( map-equiv e exception-Maybe)
    ( is-value-map-equiv-exception-Maybe e x H)

compute-map-equiv-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  (H : is-exception-Maybe (map-equiv e (inl x))) 
  inl (value-map-equiv-exception-Maybe e x H)  map-equiv e exception-Maybe
compute-map-equiv-exception-Maybe e x H =
  eq-is-value-Maybe
    ( map-equiv e exception-Maybe)
    ( is-value-map-equiv-exception-Maybe e x H)
```

### Injective maps `Maybe X → Maybe Y` can be restricted to maps `X → Y`

```agda
restrict-injective-map-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  is-injective f  (x : X) (u : Maybe Y) (p : f (inl x)  u)  Y
restrict-injective-map-Maybe' {f = f} is-inj-f x (inl y) p = y
restrict-injective-map-Maybe' {f = f} is-inj-f x (inr star) p =
  value-injective-map-exception-Maybe is-inj-f x p

restrict-injective-map-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  is-injective f  X  Y
restrict-injective-map-Maybe {f = f} is-inj-f x =
  restrict-injective-map-Maybe' is-inj-f x (f (inl x)) refl

compute-restrict-injective-map-is-exception-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  (is-inj-f : is-injective f) (x : X) (u : Maybe Y) (p : f (inl x)  u) 
  is-exception-Maybe (f (inl x)) 
  inl (restrict-injective-map-Maybe' is-inj-f x u p)  f exception-Maybe
compute-restrict-injective-map-is-exception-Maybe'
  {f = f} is-inj-f x (inl y) p q =
  ex-falso (is-not-exception-unit-Maybe y (inv p  q))
compute-restrict-injective-map-is-exception-Maybe'
  {f = f} is-inj-f x (inr star) p q =
  comp-injective-map-exception-Maybe is-inj-f x p

compute-restrict-injective-map-is-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  (is-inj-f : is-injective f) (x : X)  is-exception-Maybe (f (inl x)) 
  inl (restrict-injective-map-Maybe is-inj-f x)  f exception-Maybe
compute-restrict-injective-map-is-exception-Maybe {f = f} is-inj-f x =
  compute-restrict-injective-map-is-exception-Maybe' is-inj-f x (f (inl x)) refl

compute-restrict-injective-map-is-not-exception-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  (is-inj-f : is-injective f) (x : X) (u : Maybe Y) (p : f (inl x)  u) 
  is-not-exception-Maybe (f (inl x)) 
  inl (restrict-injective-map-Maybe' is-inj-f x u p)  f (inl x)
compute-restrict-injective-map-is-not-exception-Maybe'
  is-inj-f x (inl y) p H =
  inv p
compute-restrict-injective-map-is-not-exception-Maybe'
  is-inj-f x (inr star) p H =
  ex-falso (H p)

compute-restrict-injective-map-is-not-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} {f : Maybe X  Maybe Y} 
  (is-inj-f : is-injective f) (x : X)  is-not-exception-Maybe (f (inl x)) 
  inl (restrict-injective-map-Maybe is-inj-f x)  f (inl x)
compute-restrict-injective-map-is-not-exception-Maybe {f = f} is-inj-f x =
  compute-restrict-injective-map-is-not-exception-Maybe' is-inj-f x (f (inl x))
    refl
```

### Any equivalence `Maybe X ≃ Maybe Y` induces a map `X → Y`

We don't use with-abstraction to keep full control over the definitional
equalities, so we give the definition in two steps. After the definition is
complete, we also prove two computation rules. Since we will prove computation
rules, we make the definition abstract.

```agda
map-equiv-equiv-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y)
  (x : X) (u : Maybe Y) (p : map-equiv e (inl x)  u)  Y
map-equiv-equiv-Maybe' e =
  restrict-injective-map-Maybe' (is-injective-equiv e)

map-equiv-equiv-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y)  X  Y
map-equiv-equiv-Maybe e =
  restrict-injective-map-Maybe (is-injective-equiv e)

compute-map-equiv-equiv-is-exception-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  (u : Maybe Y) (p : map-equiv e (inl x)  u) 
  is-exception-Maybe (map-equiv e (inl x)) 
  inl (map-equiv-equiv-Maybe' e x u p)  map-equiv e exception-Maybe
compute-map-equiv-equiv-is-exception-Maybe' e =
  compute-restrict-injective-map-is-exception-Maybe' (is-injective-equiv e)

compute-map-equiv-equiv-is-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  is-exception-Maybe (map-equiv e (inl x)) 
  inl (map-equiv-equiv-Maybe e x)  map-equiv e exception-Maybe
compute-map-equiv-equiv-is-exception-Maybe e x =
  compute-map-equiv-equiv-is-exception-Maybe' e x (map-equiv e (inl x)) refl

compute-map-equiv-equiv-is-not-exception-Maybe' :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  (u : Maybe Y) (p : map-equiv e (inl x)  u) 
  is-not-exception-Maybe (map-equiv e (inl x)) 
  inl (map-equiv-equiv-Maybe' e x u p)  map-equiv e (inl x)
compute-map-equiv-equiv-is-not-exception-Maybe' e x (inl y) p H =
  inv p
compute-map-equiv-equiv-is-not-exception-Maybe' e x (inr star) p H =
  ex-falso (H p)

compute-map-equiv-equiv-is-not-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (x : X) 
  is-not-exception-Maybe (map-equiv e (inl x)) 
  inl (map-equiv-equiv-Maybe e x)  map-equiv e (inl x)
compute-map-equiv-equiv-is-not-exception-Maybe e x =
  compute-map-equiv-equiv-is-not-exception-Maybe' e x (map-equiv e (inl x)) refl
```

### Any equivalence `Maybe X ≃ Maybe Y` induces a map `Y → X`

```agda
map-inv-equiv-equiv-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y)  Y  X
map-inv-equiv-equiv-Maybe e =
  map-equiv-equiv-Maybe (inv-equiv e)

compute-map-inv-equiv-equiv-is-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (y : Y) 
  is-exception-Maybe (map-inv-equiv e (inl y)) 
  inl (map-inv-equiv-equiv-Maybe e y)  map-inv-equiv e exception-Maybe
compute-map-inv-equiv-equiv-is-exception-Maybe e =
  compute-map-equiv-equiv-is-exception-Maybe (inv-equiv e)

compute-map-inv-equiv-equiv-is-not-exception-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) (y : Y) 
  ( f : is-not-exception-Maybe (map-inv-equiv e (inl y))) 
  inl (map-inv-equiv-equiv-Maybe e y)  map-inv-equiv e (inl y)
compute-map-inv-equiv-equiv-is-not-exception-Maybe e =
  compute-map-equiv-equiv-is-not-exception-Maybe (inv-equiv e)
```

### The map `map-inv-equiv-equiv-Maybe e` is a section of `map-equiv-equiv-Maybe e`

```agda
abstract
  is-section-map-inv-equiv-equiv-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) 
    (map-equiv-equiv-Maybe e  map-inv-equiv-equiv-Maybe e) ~ id
  is-section-map-inv-equiv-equiv-Maybe e y with
    is-decidable-is-exception-Maybe (map-inv-equiv e (inl y))
  ... | inl p =
    is-injective-unit-Maybe
      ( ( compute-map-equiv-equiv-is-exception-Maybe e
          ( map-inv-equiv-equiv-Maybe e y)
          ( ( ap
              ( map-equiv e)
              ( compute-map-inv-equiv-equiv-is-exception-Maybe e y p)) 
            ( is-section-map-inv-equiv e exception-Maybe))) 
        ( ( ap (map-equiv e) (inv p)) 
          ( is-section-map-inv-equiv e (inl y))))
  ... | inr f =
    is-injective-unit-Maybe
      ( ( compute-map-equiv-equiv-is-not-exception-Maybe e
          ( map-inv-equiv-equiv-Maybe e y)
          ( is-not-exception-is-value-Maybe
            ( map-equiv e (inl (map-inv-equiv-equiv-Maybe e y)))
            ( pair y
              ( inv
                ( ( ap
                    ( map-equiv e)
                    ( compute-map-inv-equiv-equiv-is-not-exception-Maybe
                        e y f)) 
                  ( is-section-map-inv-equiv e (inl y))))))) 
        ( ( ap
            ( map-equiv e)
            ( compute-map-inv-equiv-equiv-is-not-exception-Maybe e y f)) 
          ( is-section-map-inv-equiv e (inl y))))
```

### The map `map-inv-equiv-equiv-Maybe e` is a retraction of the map `map-equiv-equiv-Maybe e`

```agda
abstract
  is-retraction-map-inv-equiv-equiv-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) 
    (map-inv-equiv-equiv-Maybe e  map-equiv-equiv-Maybe e) ~ id
  is-retraction-map-inv-equiv-equiv-Maybe e x with
    is-decidable-is-exception-Maybe (map-equiv e (inl x))
  ... | inl p =
    is-injective-unit-Maybe
      ( ( compute-map-inv-equiv-equiv-is-exception-Maybe e
          ( map-equiv-equiv-Maybe e x)
          ( ( ap
              ( map-inv-equiv e)
              ( compute-map-equiv-equiv-is-exception-Maybe e x p)) 
            ( is-retraction-map-inv-equiv e exception-Maybe))) 
        ( ( ap (map-inv-equiv e) (inv p)) 
          ( is-retraction-map-inv-equiv e (inl x))))
  ... | inr f =
    is-injective-unit-Maybe
      ( ( compute-map-inv-equiv-equiv-is-not-exception-Maybe e
          ( map-equiv-equiv-Maybe e x)
          ( is-not-exception-is-value-Maybe
            ( map-inv-equiv e (inl (map-equiv-equiv-Maybe e x)))
            ( pair x
              ( inv
                ( ( ap
                    ( map-inv-equiv e)
                    ( compute-map-equiv-equiv-is-not-exception-Maybe
                        e x f)) 
                  ( is-retraction-map-inv-equiv e (inl x))))))) 
        ( ( ap
            ( map-inv-equiv e)
            ( compute-map-equiv-equiv-is-not-exception-Maybe e x f)) 
          ( is-retraction-map-inv-equiv e (inl x))))
```

### The function `map-equiv-equiv-Maybe` is an equivalence

```agda
abstract
  is-equiv-map-equiv-equiv-Maybe :
    {l1 l2 : Level} {X : UU l1} {Y : UU l2} (e : Maybe X  Maybe Y) 
    is-equiv (map-equiv-equiv-Maybe e)
  is-equiv-map-equiv-equiv-Maybe e =
    is-equiv-is-invertible
      ( map-inv-equiv-equiv-Maybe e)
      ( is-section-map-inv-equiv-equiv-Maybe e)
      ( is-retraction-map-inv-equiv-equiv-Maybe e)

equiv-equiv-Maybe :
  {l1 l2 : Level} {X : UU l1} {Y : UU l2}  (Maybe X  Maybe Y)  (X  Y)
pr1 (equiv-equiv-Maybe e) = map-equiv-equiv-Maybe e
pr2 (equiv-equiv-Maybe e) = is-equiv-map-equiv-equiv-Maybe e

compute-equiv-equiv-Maybe-id-equiv :
  {l1 : Level} {X : UU l1} 
  equiv-equiv-Maybe id-equiv  id-equiv {A = X}
compute-equiv-equiv-Maybe-id-equiv = eq-htpy-equiv refl-htpy
```

### For any set `X`, the type of automorphisms on `X` is equivalent to the type of automorphisms on `Maybe X` that fix the exception

```agda
module _
  {l : Level} (X : Set l)
  where

  extend-equiv-Maybe :
    (type-Set X  type-Set X) 
    ( Σ ( Maybe (type-Set X)  Maybe (type-Set X))
        ( λ e  map-equiv e (inr star)  inr star))
  pr1 (pr1 extend-equiv-Maybe f) = equiv-coproduct f id-equiv
  pr2 (pr1 extend-equiv-Maybe f) = refl
  pr2 extend-equiv-Maybe =
    is-equiv-is-invertible
      ( λ f  pr1 (retraction-equiv-coproduct (pr1 f) id-equiv (p f)))
      ( λ f 
        ( eq-pair-Σ
          ( inv
            ( eq-htpy-equiv
              ( pr2 (retraction-equiv-coproduct (pr1 f) id-equiv (p f)))))
          ( eq-is-prop
            ( pr2
              ( Id-Prop
                ( pair
                  ( Maybe (type-Set X))
                  ( is-set-coproduct (is-set-type-Set X) is-set-unit))
                ( map-equiv (pr1 f) (inr star))
                ( inr star))))))
      ( λ f  eq-equiv-eq-map-equiv refl)
    where
    p :
      ( f :
        ( Σ ( Maybe (type-Set X)  Maybe (type-Set X))
            ( λ e  map-equiv e (inr star)  inr star)))
      ( b : unit) 
      map-equiv (pr1 f) (inr b)  inr b
    p f star = pr2 f

  computation-extend-equiv-Maybe :
    (f : type-Set X  type-Set X) (x y : type-Set X)  map-equiv f x  y 
    map-equiv (pr1 (map-equiv extend-equiv-Maybe f)) (inl x)  inl y
  computation-extend-equiv-Maybe f x y p = ap inl p

  computation-inv-extend-equiv-Maybe :
    (f : Maybe (type-Set X)  Maybe (type-Set X))
    (p : map-equiv f (inr star)  inr star) (x : type-Set X) 
    inl (map-equiv (map-inv-equiv extend-equiv-Maybe (pair f p)) x) 
    map-equiv f (inl x)
  computation-inv-extend-equiv-Maybe f p x =
    htpy-eq-equiv
      ( pr1 (pair-eq-Σ (pr2 (pr1 (pr2 extend-equiv-Maybe)) (pair f p))))
      ( inl x)

  comp-extend-equiv-Maybe :
    (f g : type-Set X  type-Set X) 
    htpy-equiv
      ( pr1 (map-equiv extend-equiv-Maybe (f ∘e g)))
      ( ( pr1 (map-equiv extend-equiv-Maybe f)) ∘e
        ( pr1 (map-equiv extend-equiv-Maybe g)))
  comp-extend-equiv-Maybe f g =
    preserves-comp-map-coproduct (map-equiv g) (map-equiv f) id id
```