-- Martin Escardo, 3rd August 2015

{-

 We use type-in-type to get impredicativity à la Voevodsky
 (propositional resizing) in Agda.

 No other module in this development uses type-in-type.

 Because of limitations of Agda, or perhaps of our ability to exploit
 Agda, we can only resize from the second universe to the first.

 Curiously, if we write "U" rather than "Set" below, then other
 modules don't type check, even though U=Set by definition. I am not
 sure why this is the case. But it is possible to still use U in other
 modules, and we do.

-}

{-# OPTIONS --type-in-type #-}
{-# OPTIONS --without-K #-}

module prop where

open import preliminaries

-- A proposition is a type with at most one element:

open import isprop public

-- A truth value is a type together with a witness that it is a
-- proposition. "Prop" is an Agda reserved, but unused,
-- keyword, and Agda won't let us use it as an identifier:

Prp : Set
Prp = Σ \(P : Set)  isProp P

-- We could use the pair constructor _,_ from Σ, but this doesn't type
-- check when used in a module without the option type-in-type. The
-- reason is that the types of Σ and _,_ are different with(out)
-- type-in-type. To circumvent this, we define another another binary
-- operator ₍_,_₎, which does type check when used without
-- type-in-type. The reason this works is that the type of this new
-- operator is the same with or without type-in-type:

₍_,_₎ : (P : Set)  isProp P  Prp
₍_,_₎ = _,_

-- It is also necessary, for the same reason, to specialize the
-- types of the projections:

_holds : Prp  Set
_holds = pr₁

holdsIsProp : (p : Prp)  isProp(p holds)
holdsIsProp = pr₂ 

-- NB. holdsIsProp shows that _holds is an embedding in the sense of
-- the HoTT book.

Prp-≡ : {p q : Prp}  p holds  q holds  p  q
Prp-≡ {p} {q} e = Σ-≡ e (isProp-isProp (transport isProp e (holdsIsProp p)) (holdsIsProp q))

-- open import propua -- <-- Doesn't work. We have to repeat the postulate literally:

postulate prop-ua' : {P Q : Set}  isProp P  isProp Q  (P  Q)  (Q  P)  P  Q

-- (Why? Moreover, there is an example in which we need to use both
-- prop-ua and prop-ua'.)

propext : {p q : Prp}  (p holds  q holds)  (q holds  p holds)  p  q
propext {p} {q} f g = Prp-≡ e 
 where
  e : p holds  q holds
  e = prop-ua' (holdsIsProp p) (holdsIsProp q) f g