-- Martin Escardo, 3rd August 2015, originally using type-in-type.
-- 9 May 2016, now using rewriting rather than type-in-type.
{-
Users of this module need to use the option "rewriting" like this:
{-# OPTIONS --rewriting #-}
We use Abel and Cockx's rewriting feature for Agda to get
impredicativity à la Voevodsky (propositional resizing) in Agda.
See the module resize.agda.
-}
{-# OPTIONS --without-K #-}
{-# OPTIONS --rewriting #-} -- Needed for the import resize.agda to work.
module prop where
open import preliminaries
open import isprop public
open import resize -- Don't make public, as it is inconsistent in general.
-- The type of small propositions is large:
PropLarge : U₁
PropLarge = Σ \(P : U₀) → isProp P
-- We make it small:
Prop : U₀
Prop = resize PropLarge
-- The above corresponds to Voevodsky's resizing rule RR2.
-- Notational convention:
--
-- Upper case P, Q, R : U₀, when we have isProp P, isProp Q, isProp R.
-- Lower case p, q, r : Prop.
-- Constructor:
₍_,_₎ : (P : U₀) → isProp P → Prop
₍ P , isp ₎ = resize-in(P , isp)
-- Destructors:
_holds : Prop → U₀
p holds = pr₁(resize-out p)
holdsIsProp : (p : Prop) → isProp(p holds)
holdsIsProp p = pr₂(resize-out p)
-- The idea of the terminology is that we cannot assert a point of the
-- type Prop, as it is a pair, but we can assert that it holds, meaning
-- that we assert that its first component has an inhabitant, as it is
-- a truth-value (a type P with the asserted side-condition isProp P).
-- We have the following judgemental equalities:
--
-- (β₁) ₍ P , isp ₎ holds = P,
-- (β₂) holdsIsProp ₍ P , isp ₎ = isp,
-- (η) p = ₍ p holds , holdsIsProp p ₎.
-- NB. holdsIsProp shows that _holds is an embedding in the sense of
-- the HoTT book https://homotopytypetheory.org/book/.
-- The following corresponds the Voevodky's resizing rule RR1:
resize₁ : {i : Level} (P : U i) → isProp {i} P → U₀
resize₁ P isp = resize P
-- We also need the following to make the above work:
resize₁-in : {i : Level} {P : U i} (isp : isProp {i} P) → P → resize₁ P isp
resize₁-in isp = resize-in
resize₁-out : {i : Level} {P : U i} (isp : isProp {i} P) → resize₁ P isp → P
resize₁-out isp = resize-out
-- The functions (resize₁-in isp) and (resize₁-out isp) form a judgemental
-- isomorphism. Here is a typical example where the above two
-- functions are needed:
resize₁-isProp : {i : Level} {P : U i} → (isp : isProp {i} P) → isProp (resize₁ {i} P isp)
resize₁-isProp {i} {P} isp p q = ap (resize₁-in isp) (isp (resize₁-out isp p) (resize₁-out isp q))
-- We also need the following judgemental isomorphism:
Prop-out : Prop → PropLarge
Prop-out = resize-out
Prop-in : PropLarge → Prop
Prop-in = resize-in
-- Here is a typical example where these functions are needed (because
-- the equality in the premise, being of two types in U₀, is in U₁,
-- whereas that of the conclusion, being of the type Prop, is in U₀) :
Prop-≡ : {p q : Prop} → p holds ≡ q holds → p ≡ q
Prop-≡ {p} {q} e = ap Prop-in e'
where
e' : Prop-out p ≡ Prop-out q
e' = Σ-≡ e (isProp-isProp (transport isProp e (holdsIsProp p)) (holdsIsProp q))
-- Propositional univalence says that any two (logically) equivalent
-- propositions are equal:
postulate propua : {i : Level} {P Q : U i} → isProp P → isProp Q → (P → Q) → (Q → P) → P ≡ Q
-- It can be formulated as follows:
propext : {p q : Prop} → (p holds → q holds) → (q holds → p holds) → p ≡ q
propext {p} {q} f g = Prop-≡ (propua (holdsIsProp p) (holdsIsProp q) f g)