{-

Uniqueness of identity proofs and axiom K

-}

{-# OPTIONS --safe #-}

module Cubical.Axiom.UniquenessOfIdentity where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Univalence
open import Cubical.Data.Bool
open import Cubical.Data.Empty
open import Cubical.Relation.Nullary

private
 variable
   : Level

-- Define uniqueness of identity proofs and Axiom K for an individual type

module _ (A : Type ) where

  UIP : Type 
  UIP = (x : A) (p : x  x)  refl  p

  AxiomK : (ℓ' : Level)  Type (ℓ-max  (ℓ-suc ℓ'))
  AxiomK ℓ' = (x : A) (P : x  x  Type ℓ')  P refl  (∀ p  P p)

-- UIP, K, and isSet are logically equivalent

module _ {A : Type } where

  UIP→AxiomK : UIP A   ℓ'  AxiomK A ℓ'
  UIP→AxiomK uip _ x P Prefl p = subst P (uip x p) Prefl

  AxiomK→UIP : AxiomK A   UIP A
  AxiomK→UIP K x p = K x (refl ≡_) refl p

  UIP→isSet : UIP A  isSet A
  UIP→isSet uip x = J> (uip x)

  isSet→UIP : isSet A  UIP A
  isSet→UIP setA x p = setA _ _ _ _

-- Univalence implies that universes fail UIP

¬UIPType :  {}  ¬ UIP (Type )
¬UIPType {} uip =
  false≢true (cong lower (transport-uip p (lift true)))
  where
  B = Lift {j = } Bool
  p = cong (Lift {j = }) (ua notEquiv)

  transport-uip : (p : B  B)   b  transport p b  b
  transport-uip = UIP→AxiomK uip _ B _ transportRefl