{-# OPTIONS --prop --rewriting #-}

module lib where

open import Agda.Primitive public

-- We work in observational type theory (OTT)
-- OTT is not natively supported by Agda, so we postulate function extensionality, the coe operator,
-- and its computation rules according to "Observational equality meets CIC" by Leray, Tabareau and
-- Pujet.

infixl 2 _◼_
infix 5 _⁻¹
infix 4 _≡_
infix 4 _~_
infixl 5 _,Σ_

data _≡_ {i} {A : Set i} (a : A) : A  Prop i where
  ≡refl : a  a

data _~_ {i} {A : Set i} (a : A) : {B : Set i}  B  Prop i where
  ~refl : a ~ a

~to≡ :  {i} {A : Set i} {a b : A}  a ~ b  a  b
~to≡ ~refl = ≡refl

~to≡ty :  {i} {A B : Set i} {a : A} {b : B}  a ~ b  A  B
~to≡ty ~refl = ≡refl

≡to~ :  {i} {A : Set i} {a b : A}  a  b  a ~ b
≡to~ ≡refl = ~refl

_◼_ : ∀{i}{A B C : Set i}{a : A}{b : B}{c : C}  a ~ b  b ~ c  a ~ c
~refl  e = e

_⁻¹ : ∀{i}{A B : Set i}{a : A}{b : B}  a ~ b  b ~ a
~refl ⁻¹ = ~refl

record  : Set where
  constructor tt

record ⊤ₚ : Prop where
  constructor ttₚ

record Σ {i}(A : Set i){j}(B : A  Set j) : Set (i  j) where
  constructor _,Σ_
  field
    π₁ : A
    π₂ : B π₁
open Σ public

data Squash {} (A : Set ) : Prop  where
  squash : A  Squash A

postulate pi-inj₁ :  {i j} {A B : Set i} {P : A  Set j} {Q : B  Set j}
                       ((x : A)  P x) ~ ((x : B)  Q x)  A ~ B

postulate pi-inj₂ :  {i j} {A B : Set i} {P : A  Set j} {Q : B  Set j}
                       ((x : A)  P x) ~ ((x : B)  Q x)  P ~ Q

postulate funext :  {i j} {A B : Set i} {P : A  Set j} {Q : B  Set j} {f : (x : A)  P x} {g : (x : B)  Q x}
                       ({a : A}  {b : B}  (a ~ b)  f a ~ g b)  f ~ g
postulate funextᵢ :  {i j} {A B : Set i} {P : A  Set j} {Q : B  Set j} {f : {x : A}  P x} {g : {x : B}  Q x}
                       ({a : A}  {b : B}  (a ~ b)  f {a} ~ g {b})   {x}  f {x}) ~  {x}  g {x})

postulate coe≡     : ∀{}{A B : Set }  A  B  A  B
postulate coerefl : ∀{}{A : Set }{e : A  A}{a : A}  coe≡ e a  a
postulate coeₚ     : ∀{}{A B : Prop }  A ~ B  A  B

{-# BUILTIN REWRITE _≡_ #-}
{-# REWRITE coerefl   #-}

coe≡-eq :  {} {A B : Set } (e : A  B) (t : A)  t ~ coe≡ e t
coe≡-eq ≡refl t = ~refl

coe≡-eq₂ :  {} {A B C : Set } {e₁ : A  B} {e₂ : A  C} (t : A)  coe≡ e₁ t ~ coe≡ e₂ t
coe≡-eq₂ {e₁ = ≡refl} {e₂ = ≡refl} t = ~refl

coe : ∀{}{A B : Set }  A ~ B  A  B
coe e t = coe≡ (~to≡ e) t

coe-eq :  {} {A B : Set } (e : A ~ B) (t : A)  t ~ coe e t
coe-eq ~refl t = ~refl

cong :  {i j} {A : Set i} {P : A  Set j} (f : (x : A)  P x)
         {a : A}  {b : A}  a ~ b  f a ~ f b
cong f ~refl = ~refl

cong₂ :  {i j k} {A : Set i} {B : A  Set j} {C : (a : A)  B a  Set k} (f : (a : A) (b : B a)  C a b)
         {a₀ : A}  {a₁ : A}  a₀ ~ a₁  {b₀ : B a₀} {b₁ : B a₁}  b₀ ~ b₁  f a₀ b₀ ~ f a₁ b₁
cong₂ f ~refl ~refl = ~refl

cong₃ :  {i j k l} {A : Set i} {B : A  Set j} {C : (a : A)  B a  Set k} {D : (a : A)  (b : B a)  C a b  Set l}
         (f : (a : A) (b : B a) (c : C a b)  D a b c)
         {a₀ : A}  {a₁ : A}  a₀ ~ a₁  {b₀ : B a₀} {b₁ : B a₁}  b₀ ~ b₁
         {c₀ : C a₀ b₀}  {c₁ : C a₁ b₁}  c₀ ~ c₁  f a₀ b₀ c₀ ~ f a₁ b₁ c₁
cong₃ f ~refl ~refl ~refl = ~refl

cong₄ :  {i j k l m} {A : Set i} {B : A  Set j} {C : (a : A)  B a  Set k} {D : (a : A)  (b : B a)  C a b  Set l}
           {E : (a : A)  (b : B a)  (c : C a b)  (d : D a b c)  Set m}
         (f : (a : A) (b : B a) (c : C a b) (d : D a b c)  E a b c d)
         {a₀ : A}  {a₁ : A}  a₀ ~ a₁  {b₀ : B a₀} {b₁ : B a₁}  b₀ ~ b₁
         {c₀ : C a₀ b₀}  {c₁ : C a₁ b₁}  c₀ ~ c₁  {d₀ : D a₀ b₀ c₀}  {d₁ : D a₁ b₁ c₁}  d₀ ~ d₁
         f a₀ b₀ c₀ d₀ ~ f a₁ b₁ c₁ d₁
cong₄ f ~refl ~refl ~refl ~refl = ~refl

cong₅ :  {i j k l m n} {A : Set i} {B : A  Set j} {C : (a : A)  B a  Set k} {D : (a : A)  (b : B a)  C a b  Set l}
           {E : (a : A)  (b : B a)  (c : C a b)  (d : D a b c)  Set m}
           {F : (a : A)  (b : B a)  (c : C a b)  (d : D a b c)  (e : E a b c d)  Set n}
         (f : (a : A) (b : B a) (c : C a b) (d : D a b c) (e : E a b c d)  F a b c d e)
         {a₀ : A}  {a₁ : A}  a₀ ~ a₁  {b₀ : B a₀} {b₁ : B a₁}  b₀ ~ b₁
         {c₀ : C a₀ b₀}  {c₁ : C a₁ b₁}  c₀ ~ c₁  {d₀ : D a₀ b₀ c₀}  {d₁ : D a₁ b₁ c₁}  d₀ ~ d₁
         {e₀ : E a₀ b₀ c₀ d₀}  {e₁ : E a₁ b₁ c₁ d₁}  e₀ ~ e₁
         f a₀ b₀ c₀ d₀ e₀ ~ f a₁ b₁ c₁ d₁ e₁
cong₅ f ~refl ~refl ~refl ~refl ~refl = ~refl

congᵣᵣᵣᵢᵣ :  {i j k l m n} {A : Set i} {B : A  Set j} {C : (a : A)  B a  Set k} {D : (a : A)  (b : B a)  C a b  Prop l}
           {E : (a : A)  (b : B a)  (c : C a b)  (d : D a b c)  Set m}
           {F : (a : A)  (b : B a)  (c : C a b)  (d : D a b c)  E a b c d  Set n}
         (f : (a : A) (b : B a) (c : C a b) (d : D a b c) (e : E a b c d)  F a b c d e)
         {a₀ : A}  {a₁ : A}  a₀ ~ a₁  {b₀ : B a₀} {b₁ : B a₁}  b₀ ~ b₁
         {c₀ : C a₀ b₀}  {c₁ : C a₁ b₁}  c₀ ~ c₁  {d₀ : D a₀ b₀ c₀}  {d₁ : D a₁ b₁ c₁}
         {e₀ : E a₀ b₀ c₀ d₀}  {e₁ : E a₁ b₁ c₁ d₁}  e₀ ~ e₁
         f a₀ b₀ c₀ d₀ e₀ ~ f a₁ b₁ c₁ d₁ e₁
congᵣᵣᵣᵢᵣ f ~refl ~refl ~refl ~refl = ~refl

~cong :  {i j} {A B : Set i} {P : A  Set j} {Q : B  Set j}
         {f : (x : A)  P x} {g : (x : B)  Q x}  (f ~ g)
          {a : A}  {b : B}  a ~ b  f a ~ g b
~cong {f = f} {g = g} e₁ {a = a} e₂ with (pi-inj₂ (≡to~ (~to≡ty e₁)))
~cong {f = f} {g = g} ~refl {a = a} ~refl | ~refl = ~refl

postulate ~congᵢᵣ :  {i j k} {A B : Set i}
                    {P : A  Set j} {P' : {a : A}  P a  Set k}
                    {Q : B  Set j} {Q' : {b : B}  Q b  Set k}
                    {f : {a : A}  (x : P a)  P' x} {g : {b : B}  (x : Q b)  Q' x}
                     _~_ {A = {a : A}  (x : P a)  P' x} f {B = {b : B}  (x : Q b)  Q' x} g
                     {a : A}  {b : B}  a ~ b
                     {x : P a}  {y : Q b}  x ~ y  f {a} x ~ g {b} y

-- also provable from the injectivity of irrelevant pi's
postulate ~congₚₛ :  {i j} {A B : Prop i} {P : A  Set j} {Q : B  Set j}
                  {f : (x : A)  P x} {g : (x : B)  Q x}  (f ~ g)
                   {a : A}  {b : B}  f a ~ g b

funextH :  {i j} {A : Set i} {P : A  Set j} {f g : (x : A)  P x}  ((a : A)  f a ~ g a)  f ~ g
funextH {f = f} {g = g} e = funext λ {_} {b} e'  cong f e'  e b

funextHᵢ :  {i j} {A : Set i} {P : A  Set j} {f g : {x : A}  P x}  ({a : A}  f {a} ~ g {a})   {x}  f {x}) ~  {x}  g {x})
funextHᵢ {f = f} {g = g} e = funextᵢ λ {_} {b} e'  cong  x  f {x}) e'  e {b}

funexth :  {i j} {A : Set i} {P : A  Set j} {Q : A  Set j} {f : (x : A)  P x} {g : (x : A)  Q x}
          ((a : A)  f a ~ g a)  f ~ g
funexth {f = f} {g = g} e = funext λ {_} {b} e'  cong f e'  e b

funexthᵢ :  {i j} {A : Set i} {P : A  Set j} {Q : A  Set j} {f : {x : A}  P x} {g : {x : A}  Q x}
          ({a : A}  f {a} ~ g {a})   {x}  f {x}) ~  {x}  g {x})
funexthᵢ {f = f} {g = g} e = funextᵢ λ {_} {b} e'  cong  x  f {x}) e'  e {b}

funextHᵢᵣ :  {i j k} {A : Set i} {P : A  Set j} {Q : (a : A)  P a  Set k} {f g : {x : A}  (y : P x)  Q x y}
           ({a : A}  (p : P a)  f {a} p ~ g {a} p)   {x} y  f {x} y) ~  {x} y  g {x} y)
funextHᵢᵣ H = funextHᵢ λ {a}  funextH λ p  H p

funexthᵢᵣ :  {i j k} {A : Set i} {P : A  Set j} {Q : (a : A)  P a  Set k} {Q' : (a : A)  P a  Set k}
            {f : {x : A}  (y : P x)  Q x y} {g : {x : A}  (y : P x)  Q' x y}
           ({a : A}  (p : P a)  f {a} p ~ g {a} p)   {x} y  f {x} y) ~  {x} y  g {x} y)
funexthᵢᵣ H = funexthᵢ λ {a}  funexth λ p  H p

~Jᵢ :  {i j} {A : Set i} {a : A} (P : (b : A)  (a ~ b)  Prop j) (Prefl : P a ~refl) (b : A) (e : a ~ b)  P b e
~Jᵢ P Prefl b ~refl = Prefl

~Jeq :  {i j} {A : Set i} {a : A} (P : (b : A)  (a ~ b)  Set j) (b : A) (e : a ~ b)  P a ~refl ~ P b e
~Jeq P b ~refl = ~refl

~Jeq' :  {i j} {A : Set i} {a : A} (P : (b : A)  (b ~ a)  Set j) (b : A) (e : b ~ a)  P a ~refl ~ P b e
~Jeq' P b ~refl = ~refl

~Jeq₂' :  {i j k} {A : Set i} {B : A  Set j} {a : A} {b : B a} (P : (a' : A)  (a' ~ a)  (b' : B a')  (b' ~ b)  Set k)
           (a' : A) (e₁ : a' ~ a) (b' : B a') (e₂ : b' ~ b)  P a ~refl b ~refl ~ P a' e₁ b' e₂
~Jeq₂' P a' ~refl b' ~refl = ~refl

~J :  {i j} {A : Set i} {a : A} (P : (b : A)  (a ~ b)  Set j) (Prefl : P a ~refl) (b : A) (e : a ~ b)  P b e
~J {a = a} P Prefl b e = coe (~Jeq P b e) Prefl