\begin{code}
{-# OPTIONS --safe #-}
module Examples.Quotients where
open import Prelude hiding (_/_; [_]; eq/; squash/; rec/; isSet; isProp; elim/; ∥_∥)
\end{code}
\begin{code}
isProp : Type → Type
\end{code}
%<*is-prop>
\begin{code}
isProp P = (x y : P) → x ≡ y
\end{code}
%</is-prop>
\begin{code}
isSet : Type → Type
\end{code}
%<*is-set>
\begin{code}[number=eq:isSet]
isSet B = (x y : B) → (p q : x ≡ y) → p ≡ q
\end{code}
%</is-set>
%<*quot-def>
\begin{code}[number=quot-def]
data _/_ (A : Type) (_~_ : A → A → Type) : Type where
[_] : A → A / _~_
eq/ : (x y : A) → x ~ y → [ x ] ≡ [ y ]
squash/ : isSet (A / _~_)
\end{code}
%</quot-def>
\begin{code}
module _ {A : Type} {_~_ : A → A → Type} {B : Type} where
\end{code}
%<*rec-head>
\begin{code}
rec/ : isSet B
→ (f : A → B)
→ (∀ x y → x ~ y → f x ≡ f y)
→ A / _~_ → B
rec/ set f resp = ϕ where
\end{code}
%</rec-head>
%<*rec-body>
\begin{code}[number=rec-impl]
ϕ : A / _~_ → B
ϕ [ x ] = f x
ϕ (eq/ x y x~y i) = resp x y x~y i
ϕ (squash/ x y p q i j) =
set (ϕ x) (ϕ y) (cong ϕ p) (cong ϕ q) i j
\end{code}
%</rec-body>
%<*prop-trunc>
\begin{code}
∥_∥ : Type → Type
∥ A ∥ = A / λ _ _ → ⊤
\end{code}
%</prop-trunc>