open import 1Lab.Function.Surjection
open import 1Lab.Path.IdentitySystem
open import 1Lab.Reflection.HLevel
open import 1Lab.HLevel.Universe
open import 1Lab.HIT.Truncation
open import 1Lab.HLevel.Closure
open import 1Lab.Reflection using (arg ; typeError)
open import 1Lab.Univalence
open import 1Lab.Inductive
open import 1Lab.HLevel
open import 1Lab.Equiv
open import 1Lab.Path
open import 1Lab.Type

open import Data.List.Base
open import Data.Sum.Base

open import Meta.Idiom
open import Meta.Bind

module 1Lab.Resizing where


# Propositional resizingπ

Ordinarily, the collection of all predicates on types lives in the next universe up, This is because predicates are not special in type theory: they are ordinary type families, that just so happen to be valued in propositions. For most purposes we can work with this limitation: this is called predicative mathematics. But, for a few classes of theorems, predicativity is too restrictive: Even if we donβt have a single universe of propositions that can accommodate all predicates, we would still like for universes to be closed under power-sets.

Using some of Agdaβs more suspicious features, we can achieve this in a way which does not break computation too much. Specifically, weβll use a combination of NO_UNIVERSE_CHECK, postulates, and rewrite rules.

We start with the NO_UNIVERSE_CHECK part: We define the small type of propositions, Ξ©, to be a record containing a Type (together with an irrelevant proof that this type is a proposition), but contrary to the universe checker, which would like us to put Ξ© : Typeβ, we instead force Ξ© : Type.

{-# NO_UNIVERSE_CHECK #-}
constructor el
field
β£_β£   : Type
is-tr : is-prop β£_β£


This type, a priori, only contains the propositions whose underlying type lives in the first universe. However, we can populate it using a NO_UNIVERSE_CHECK-powered higher inductive type, the βsmall propositional truncationβ:

{-# NO_UNIVERSE_CHECK #-}
data β‘ {β} (A : Type β) : Type where
inc    : A β β‘ A
squash : (x y : β‘ A) β x β‘ y


Just like the ordinary propositional truncation, every type can be squashed, but unlike the ordinary propositional truncation, the β‘-squashing of a type always lives in the lowest universe. If is a proposition in any universe, is its name in the zeroth universe.

instance
H-Level-β‘ : β {β} {T : Type β} {n} β H-Level (β‘ T) (suc n)
H-Level-β‘ = prop-instance squash

open hlevel-projection
Ξ©-hlevel-proj .get-level x = pure (quoteTerm (suc zero))
Ξ©-hlevel-proj .get-argument (arg _ t β· _) = pure t
Ξ©-hlevel-proj .get-argument _ = typeError []


We can also prove a univalence principle for Ξ©:

Ξ©-ua : {A B : Ξ©} β (β£ A β£ β β£ B β£) β (β£ B β£ β β£ A β£) β A β‘ B
Ξ©-ua {A} {B} f g i .β£_β£ = ua (prop-ext! f g) i
Ξ©-ua {A} {B} f g i .is-tr =
is-propβpathp (Ξ» i β is-prop-is-prop {A = ua (prop-ext! f g) i})
(A .is-tr) (B .is-tr) i

instance abstract
H-Level-Ξ© = basic-instance 2 $retractβis-hlevel 2 (Ξ» r β el β£ r β£ (r .is-tr)) (Ξ» r β el β£ r β£ (r .is-tr)) (Ξ» x β Ξ©-ua (Ξ» x β x) Ξ» x β x) (n-Type-is-hlevel {lzero} 1)  The β‘ type former is a functor (in the handwavy sense that it supports a βmapβ operation), and can be projected from into propositions of any universe. These functions compute on incs, as usual. β‘-map : β {β β'} {A : Type β} {B : Type β'} β (A β B) β β‘ A β β‘ B β‘-map f (inc x) = inc (f x) β‘-map f (squash x y i) = squash (β‘-map f x) (β‘-map f y) i β‘-rec : β {β β'} {A : Type β} {B : Type β'} β is-prop B β (A β B) β β‘ A β B β‘-rec bp f (inc x) = f x β‘-rec bp f (squash x y i) = bp (β‘-rec bp f x) (β‘-rec bp f y) i elΞ© : β {β} (T : Type β) β Ξ© elΞ© T .β£_β£ = β‘ T elΞ© T .is-tr = squash  β‘-elim : β {β β'} {A : Type β} {P : β‘ A β Type β'} β (β x β is-prop (P x)) β (β x β P (inc x)) β β x β P x β‘-elim pprop go (inc x) = go x β‘-elim pprop go (squash x y i) = is-propβpathp (Ξ» i β pprop (squash x y i)) (β‘-elim pprop go x) (β‘-elim pprop go y) i instance Inductive-β‘ : β {β β' βm} {A : Type β} {P : β‘ A β Type β'} β¦ i : Inductive (β x β P (inc x)) βm β¦ β β¦ _ : β {x} β H-Level (P x) 1 β¦ β Inductive (β x β P x) βm Inductive-β‘ β¦ i β¦ = record { methods = i .Inductive.methods ; from = Ξ» f β β‘-elim (Ξ» x β hlevel 1) (i .Inductive.from f) } β‘-out : β {β} {A : Type β} β is-prop A β β‘ A β A β‘-out ap = β‘-rec ap (Ξ» x β x) β‘-out! : β {β} {A : Type β} β β¦ _ : H-Level A 1 β¦ β β‘ A β A β‘-out! = rec! Ξ» x β x β‘-rec-set : β {β β'} {A : Type β} {B : Type β'} β is-set B β (f : A β B) β (β x y β f x β‘ f y) β β‘ A β B β‘-rec-set B-set f f-const a = fst$ β‘-elim
(Ξ» _ β is-constantβimage-is-prop B-set f f-const)
(Ξ» a β f a , inc (a , refl))
a

β‘-idempotent : β {β} {A : Type β} β is-prop A β β‘ A β A
β‘-idempotent aprop = prop-ext squash aprop (β‘-out aprop) inc

β‘-ap
: β {β β'} {A : Type β} {B : Type β'}
β β‘ (A β B) β β‘ A β β‘ B
β‘-ap (inc f) (inc g) = inc (f g)
β‘-ap (inc f) (squash g g' i) = squash (β‘-ap (inc f) g) (β‘-ap (inc f) g') i
β‘-ap (squash f f' i) g = squash (β‘-ap f g) (β‘-ap f' g) i

β‘-bind
: β {β β'} {A : Type β} {B : Type β'}
β β‘ A β (A β β‘ B) β β‘ B
β‘-bind (inc x) f = f x
β‘-bind (squash x x' i) f = squash (β‘-bind x f) (β‘-bind x' f) i

instance
Map-β‘ : Map (eff β‘)
Map-β‘ .Map.map = β‘-map

Idiom-β‘ : Idiom (eff β‘)
Idiom-β‘ .Idiom.pure = inc
Idiom-β‘ .Idiom._<*>_ = β‘-ap

Bind-β‘ : Bind (eff β‘)
Bind-β‘ .Bind._>>=_ = β‘-bind

is-setβlocally-small
: β {β} {A : Type β}
β is-set A
β is-identity-system {A = A} (Ξ» x y β β‘ (x β‘ y)) (Ξ» x β inc refl)
is-setβlocally-small a-set .to-path = β‘-rec (a-set _ _) id
is-setβlocally-small a-set .to-path-over p = is-propβpathp (Ξ» _ β squash) _ _

to-is-true
: β {P Q : Ξ©} β¦ _ : H-Level β£ Q β£ 0 β¦
β β£ P β£
β P β‘ Q
to-is-true prf = Ξ©-ua (Ξ» _ β hlevel 0 .centre) (Ξ» _ β prf)

tr-β‘ : β {β} {A : Type β} β β₯ A β₯ β β‘ A
tr-β‘ (inc x) = inc x
tr-β‘ (squash x y i) = squash (tr-β‘ x) (tr-β‘ y) i

β‘-tr : β {β} {A : Type β} β β‘ A β β₯ A β₯
β‘-tr (inc x) = inc x
β‘-tr (squash x y i) = squash (β‘-tr x) (β‘-tr y) i


## Connectivesπ

The universe of small propositions contains true, false, conjunctions, disjunctions, and implications.

infixr 6 _β§Ξ©_

β€Ξ© : Ξ©

β£ P β§Ξ© Q β£ = β£ P β£ Γ β£ Q β£
(P β§Ξ© Q) .is-tr = hlevel 1

β£ P β¨Ξ© Q β£ = β₯ β£ P β£ β β£ Q β£ β₯
(P β¨Ξ© Q) .is-tr = hlevel 1

β£ P βΞ© Q β£ = β£ P β£ β β£ Q β£
(P βΞ© Q) .is-tr = hlevel 1



Furthermore, we can quantify over types of arbitrary size and still land in Ξ©.

βΞ© : β {β} (A : Type β) β (A β Ξ©) β Ξ©
β£ βΞ© A P β£ = β‘ (Ξ£[ x β A ] β£ P x β£)
βΞ© A P .is-tr = squash

β£ βΞ© A P β£ = β‘ (β (x : A) β β£ P x β£)
βΞ© A P .is-tr = squash

syntax βΞ© A (Ξ» x β B) = βΞ©[ x β A ] B
syntax βΞ© A (Ξ» x β B) = βΞ©[ x β A ] B


These connectives and quantifiers are only provided for completeness; if you find yourself building nested propositions, it is generally a good idea to construct the large proposition by hand, and then use truncation to turn it into a small proposition.

module _ {β β'} {A : Type β} {B : Type β'} (f : A β B) where