# Set truncations

```agda
{-# OPTIONS --lossy-unification #-}

module foundation.set-truncations where
```

<details><summary>Imports</summary>

```agda
open import foundation.dependent-pair-types
open import foundation.effective-maps-equivalence-relations
open import foundation.equality-coproduct-types
open import foundation.functoriality-cartesian-product-types
open import foundation.functoriality-coproduct-types
open import foundation.mere-equality
open import foundation.postcomposition-functions
open import foundation.reflecting-maps-equivalence-relations
open import foundation.sets
open import foundation.slice
open import foundation.surjective-maps
open import foundation.truncations
open import foundation.uniqueness-set-truncations
open import foundation.unit-type
open import foundation.universal-property-coproduct-types
open import foundation.universal-property-dependent-pair-types
open import foundation.universal-property-image
open import foundation.universal-property-set-quotients
open import foundation.universal-property-set-truncation
open import foundation.universe-levels

open import foundation-core.cartesian-product-types
open import foundation-core.contractible-types
open import foundation-core.coproduct-types
open import foundation-core.embeddings
open import foundation-core.empty-types
open import foundation-core.equivalences
open import foundation-core.function-types
open import foundation-core.functoriality-dependent-function-types
open import foundation-core.functoriality-dependent-pair-types
open import foundation-core.functoriality-function-types
open import foundation-core.homotopies
open import foundation-core.identity-types
open import foundation-core.propositions
open import foundation-core.truncation-levels
```

</details>

## Idea

The **set truncation** of a type `A` is a map `η : A → trunc-Set A` that
satisfies
[the universal property of set truncations](foundation.universal-property-set-truncation.md).

## Definition

```agda
type-trunc-Set : {l : Level}  UU l  UU l
type-trunc-Set = type-trunc zero-𝕋

is-set-type-trunc-Set : {l : Level} {A : UU l}  is-set (type-trunc-Set A)
is-set-type-trunc-Set = is-trunc-type-trunc

trunc-Set : {l : Level}  UU l  Set l
trunc-Set = trunc zero-𝕋

unit-trunc-Set : {l : Level} {A : UU l}  A  type-trunc-Set A
unit-trunc-Set = unit-trunc

is-set-truncation-trunc-Set :
  {l1 : Level} (A : UU l1)  is-set-truncation (trunc-Set A) unit-trunc-Set
is-set-truncation-trunc-Set A = is-truncation-trunc
```

## Properties

### The dependent universal property of set truncations

```agda
dependent-universal-property-trunc-Set :
  {l1 : Level} {A : UU l1} 
  dependent-universal-property-set-truncation (trunc-Set A) unit-trunc-Set
dependent-universal-property-trunc-Set = dependent-universal-property-trunc

equiv-dependent-universal-property-trunc-Set :
  {l1 l2 : Level} {A : UU l1} (B : type-trunc-Set A  Set l2) 
  ((x : type-trunc-Set A)  type-Set (B x)) 
  ((a : A)  type-Set (B (unit-trunc-Set a)))
equiv-dependent-universal-property-trunc-Set =
  equiv-dependent-universal-property-trunc

module _
  {l1 l2 : Level} {A : UU l1} (B : type-trunc-Set A  Set l2)
  (f : (x : A)  type-Set (B (unit-trunc-Set x)))
  where

  Π-trunc-Set : UU (l1  l2)
  Π-trunc-Set =
    Σ ( (x : type-trunc-Set A)  type-Set (B x))
      ( λ g  g  unit-trunc-Set ~ f)

  function-dependent-universal-property-trunc-Set :
    (x : type-trunc-Set A)  type-Set (B x)
  function-dependent-universal-property-trunc-Set =
    function-dependent-universal-property-trunc B f

  compute-dependent-universal-property-trunc-Set :
    function-dependent-universal-property-trunc-Set  unit-trunc-Set ~ f
  compute-dependent-universal-property-trunc-Set =
    htpy-dependent-universal-property-trunc B f

  apply-dependent-universal-property-trunc-Set' :
    (x : type-trunc-Set A)  type-Set (B x)
  apply-dependent-universal-property-trunc-Set' =
    map-inv-equiv (equiv-dependent-universal-property-trunc-Set B) f
```

### The universal property of set truncations

```agda
universal-property-trunc-Set :
  {l1 : Level} (A : UU l1) 
  universal-property-set-truncation (trunc-Set A) (unit-trunc-Set)
universal-property-trunc-Set A = universal-property-trunc zero-𝕋 A

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

  equiv-universal-property-trunc-Set :
    (type-trunc-Set A  type-Set B)  (A  type-Set B)
  equiv-universal-property-trunc-Set = equiv-universal-property-trunc A B

  apply-universal-property-trunc-Set :
    (t : type-trunc-Set A)  (A  type-Set B)  type-Set B
  apply-universal-property-trunc-Set t f = map-universal-property-trunc B f t

  map-universal-property-trunc-Set :
    (A  type-Set B)  hom-Set (trunc-Set A) B
  map-universal-property-trunc-Set = map-universal-property-trunc B

  triangle-universal-property-trunc-Set :
    (f : A  type-Set B) 
    map-universal-property-trunc-Set f  unit-trunc-Set ~ f
  triangle-universal-property-trunc-Set = triangle-universal-property-trunc B
  Map-trunc-Set : (f : A  type-Set B)  UU (l1  l2)
  Map-trunc-Set f =
    Σ (type-trunc-Set A  type-Set B)  g  g  unit-trunc-Set ~ f)

apply-universal-property-trunc-Set' :
  {l1 l2 : Level} {A : UU l1} (t : type-trunc-Set A) (B : Set l2) 
  (A  type-Set B)  type-Set B
apply-universal-property-trunc-Set' t B f =
  map-universal-property-trunc-Set B f t
```

### The set truncation of `X` is the set quotient by the mere equality relation

```agda
reflecting-map-mere-eq-unit-trunc-Set :
  {l : Level} (A : UU l) 
  reflecting-map-equivalence-relation
    ( mere-eq-equivalence-relation A)
    ( type-trunc-Set A)
reflecting-map-mere-eq-unit-trunc-Set A =
  pair unit-trunc-Set (reflects-mere-eq (trunc-Set A) unit-trunc-Set)

abstract
  is-set-quotient-trunc-Set :
    {l1 : Level} (A : UU l1) 
    is-set-quotient
      ( mere-eq-equivalence-relation A)
      ( trunc-Set A)
      ( reflecting-map-mere-eq-unit-trunc-Set A)
  is-set-quotient-trunc-Set A =
    is-set-quotient-is-set-truncation
      ( trunc-Set A)
      ( unit-trunc-Set)
      ( λ {l}  is-set-truncation-trunc-Set A)

module _
  {l : Level}
  where

  abstract
    is-surjective-and-effective-unit-trunc-Set :
      (A : UU l) 
      is-surjective-and-effective
        ( mere-eq-equivalence-relation A)
        ( unit-trunc-Set)
    is-surjective-and-effective-unit-trunc-Set A =
      is-surjective-and-effective-is-set-quotient
        ( mere-eq-equivalence-relation A)
        ( trunc-Set A)
        ( unit-trunc-Set ,
          reflects-mere-eq (trunc-Set A) unit-trunc-Set)
        ( λ {l}  is-set-quotient-trunc-Set A)

  abstract
    is-surjective-unit-trunc-Set :
      (A : UU l)  is-surjective (unit-trunc-Set {A = A})
    is-surjective-unit-trunc-Set A =
      pr1 (is-surjective-and-effective-unit-trunc-Set A)

  abstract
    is-effective-unit-trunc-Set :
      (A : UU l) 
      is-effective (mere-eq-equivalence-relation A) (unit-trunc-Set {A = A})
    is-effective-unit-trunc-Set A =
      pr2 (is-surjective-and-effective-unit-trunc-Set A)

  abstract
    apply-effectiveness-unit-trunc-Set :
      {A : UU l} {x y : A}  unit-trunc-Set x  unit-trunc-Set y  mere-eq x y
    apply-effectiveness-unit-trunc-Set {A = A} {x} {y} =
      map-equiv (is-effective-unit-trunc-Set A x y)

  abstract
    apply-effectiveness-unit-trunc-Set' :
      {A : UU l} {x y : A}  mere-eq x y  unit-trunc-Set x  unit-trunc-Set y
    apply-effectiveness-unit-trunc-Set' {A = A} {x} {y} =
      map-inv-equiv (is-effective-unit-trunc-Set A x y)

  emb-trunc-Set : (A : UU l)  type-trunc-Set A  (A  Prop l)
  emb-trunc-Set A =
    emb-is-surjective-and-effective
      ( mere-eq-equivalence-relation A)
      ( trunc-Set A)
      ( unit-trunc-Set)
      ( is-surjective-and-effective-unit-trunc-Set A)

  hom-slice-trunc-Set :
    (A : UU l)  hom-slice (mere-eq-Prop {A = A}) (map-emb (emb-trunc-Set A))
  pr1 (hom-slice-trunc-Set A) = unit-trunc-Set
  pr2 (hom-slice-trunc-Set A) =
    triangle-emb-is-surjective-and-effective
      ( mere-eq-equivalence-relation A)
      ( trunc-Set A)
      ( unit-trunc-Set)
      ( is-surjective-and-effective-unit-trunc-Set A)

  abstract
    is-image-trunc-Set :
      (A : UU l) 
      is-image
        ( mere-eq-Prop {A = A})
        ( emb-trunc-Set A)
        ( hom-slice-trunc-Set A)
    is-image-trunc-Set A =
      is-image-is-surjective-and-effective
        ( mere-eq-equivalence-relation A)
        ( trunc-Set A)
        ( unit-trunc-Set)
        ( is-surjective-and-effective-unit-trunc-Set A)
```

### Uniqueness of `trunc-Set`

```agda
module _
  {l1 l2 : Level} {A : UU l1} (B : Set l2) (f : A  type-Set B)
  {h : hom-Set B (trunc-Set A)} (H : h  f ~ unit-trunc-Set)
  where

  abstract
    is-equiv-is-set-truncation' : is-set-truncation B f  is-equiv h
    is-equiv-is-set-truncation' Sf =
      is-equiv-is-set-truncation-is-set-truncation
        ( B)
        ( f)
        ( trunc-Set A)
        ( unit-trunc-Set)
        ( H)
        ( Sf)
        ( λ {h}  is-set-truncation-trunc-Set A)

  abstract
    is-set-truncation-is-equiv' :
      is-equiv h  is-set-truncation B f
    is-set-truncation-is-equiv' Eh =
      is-set-truncation-is-equiv-is-set-truncation
        ( B)
        ( f)
        ( trunc-Set A)
        ( unit-trunc-Set)
        ( H)
        ( λ {l}  is-set-truncation-trunc-Set A)
        ( Eh)

module _
  {l1 l2 : Level} {A : UU l1} (B : Set l2) (f : A  type-Set B)
  {h : hom-Set (trunc-Set A) B} (H : h  unit-trunc-Set ~ f)
  where

  abstract
    is-equiv-is-set-truncation : is-set-truncation B f  is-equiv h
    is-equiv-is-set-truncation Sf =
      is-equiv-is-set-truncation-is-set-truncation
        ( trunc-Set A)
        ( unit-trunc-Set)
        ( B)
        ( f)
        ( H)
        ( λ {l}  is-set-truncation-trunc-Set A)
        ( Sf)

  abstract
    is-set-truncation-is-equiv :
      is-equiv h  is-set-truncation B f
    is-set-truncation-is-equiv Eh =
      is-set-truncation-is-set-truncation-is-equiv
        ( trunc-Set A)
        ( unit-trunc-Set)
        ( B)
        ( f)
        ( H)
        ( Eh)
        ( λ {l}  is-set-truncation-trunc-Set A)

is-equiv-unit-trunc-Set :
  {l : Level} (A : Set l)  is-equiv (unit-trunc-Set {A = type-Set A})
is-equiv-unit-trunc-Set = is-equiv-unit-trunc

equiv-unit-trunc-Set :
  {l : Level} (A : Set l)  type-Set A  type-trunc-Set (type-Set A)
equiv-unit-trunc-Set = equiv-unit-trunc

equiv-unit-trunc-empty-Set : empty  type-trunc-Set empty
equiv-unit-trunc-empty-Set = equiv-unit-trunc-Set empty-Set

abstract
  is-empty-trunc-Set :
    {l : Level} {A : UU l}  is-empty A  is-empty (type-trunc-Set A)
  is-empty-trunc-Set f x = apply-universal-property-trunc-Set' x empty-Set f

abstract
  is-empty-is-empty-trunc-Set :
    {l : Level} {A : UU l}  is-empty (type-trunc-Set A)  is-empty A
  is-empty-is-empty-trunc-Set f = f  unit-trunc-Set

equiv-unit-trunc-unit-Set : unit  type-trunc-Set unit
equiv-unit-trunc-unit-Set = equiv-unit-trunc-Set unit-Set

abstract
  is-contr-trunc-Set :
    {l : Level} {A : UU l}  is-contr A  is-contr (type-trunc-Set A)
  is-contr-trunc-Set {l} {A} H =
    is-contr-equiv'
      ( A)
      ( equiv-unit-trunc-Set (pair A (is-set-is-contr H)))
      ( H)

module _
  {l1 l2 : Level} {A : UU l1} (B : Set l2) (f : A  type-Set B)
  (Sf : is-set-truncation B f)
  where

  abstract
    uniqueness-trunc-Set :
      is-contr
        ( Σ (type-trunc-Set A  type-Set B)
        ( λ e  map-equiv e  unit-trunc-Set ~ f))
    uniqueness-trunc-Set =
      uniqueness-set-truncation (trunc-Set A) unit-trunc-Set B f
        ( λ {l}  is-set-truncation-trunc-Set A)
        ( Sf)

  equiv-uniqueness-trunc-Set : type-trunc-Set A  type-Set B
  equiv-uniqueness-trunc-Set = pr1 (center uniqueness-trunc-Set)

  map-equiv-uniqueness-trunc-Set : type-trunc-Set A  type-Set B
  map-equiv-uniqueness-trunc-Set = map-equiv equiv-uniqueness-trunc-Set

  triangle-uniqueness-trunc-Set :
    map-equiv-uniqueness-trunc-Set  unit-trunc-Set ~ f
  triangle-uniqueness-trunc-Set = pr2 (center uniqueness-trunc-Set)

module _
  {l1 l2 : Level} {A : UU l1} (B : Set l2) (f : A  type-Set B)
  (Sf : is-set-truncation B f)
  where

  abstract
    uniqueness-trunc-Set' :
      is-contr
        ( Σ ( type-Set B  type-trunc-Set A)
            ( λ e  map-equiv e  f ~ unit-trunc-Set))
    uniqueness-trunc-Set' =
      uniqueness-set-truncation B f (trunc-Set A) unit-trunc-Set Sf
        ( λ {l}  is-set-truncation-trunc-Set A)

  equiv-uniqueness-trunc-Set' : type-Set B  type-trunc-Set A
  equiv-uniqueness-trunc-Set' = pr1 (center uniqueness-trunc-Set')

  map-equiv-uniqueness-trunc-Set' : type-Set B  type-trunc-Set A
  map-equiv-uniqueness-trunc-Set' =
    map-equiv equiv-uniqueness-trunc-Set'

  triangle-uniqueness-trunc-Set' :
    map-equiv-uniqueness-trunc-Set'  f ~ unit-trunc-Set
  triangle-uniqueness-trunc-Set' = pr2 (center uniqueness-trunc-Set')
```

### The set truncation of a set is equivalent to the set

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

  equiv-unit-trunc-set : type-Set A  type-trunc-Set (type-Set A)
  equiv-unit-trunc-set = equiv-unit-trunc A
```

### Distributive of set truncation over coproduct

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

  abstract
    distributive-trunc-coprod-Set :
      is-contr
        ( Σ ( type-equiv-Set
              ( trunc-Set (A + B))
              ( coprod-Set (trunc-Set A) (trunc-Set B)))
            ( λ e 
              ( map-equiv e  unit-trunc-Set) ~
              ( map-coprod unit-trunc-Set unit-trunc-Set)))
    distributive-trunc-coprod-Set =
      uniqueness-trunc-Set
        ( coprod-Set (trunc-Set A) (trunc-Set B))
        ( map-coprod unit-trunc-Set unit-trunc-Set)
        ( λ {l} C 
          is-equiv-right-factor
            ( ev-inl-inr  x  type-Set C))
            ( precomp-Set (map-coprod unit-trunc-Set unit-trunc-Set) C)
            ( universal-property-coprod (type-Set C))
            ( is-equiv-comp
              ( map-prod
                ( precomp-Set unit-trunc-Set C)
                ( precomp-Set unit-trunc-Set C))
              ( ev-inl-inr  x  type-Set C))
              ( universal-property-coprod (type-Set C))
              ( is-equiv-map-prod
                ( precomp-Set unit-trunc-Set C)
                ( precomp-Set unit-trunc-Set C)
                ( is-set-truncation-trunc-Set A C)
                ( is-set-truncation-trunc-Set B C))))

  equiv-distributive-trunc-coprod-Set :
    type-equiv-Set (trunc-Set (A + B)) (coprod-Set (trunc-Set A) (trunc-Set B))
  equiv-distributive-trunc-coprod-Set =
    pr1 (center distributive-trunc-coprod-Set)

  map-equiv-distributive-trunc-coprod-Set :
    hom-Set (trunc-Set (A + B)) (coprod-Set (trunc-Set A) (trunc-Set B))
  map-equiv-distributive-trunc-coprod-Set =
    map-equiv equiv-distributive-trunc-coprod-Set

  triangle-distributive-trunc-coprod-Set :
    ( map-equiv-distributive-trunc-coprod-Set  unit-trunc-Set) ~
    ( map-coprod unit-trunc-Set unit-trunc-Set)
  triangle-distributive-trunc-coprod-Set =
    pr2 (center distributive-trunc-coprod-Set)
```

### Set truncations of Σ-types

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

  abstract
    trunc-Σ-Set :
      is-contr
        ( Σ ( type-trunc-Set (Σ A B) 
              type-trunc-Set (Σ A  x  type-trunc-Set (B x))))
            ( λ e 
              ( map-equiv e  unit-trunc-Set) ~
              ( unit-trunc-Set  tot  x  unit-trunc-Set))))
    trunc-Σ-Set =
      uniqueness-trunc-Set
        ( trunc-Set (Σ A  x  type-trunc-Set (B x))))
        ( unit-trunc-Set  tot  x  unit-trunc-Set))
        ( λ {l} C 
          is-equiv-right-factor
            ( ev-pair)
            ( precomp-Set (unit-trunc-Set  tot  x  unit-trunc-Set)) C)
            ( is-equiv-ev-pair)
            ( is-equiv-htpy-equiv
              ( ( equiv-Π-equiv-family
                  ( λ x  equiv-universal-property-trunc-Set C)) ∘e
                ( equiv-ev-pair) ∘e
                ( equiv-universal-property-trunc-Set C))
              ( refl-htpy)))

  equiv-trunc-Σ-Set :
    type-trunc-Set (Σ A B)  type-trunc-Set (Σ A  x  type-trunc-Set (B x)))
  equiv-trunc-Σ-Set = pr1 (center trunc-Σ-Set)

  map-equiv-trunc-Σ-Set :
    type-trunc-Set (Σ A B)  type-trunc-Set (Σ A  x  type-trunc-Set (B x)))
  map-equiv-trunc-Σ-Set = map-equiv equiv-trunc-Σ-Set
```

### `trunc-Set` distributes over products

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

  abstract
    distributive-trunc-prod-Set :
      is-contr
        ( Σ ( type-trunc-Set (A × B)  (type-trunc-Set A × type-trunc-Set B))
            ( λ e 
              ( map-equiv e  unit-trunc-Set) ~
              ( map-prod unit-trunc-Set unit-trunc-Set)))
    distributive-trunc-prod-Set =
      uniqueness-trunc-Set
        ( prod-Set (trunc-Set A) (trunc-Set B))
        ( map-prod unit-trunc-Set unit-trunc-Set)
        ( λ {l} C 
          is-equiv-right-factor
            ( ev-pair)
            ( precomp-Set (map-prod unit-trunc-Set unit-trunc-Set) C)
            ( is-equiv-ev-pair)
            ( is-equiv-htpy-equiv
              ( ( equiv-universal-property-trunc-Set (Π-Set' B  y  C))) ∘e
                ( equiv-postcomp
                  ( type-trunc-Set A)
                  ( equiv-universal-property-trunc-Set C)) ∘e
                ( equiv-ev-pair))
              ( refl-htpy)))

  equiv-distributive-trunc-prod-Set :
    type-trunc-Set (A × B)  (type-trunc-Set A × type-trunc-Set B)
  equiv-distributive-trunc-prod-Set =
    pr1 (center distributive-trunc-prod-Set)

  map-equiv-distributive-trunc-prod-Set :
    type-trunc-Set (A × B)  type-trunc-Set A × type-trunc-Set B
  map-equiv-distributive-trunc-prod-Set =
    map-equiv equiv-distributive-trunc-prod-Set

  map-inv-equiv-distributive-trunc-prod-Set :
    type-trunc-Set A × type-trunc-Set B  type-trunc-Set (A × B)
  map-inv-equiv-distributive-trunc-prod-Set =
    map-inv-equiv equiv-distributive-trunc-prod-Set

  triangle-distributive-trunc-prod-Set :
    ( map-equiv-distributive-trunc-prod-Set  unit-trunc-Set) ~
    ( map-prod unit-trunc-Set unit-trunc-Set)
  triangle-distributive-trunc-prod-Set =
    pr2 (center distributive-trunc-prod-Set)
```