# Coproduct types

```agda
module foundation.coproduct-types where

open import foundation-core.coproduct-types public
```

<details><summary>Imports</summary>

```agda
open import foundation.action-on-identifications-functions
open import foundation.dependent-pair-types
open import foundation.negated-equality
open import foundation.noncontractible-types
open import foundation.subuniverses
open import foundation.unit-type
open import foundation.universe-levels

open import foundation-core.contractible-types
open import foundation-core.empty-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.injective-maps
open import foundation-core.negation
open import foundation-core.propositions
```

</details>

### The predicates of being in the left and in the right summand

```agda
module _
  {l1 l2 : Level} {X : UU l1} {Y : UU l2}
  where

  is-left-Prop : X + Y  Prop lzero
  is-left-Prop (inl x) = unit-Prop
  is-left-Prop (inr x) = empty-Prop

  is-left : X + Y  UU lzero
  is-left x = type-Prop (is-left-Prop x)

  is-prop-is-left : (x : X + Y)  is-prop (is-left x)
  is-prop-is-left x = is-prop-type-Prop (is-left-Prop x)

  is-right-Prop : X + Y  Prop lzero
  is-right-Prop (inl x) = empty-Prop
  is-right-Prop (inr x) = unit-Prop

  is-right : X + Y  UU lzero
  is-right x = type-Prop (is-right-Prop x)

  is-prop-is-right : (x : X + Y)  is-prop (is-right x)
  is-prop-is-right x = is-prop-type-Prop (is-right-Prop x)

  is-left-or-is-right : (x : X + Y)  is-left x + is-right x
  is-left-or-is-right (inl x) = inl star
  is-left-or-is-right (inr x) = inr star
```

### The predicate that a subuniverse is closed under coproducts

We formulate a variant with three subuniverses and the more traditional variant
using a single subuniverse

```agda
is-closed-under-coproducts-subuniverses :
  {l1 l2 l3 l4 l5 : Level} (P : subuniverse l1 l2) (Q : subuniverse l3 l4) 
  subuniverse (l1  l3) l5  UU (lsuc l1  l2  lsuc l3  l4  l5)
is-closed-under-coproducts-subuniverses {l1} {l2} {l3} P Q R =
  {X : UU l1} {Y : UU l3} 
  is-in-subuniverse P X  is-in-subuniverse Q Y  is-in-subuniverse R (X + Y)

is-closed-under-coproducts-subuniverse :
  {l1 l2 : Level} (P : subuniverse l1 l2)  UU (lsuc l1  l2)
is-closed-under-coproducts-subuniverse P =
  is-closed-under-coproducts-subuniverses P P P
```

## Properties

### The left and right inclusions are injective

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

  is-injective-inl : is-injective {B = A + B} inl
  is-injective-inl refl = refl

  is-injective-inr : is-injective {B = A + B} inr
  is-injective-inr refl = refl

  neq-inl-inr : {x : A} {y : B}  inl x  inr y
  neq-inl-inr ()

  neq-inr-inl : {x : B} {y : A}  inr x  inl y
  neq-inr-inl ()
```

### The type of left elements is equivalent to the left summand

```agda
module _
  {l1 l2 : Level} {X : UU l1} {Y : UU l2}
  where

  map-equiv-left-summand : Σ (X + Y) is-left  X
  map-equiv-left-summand (inl x , star) = x
  map-equiv-left-summand (inr x , ())

  map-inv-equiv-left-summand : X  Σ (X + Y) is-left
  pr1 (map-inv-equiv-left-summand x) = inl x
  pr2 (map-inv-equiv-left-summand x) = star

  is-section-map-inv-equiv-left-summand :
    (map-equiv-left-summand  map-inv-equiv-left-summand) ~ id
  is-section-map-inv-equiv-left-summand x = refl

  is-retraction-map-inv-equiv-left-summand :
    (map-inv-equiv-left-summand  map-equiv-left-summand) ~ id
  is-retraction-map-inv-equiv-left-summand (inl x , star) = refl
  is-retraction-map-inv-equiv-left-summand (inr x , ())

  equiv-left-summand : (Σ (X + Y) is-left)  X
  pr1 equiv-left-summand = map-equiv-left-summand
  pr2 equiv-left-summand =
    is-equiv-is-invertible
      map-inv-equiv-left-summand
      is-section-map-inv-equiv-left-summand
      is-retraction-map-inv-equiv-left-summand
```

### The type of right elements is equivalent to the right summand

```agda
module _
  {l1 l2 : Level} {X : UU l1} {Y : UU l2}
  where

  map-equiv-right-summand : Σ (X + Y) is-right  Y
  map-equiv-right-summand (inl x , ())
  map-equiv-right-summand (inr x , star) = x

  map-inv-equiv-right-summand : Y  Σ (X + Y) is-right
  pr1 (map-inv-equiv-right-summand y) = inr y
  pr2 (map-inv-equiv-right-summand y) = star

  is-section-map-inv-equiv-right-summand :
    map-equiv-right-summand  map-inv-equiv-right-summand ~ id
  is-section-map-inv-equiv-right-summand y = refl

  is-retraction-map-inv-equiv-right-summand :
    map-inv-equiv-right-summand  map-equiv-right-summand ~ id
  is-retraction-map-inv-equiv-right-summand (inl x , ())
  is-retraction-map-inv-equiv-right-summand (inr x , star) = refl

  equiv-right-summand : Σ (X + Y) is-right  Y
  pr1 equiv-right-summand = map-equiv-right-summand
  pr2 equiv-right-summand =
    is-equiv-is-invertible
      map-inv-equiv-right-summand
      is-section-map-inv-equiv-right-summand
      is-retraction-map-inv-equiv-right-summand
```

### Coproducts of contractible types are not contractible

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

  abstract
    is-not-contractible-coproduct-is-contr :
      is-contr A  is-contr B  is-not-contractible (A + B)
    is-not-contractible-coproduct-is-contr HA HB HAB =
      neq-inl-inr {x = center HA} {y = center HB} (eq-is-contr HAB)
```

### Coproducts of mutually exclusive propositions are propositions

```agda
module _
  {l1 l2 : Level} {P : UU l1} {Q : UU l2}
  where

  abstract
    all-elements-equal-coproduct :
      (P  ¬ Q)  all-elements-equal P  all-elements-equal Q 
      all-elements-equal (P + Q)
    all-elements-equal-coproduct f is-prop-P is-prop-Q (inl p) (inl p') =
      ap inl (is-prop-P p p')
    all-elements-equal-coproduct f is-prop-P is-prop-Q (inl p) (inr q') =
      ex-falso (f p q')
    all-elements-equal-coproduct f is-prop-P is-prop-Q (inr q) (inl p') =
      ex-falso (f p' q)
    all-elements-equal-coproduct f is-prop-P is-prop-Q (inr q) (inr q') =
      ap inr (is-prop-Q q q')

  abstract
    is-prop-coproduct : (P  ¬ Q)  is-prop P  is-prop Q  is-prop (P + Q)
    is-prop-coproduct f is-prop-P is-prop-Q =
      is-prop-all-elements-equal
        ( all-elements-equal-coproduct f
          ( eq-is-prop' is-prop-P)
          ( eq-is-prop' is-prop-Q))

coproduct-Prop :
  {l1 l2 : Level} (P : Prop l1) (Q : Prop l2) 
  (type-Prop P  ¬ (type-Prop Q))  Prop (l1  l2)
pr1 (coproduct-Prop P Q H) =
  type-Prop P + type-Prop Q
pr2 (coproduct-Prop P Q H) =
  is-prop-coproduct H (is-prop-type-Prop P) (is-prop-type-Prop Q)
```