\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>