module Proposition where

open import Empty
open import Equality
open import Function
open import Level
open import Product
open import Quotient
open import Sum
open import UIP

----------------------------------------------------------------------
-- Negation
----------------------------------------------------------------------
¬ : { : Level}  Set   Set 
¬ {} A = A  Ø {}

----------------------------------------------------------------------
-- Indiscrete relation
----------------------------------------------------------------------
data  { : Level}{A : Set } : A  A  Set  where
  ∇rel : {x y : A}    x y

----------------------------------------------------------------------
-- Propositional truncation via quotients
----------------------------------------------------------------------
infix  5 ∥_∥
∥_∥ : { : Level}  Set   Set 
 A  = A /  

infix  5 _mod∇
_mod∇ :{ : Level}{A : Set }  A   A 
x mod∇ = [ x ]/ 

∥∥elim :
  { ℓ' : Level}
  {A : Set }
  (B :  A   Set ℓ')
  (f : (x : A)   B (x mod∇))
  (_ : (x x' : A)  subst B (by ∇rel) (f x)  f x')
   -----------------------------------------------
  (y :  A )  B y
∥∥elim B f e = qelim  B f  x x' _  e x x')

∥∥comp :
  { ℓ' : Level}
  {A : Set }
  (B :  A   Set ℓ')
  (f : (x : A)   B (x mod∇))
  (e : (x x' : A)  subst B (by ∇rel) (f x)  f x')
  (x : A)
   -----------------------------------------------
  ∥∥elim B f e (x mod∇)  f x
∥∥comp B f e x  = qcomp  B f  x x' _  e x x') x

∥∥rec :
  { ℓ' : Level}
  {A : Set }
  {B : Set ℓ'}
  (f : A  B)
  (_ : (x x' : A)  f x  f x')
   ---------------------------
   A   B
∥∥rec f e = qrec  _ f  x x' _  e x x')

∥∥rec-comp :
  { ℓ' : Level}
  {A : Set }
  {B : Set ℓ'}
  (f : A  B)
  (e : (x x' : A)  f x  f x')
  (x : A)
   ---------------------------
  ∥∥rec f e (x mod∇)  f x
∥∥rec-comp f e x = qrec-comp  _ f  x x' _  e x x') x

----------------------------------------------------------------------
-- Mere propositions
----------------------------------------------------------------------
isProp :
  { : Level}
  (A : Set )
   ---------
  Set 
isProp A = {x y : A}  x  y

∥∥isProp :
  { : Level}
  {A : Set }
   ------------
  isProp ( A )
∥∥isProp {y = q} =
  qelim   p'  p'  q) (f q)  _ _ _  uip) _
  where
  f : (q' :  _ )(x : _)  (x mod∇)  q'
  f q' x =
    qelim   q'  (x mod∇)  q')  y  by ∇rel)  _ _ _  uip) q'
    
----------------------------------------------------------------------
-- Mere disjunction
----------------------------------------------------------------------
infixr 3 _or_
_or_ : { : Level}  Set   Set   Set 
A or B =  A  B 

orcompat :
  { ℓ' : Level}
  {A B : Set }
  {C : Set ℓ'}
  {f : A  C}
  {g : B  C}
  (u : (x x' : A)  f x  f x')
  (v : (y y' : B)  g y  g y')
  (w : (x : A)(y : B)  f x  g y)
  (z z' : A  B)
   ------------------------------
  [ f  g ] z  [ f  g ] z'
orcompat u _ _ (inl x) (inl x') = u x x'
orcompat _ _ w (inl x) (inr y)  = w x y
orcompat _ _ w (inr y) (inl x)  = symm (w x y)
orcompat _ v _ (inr y) (inr y') = v y y'

orrec :
  { ℓ' : Level}
  {A B : Set }
  {C : Set ℓ'}
  (f : A  C)
  (g : B  C)
  (u : (x x' : A)  f x  f x')
  (v : (y y' : B)  g y  g y')
  (w : (x : A)(y : B)  f x  g y)
   ------------------------------
  A or B  C
orrec f g u v w = ∥∥rec [ f  g ] (orcompat u v w)

orcompl :
  { ℓ' : Level}
  {A B : Set }
  {C : Set ℓ'}
  (f : A  C)
  (g : B  C)
  (u : (x x' : A)  f x  f x')
  (v : (y y' : B)  g y  g y')
  (w : (x : A)(y : B)  f x  g y)
  (x : A)
   ---------------------------------
  orrec f g u v w (inl x mod∇)  f x
orcompl f g u v w  = (∥∥rec-comp [ f  g ] (orcompat u v w))  inl

orcompr :
  { ℓ' : Level}
  {A B : Set }
  {C : Set ℓ'}
  (f : A  C)
  (g : B  C)
  (u : (x x' : A)  f x  f x')
  (v : (y y' : B)  g y  g y')
  (w : (x : A)(y : B)  f x  g y)
  (y : B)
   --------------------------------
  orrec f g u v w (inr y mod∇)  g y
orcompr f g u v w  = (∥∥rec-comp [ f  g ] (orcompat u v w))  inr
 
----------------------------------------------------------------------
-- Mere existence
----------------------------------------------------------------------
infix  1 
 :
  { ℓ' : Level}
  (A : Set )
  (B : A  Set ℓ')
   --------------
  Set(  ℓ')
 A B =  Σ A B 

syntax  A  x  B) = ∃ x ∈ A , B

----------------------------------------------------------------------
-- Comprehension
----------------------------------------------------------------------
infix 3 _by_
record subset
  { ℓ' : Level}
  (A : Set )
  (P : A  Set ℓ') : Set (  ℓ') where
  constructor _by_
  field
    inc     : A
    prfinc  :  P inc 

open subset public

syntax subset A  x  P) = ⟦ x ∈ A ∣ P ⟧

incInj :
  { ℓ' : Level}
  {A : Set }
  {P : A  Set ℓ'}
  {a b : subset A P}
   -------------------
  inc a  inc b  a  b
incInj {a = x by _} refl = cong (x by_) (∥∥isProp)