https://github.com/AndrasKovacs/universes
Raw File
Tip revision: dfb2127865dda7ab2db1a29ea1a2d5ac3d60f4b5 authored by AndrasKovacs on 29 October 2021, 18:43:22 UTC
fixes
Tip revision: dfb2127
IRUniverse.agda

module IRUniverse where

{-
Inductive-recursive universes over arbitrary level structures.

We give a full formalization of Section 4.1 of the paper.

Additionally, we give some examples for type codes using ω and ω*ω levels.

We also give a simple example for having _⊔_ operation on levels when levels
form a type theoretic ordinal.
-}

open import Lib

-- set with well-founded transitive relation
record LvlStruct : Set₁ where
  infix 4 _<_
  infixr 5 _∘_
  field
    Lvl         : Set
    _<_         : Lvl → Lvl → Set
    <-prop      : ∀ {i j}{p q : i < j} → p ≡ q
    _∘_         : ∀ {i j k} → j < k → i < j → i < k
    instance wf : ∀ {i} → Acc _<_ i

  acyclic : ∀ {i} → i < i → ⊥
  acyclic {i} p = go wf p where
    go : ∀ {i} → Acc _<_ i → i < i → ⊥
    go {i} (acc f) q = go (f i q) q

module IR-Universe (lvl : LvlStruct) where
  open LvlStruct lvl public
  open import Data.Nat hiding (_<_; _≤_)

  infix 4 _<'_
  infixr 1 _⊎'_

  data Uⁱʳ {i}(l : ∀ j → j < i → Set) : Set
  Elⁱʳ : ∀ {i l} → Uⁱʳ {i} l → Set

  data Uⁱʳ {i} l where
    U'       : ∀ {j} → j < i → Uⁱʳ l
    ℕ' ⊤' ⊥' : Uⁱʳ l
    _⊎'_     : Uⁱʳ l → Uⁱʳ l → Uⁱʳ l
    Π' Σ' W' : (a : Uⁱʳ l) → (Elⁱʳ a → Uⁱʳ l) → Uⁱʳ l

    -- codes for levels and morphisms, only used in level-polymorphic code examples
    Lvl'  : Uⁱʳ l
    _<'_  : Lvl → Lvl → Uⁱʳ l

  Elⁱʳ {_}{l}(U' p) = l _ p
  Elⁱʳ ℕ'           = ℕ
  Elⁱʳ ⊤'           = ⊤
  Elⁱʳ ⊥'           = ⊥
  Elⁱʳ Lvl'         = Lvl
  Elⁱʳ (i <' j)     = i < j
  Elⁱʳ (a ⊎' b)     = Elⁱʳ a ⊎ Elⁱʳ b
  Elⁱʳ (Π' a b)     = ∀ x → Elⁱʳ (b x)
  Elⁱʳ (Σ' a b)     = ∃ λ x → Elⁱʳ (b x)
  Elⁱʳ (W' a b)     = W (Elⁱʳ a) (λ x → Elⁱʳ (b x))

  -- Interpreting levels & lifts
  --------------------------------------------------------------------------------

  U< : ∀ {i} {{_ : Acc _<_ i}} j → j < i → Set
  U< {i} {{acc f}} j p = Uⁱʳ {j} (U< {j}{{f j p}})

  U : Lvl → Set
  U i = Uⁱʳ {i} (U< {i} {{wf}})

  El : ∀ {i} → U i → Set
  El {i} = Elⁱʳ {i}{U< {i}{{wf}}}

  U<-compute : ∀ {i a j p} → U< {i}{{a}} j p ≡ U j
  U<-compute {i} {acc f} {j} {p} = (λ a → Uⁱʳ (U< {{a}})) & Acc-prop (f j p) wf

  Lift   : ∀ {i j} → i < j → U i → U j
  ElLift : ∀ {i j} p a → El (Lift {i}{j} p a) ≡ El a
  Lift   p (U' q)      = U' (p ∘ q)
  Lift   p ℕ'          = ℕ'
  Lift   p ⊤'          = ⊤'
  Lift   p ⊥'          = ⊥'
  Lift   p Lvl'        = Lvl'
  Lift   p (i <' j)    = i <' j
  Lift   p (a ⊎' b)    = Lift p a ⊎' Lift p b
  Lift   p (Π' a b)    = Π' (Lift p a) λ x → Lift p (b (coe (ElLift p a) x))
  Lift   p (Σ' a b)    = Σ' (Lift p a) λ x → Lift p (b (coe (ElLift p a) x))
  Lift   p (W' a b)    = W' (Lift p a) λ x → Lift p (b (coe (ElLift p a) x))
  ElLift {i}{j} p (U' {k} q) = U<-compute {p = p ∘ q} ◾ U<-compute {p = q} ⁻¹
  ElLift p ℕ'       = refl
  ElLift p ⊤'       = refl
  ElLift p ⊥'       = refl
  ElLift p Lvl'     = refl
  ElLift p (i <' j) = refl
  ElLift p (a ⊎' b) = _⊎_ & ElLift p a ⊗ ElLift p b
  ElLift p (Π' a b) rewrite ElLift p a = (λ f → ∀ x → f x) & ext (ElLift p F.∘ b)
  ElLift p (Σ' a b) rewrite ElLift p a = Σ _ & ext (ElLift p F.∘ b)
  ElLift p (W' a b) rewrite ElLift p a = W _ & ext (ElLift p F.∘ b)

  -- congruence helper lemma
  congr2 : ∀ {i}{l : ∀ j → j < i → Set}
          (F' : (a : Uⁱʳ l) → (Elⁱʳ a → Uⁱʳ l) → Uⁱʳ l)
          {a₀ a₁ : Uⁱʳ l}(a₂ : a₀ ≡ a₁)
          {b₀ : Elⁱʳ a₀ → Uⁱʳ l}{b₁ : Elⁱʳ a₁ → Uⁱʳ l}
        → (∀ x → b₀ x ≡ b₁ (coe (Elⁱʳ & a₂) x))
        → F' a₀ b₀ ≡ F' a₁ b₁
  congr2 {i} {l} F' {a₀} refl {b₀} {b₁} b₂ = F' a₀ & ext b₂

  -- functorial lifting
  Lift∘ : ∀ {i j k}(p : i < j)(q : j < k) a → Lift q (Lift p a) ≡ Lift (q ∘ p) a
  Lift∘ p q (U' r)   = U' & <-prop
  Lift∘ p q ℕ'       = refl
  Lift∘ p q ⊤'       = refl
  Lift∘ p q ⊥'       = refl
  Lift∘ p q Lvl'     = refl
  Lift∘ p q (i <' j) = refl
  Lift∘ p q (a ⊎' b) = _⊎'_ & Lift∘ p q a ⊗ Lift∘ p q b
  Lift∘ p q (Π' a b) =
    congr2 Π' (Lift∘ p q a)
        (λ x → Lift∘ p q _
             ◾ (λ x → Lift (q ∘ p) (b x)) &
                  (coe∘ (ElLift p a) (ElLift q (Lift p a)) x
                ◾ (λ y → coe y x) & UIP
                ◾ coe∘ (ElLift (q ∘ p) a) (Elⁱʳ & Lift∘ p q a) x ⁻¹))
  Lift∘ p q (Σ' a b) =
    congr2 Σ' (Lift∘ p q a)
        (λ x → Lift∘ p q _
             ◾ (λ x → Lift (q ∘ p) (b x)) &
                  (coe∘ (ElLift p a) (ElLift q (Lift p a)) x
                ◾ (λ y → coe y x) & UIP
                ◾ coe∘ (ElLift (q ∘ p) a) (Elⁱʳ & Lift∘ p q a) x ⁻¹))
  Lift∘ p q (W' a b) =
    congr2 W' (Lift∘ p q a)
        (λ x → Lift∘ p q _
             ◾ (λ x → Lift (q ∘ p) (b x)) &
                  (coe∘ (ElLift p a) (ElLift q (Lift p a)) x
                ◾ (λ y → coe y x) & UIP
                ◾ coe∘ (ElLift (q ∘ p) a) (Elⁱʳ & Lift∘ p q a) x ⁻¹))

  -- conveniences
  --------------------------------------------------------------------------------

  _⇒'_ : ∀ {i l} → Uⁱʳ {i} l → Uⁱʳ l → Uⁱʳ l
  a ⇒' b = Π' a λ _ → b
  infixr 3 _⇒'_

  _×'_ : ∀ {i l} → Uⁱʳ {i} l → Uⁱʳ l → Uⁱʳ l
  a ×' b = Σ' a λ _ → b
  infixr 4 _×'_

  -- This is convenient in code examples, where we often want to lift values in Elⁱʳ U'
  LiftU : ∀ {i j}(p : i < j) → El (U' p) → U j
  LiftU p a = Lift p (coe U<-compute a)


-- Type-theoretic ordinals
--------------------------------------------------------------------------------

record Ordinal (lvl : LvlStruct) : Set where
  open LvlStruct lvl
  field
    cmp    : ∀ i j → i < j ⊎ j < i ⊎ i ≡ j
    <-ext  : ∀ {i j} → (∀ k → (k < i → k < j) × (k < j → k < i)) → i ≡ j

  private
    pattern inj₂₁ x = inj₂ (inj₁ x)
    pattern inj₂₂ x = inj₂ (inj₂ x)

  _≤_ : Lvl → Lvl → Set; infix 4 _≤_
  i ≤ j = i < j ⊎ i ≡ j

  _⊔_ : Lvl → Lvl → Lvl; infixr 5 _⊔_
  i ⊔ j with cmp i j
  ... | inj₁  _ = j
  ... | inj₂₁ _ = i
  ... | inj₂₂ _ = i

  ⊔₁ : ∀ i j → i ≤ i ⊔ j
  ⊔₁ i j with cmp i j
  ... | inj₁  p = inj₁ p
  ... | inj₂₁ p = inj₂ refl
  ... | inj₂₂ p = inj₂ refl

  ⊔₂ : ∀ i j → j ≤ i ⊔ j
  ⊔₂ i j with cmp i j
  ... | inj₁  p = inj₂ refl
  ... | inj₂₁ p = inj₁ p
  ... | inj₂₂ p = inj₂ (p ⁻¹)

  ⊔-least : ∀ {i j k} → i ≤ k → j ≤ k → i ⊔ j ≤ k
  ⊔-least {i}{j}{k} p q with cmp i j
  ... | inj₁  _ = q
  ... | inj₂₁ _ = p
  ... | inj₂₂ _ = p

  ≤-prop : ∀ {i j}{p q : i ≤ j} → p ≡ q
  ≤-prop {p = inj₁ p}    {inj₁ q}    = inj₁ & <-prop
  ≤-prop {p = inj₁ p}    {inj₂ refl} = ⊥-elim (acyclic p)
  ≤-prop {p = inj₂ refl} {inj₁ q}    = ⊥-elim (acyclic q)
  ≤-prop {p = inj₂ p}    {inj₂ q}    = inj₂ & UIP

module IR-Univ-Ordinal {lvl} (ord : Ordinal lvl) where
  open Ordinal ord public
  open IR-Universe lvl public

  -- non-strict lifts
  Lift≤ : ∀ {i j} → i ≤ j → U i → U j
  Lift≤ (inj₁ p)    a = Lift p a
  Lift≤ (inj₂ refl) a = a

  ElLift≤ : ∀ {i j} p a → El (Lift≤ {i}{j} p a) ≡ El a
  ElLift≤ (inj₁ p)    a = ElLift p a
  ElLift≤ (inj₂ refl) a = refl

  -- alternative Π type formation with _⊔_ and Lift.
  Π'' : ∀ {i j}(a : U i) → (El a → U j) → U (i ⊔ j)
  Π'' {i}{j} a b = Π' (Lift≤ (⊔₁ i j) a) λ x → Lift≤ (⊔₂ i j) (b (coe (ElLift≤ (⊔₁ i j) a) x))


-- Examples. Here we instantiate level structures, and give examples for some
-- type codes and their El interpretations.
--------------------------------------------------------------------------------

-- finite levels
module ℕ-example where
  open import Data.Nat
  open import Data.Nat.Properties
  open import Data.Nat.Induction

  lvl : LvlStruct
  lvl = record {
      Lvl = ℕ
    ; _<_ = _<_
    ; <-prop = <-irrelevant _ _
    ; _∘_ = λ p q → <-trans q p
    ; wf  = <-wellFounded _
    }

  open IR-Universe lvl hiding (_<_)

  <suc : ∀ {i} → i < suc i
  <suc {i} = ≤-refl

  id' : ∀ {i} → El {suc i} (Π' (U' <suc) λ A → LiftU <suc A ⇒' LiftU <suc A)
  id' {i} A x = x

  const₀' : El {1} (Π' (U' <suc) λ A → Π' (U' <suc) λ B → LiftU <suc A ⇒' LiftU <suc B ⇒' LiftU <suc A)
  const₀' A B x y = x


-- ω*ω levels
module ℕ*ℕ-example where

  import Data.Nat as N
  open import Data.Nat.Properties
  open import Data.Nat.Induction
  open Lexicographic N._<_ (λ _ → N._<_)

  trs : ∀ {i j k} → j < k → i < j → i < k
  trs (left  p) (left  q) = left (<-trans q p)
  trs (left  p) (right q) = left p
  trs (right p) (left  q) = left q
  trs (right p) (right q) = right (<-trans q p)

  <-irr : ∀{x y}(a b : x < y) → a ≡ b
  <-irr (left  p) (left  q) = left & <-irrelevant _ _
  <-irr (left  p) (right q) = ⊥-elim (<-irrefl refl p)
  <-irr (right p) (left  q) = ⊥-elim (<-irrefl refl q)
  <-irr (right p) (right q) = right & <-irrelevant _ _

  --  representation: (i, j) ~ (ω*i + j)
  lvl : LvlStruct
  lvl = record {
      Lvl = N.ℕ × N.ℕ
    ; _<_ = _<_
    ; <-prop = <-irr _ _
    ; _∘_ = trs
    ; wf  = wellFounded <-wellFounded <-wellFounded _
    }

  open IR-Universe lvl hiding (_<_)

  -- raise by 1
  <suc : ∀ {i j} → (i , j) < (i , N.suc j)
  <suc {i} = right ≤-refl

  -- raise to closest limit level
  <Suc : ∀ {i} j → (i , j) < (N.suc i , 0)
  <Suc {i} j = left ≤-refl

  ω : Lvl
  ω = 1 , 0

  #_ : N.ℕ → Lvl; infix 10 #_
  # n = 0 , n

  _+_ : Lvl → Lvl → Lvl; infix 6 _+_
  (i , j) + (i' , j') = i N.+ i' , j N.+ j'

  idω : El {ω} (Π' ℕ' λ i → Π' (U' (<Suc i)) λ A → LiftU (<Suc i) A ⇒' LiftU (<Suc i) A)
  idω i A x = x

  idω' : El {ω} (Π' Lvl' λ i → Π' (i <' ω) λ p → Π' (U' p) λ A → LiftU p A ⇒' LiftU p A)
  idω' i p A x = x

  fω+2 : El {ω + # 2} (U' (trs <suc <suc) ⇒' U' <suc)
  fω+2 = LiftU <suc
back to top