{-# OPTIONS --cubical --no-import-sorts --safe --guardedness #-} module Cubical.Codata.Conat.Bounded where open import Cubical.Foundations.Equiv open import Cubical.Foundations.Function open import Cubical.Foundations.HLevels open import Cubical.Foundations.Isomorphism open import Cubical.Foundations.Prelude open import Cubical.Foundations.Transport open import Cubical.Foundations.Univalence open import Cubical.Codata.Conat.Base renaming (zero to czero; suc to csuc) open import Cubical.Codata.Conat.Properties open import Cubical.Data.Empty as Empty open import Cubical.Data.Sigma open import Cubical.Data.Sum hiding (rec) open import Cubical.Data.Unit open import Cubical.Relation.Nullary open import Cubical.Data.Nat as Nat import Cubical.Data.Fin.Recursive as Fin private variable ℓ : Level _≺_ : ℕ → Conat → Type _ _≺′_ : ℕ → Conat′ → Type _ n ≺ c = n ≺′ force c _ ≺′ czero = ⊥ zero ≺′ csuc _ = Unit suc n ≺′ csuc c = n ≺ c isProp≺ : ∀ n c → isProp (n ≺ c) isProp≺′ : ∀ n c → isProp (n ≺′ c) isProp≺ n c = isProp≺′ n (force c) isProp≺′ n czero = isProp⊥ isProp≺′ zero (csuc _) = isPropUnit isProp≺′ (suc n) (csuc c') = isProp≺ n c' isPropDep≺ : ∀ c → isPropDep (_≺ c) isPropDep≺ c = isOfHLevel→isOfHLevelDep 1 (λ n → isProp≺ n c) {_} {_} isPropDep≺′ : ∀ c → isPropDep (_≺′ c) isPropDep≺′ c = isOfHLevel→isOfHLevelDep 1 (λ n → isProp≺′ n c) {_} {_} private apart : ℕ → ℕ → Type apart zero zero = ⊥ apart (suc m) (suc n) = apart m n apart _ _ = Unit ≢→apart : (i j : ℕ) → ¬ i ≡ j → apart i j ≢→apart zero zero ¬p = ¬p refl ≢→apart (suc i) (suc j) ¬p = ≢→apart i j (¬p ∘ cong suc) ≢→apart zero (suc j) _ = _ ≢→apart (suc i) zero _ = _ apart→≢ : (i j : ℕ) → apart i j → ¬ i ≡ j apart→≢ (suc i) zero _ = snotz apart→≢ zero (suc j) _ = znots apart→≢ (suc i) (suc j) i#j = apart→≢ i j i#j ∘ cong predℕ isPropApart : ∀ m n → isProp (apart m n) isPropApart 0 0 = isProp⊥ isPropApart (suc m) (suc n) = isPropApart m n isPropApart (suc _) 0 = isPropUnit isPropApart 0 (suc _) = isPropUnit _#_ : ∀{P : ℕ → Type ℓ} → (l r : Σ ℕ P) → Type (m , _) # (n , _) = apart m n #→≢ : ∀{P : ℕ → Type ℓ} → (l r : Σ ℕ P) → l # r → ¬ l ≡ r #→≢ (i , _) (j , _) d = apart→≢ i j d ∘ cong fst isProp# : ∀{P : ℕ → Type ℓ} (l r : Σ ℕ P) → isProp (l # r) isProp# (m , _) (n , _) = isPropApart m n isProp#Depᵣ : ∀{P : ℕ → Type ℓ} (r : Σ ℕ P) → isPropDep (_# r) isProp#Depᵣ r = isOfHLevel→isOfHLevelDep 1 (λ l → isProp# l r) {_} {_} Bounded : Conat → Type Bounded m = Σ[ n ∈ ℕ ] n ≺ m Bounded′ : Conat′ → Type Bounded′ m = Σ[ n ∈ ℕ ] n ≺′ m discreteB′ : ∀ m → (i j : Bounded′ m) → (i ≡ j) ⊎ (i # j) discreteB′ m (i , i≺m) (j , j≺m) with discreteℕ i j ... | yes p = inl λ i → p i , isPropDep≺′ m i≺m j≺m p i ... | no ¬p = inr (≢→apart i j ¬p) ≺∞ : ∀ n → n ≺ ∞ ≺∞ zero = _ ≺∞ (suc n) = ≺∞ n Σ≺∞≃ℕ : Bounded ∞ ≃ ℕ Σ≺∞≃ℕ = isoToEquiv λ where .fun → fst .inv n → n , ≺∞ n .rightInv _ → refl .leftInv (n , p) i → λ where .fst → n .snd → isProp≺ n ∞ (≺∞ n) p i where open Iso Σ≺∞≡ℕ : Bounded ∞ ≡ ℕ Σ≺∞≡ℕ = ua Σ≺∞≃ℕ _≺?_ : ∀ n c → Dec (n ≺ c) n ≺? c with force c _ ≺? c | czero = no (idfun ⊥) zero ≺? c | csuc d = yes _ suc n ≺? c | csuc d = n ≺? d ≺-pred : ∀ n c → suc n ≺ c → n ≺ c ≺-pred n c sn≺c with force c ≺-pred zero c sn≺c | csuc d = _ ≺-pred (suc n) c sn≺c | csuc d = ≺-pred n d sn≺c ≺?-yes : ∀ n c → (p : n ≺ c) → n ≺? c ≡ yes p ≺?-yes n c p with force c ≺?-yes zero c p | csuc c' = refl ≺?-yes (suc n) c p | csuc c' = ≺?-yes n c' p ∀≺-same : ∀ m n → (∀ k → (k ≺ m) ≡ (k ≺ n)) → m ≡ n ∀≺-same m n ∀≺ i .force with force m | force n ... | czero | czero = czero ... | csuc o | csuc p = csuc (∀≺-same o p (∀≺ ∘ suc) i) ... | csuc o | czero = Empty.rec {A = csuc o ≡ czero} (transport (∀≺ 0) _) i ... | czero | csuc p = Empty.rec {A = czero ≡ csuc p} (transport⁻ (∀≺ 0) _) i Bounded→Fin : ∀ m → Bounded (embed m) → Fin.Fin m Bounded→Fin (suc m) (0 , 0≺m) = Fin.zero Bounded→Fin (suc m) (suc n , n≺m) = Fin.suc (Bounded→Fin m (n , n≺m)) module Untangle {m n} (f : Bounded′ (csuc m) → Bounded′ (csuc n)) (g : Bounded′ (csuc n) → Bounded′ (csuc m)) (rinv : section f g) (linv : retract f g) where bzro : ∀{k} → Bounded′ (csuc k) bzro = (zero , _) bsuc : ∀{k} → Bounded k → Bounded′ (csuc k) bsuc (l , l≺k) = (suc l , l≺k) #-f : ∀ v u → v # u → f v # f u #-f v u v#u with discreteB′ (csuc n) (f v) (f u) ... | inr fv#fu = fv#fu ... | inl fv≡fu = rec (#→≢ v u v#u (sym (linv v) ∙∙ cong g (fv≡fu) ∙∙ linv u)) #-g : ∀ v u → v # u → g v # g u #-g v u v#u with discreteB′ (csuc m) (g v) (g u) ... | inr gv#gu = gv#gu ... | inl gv≡gu = rec (#→≢ v u v#u (sym (rinv v) ∙∙ cong f (gv≡gu) ∙∙ rinv u)) #-fg : ∀ v u → v # u → f (g v) # f (g u) #-fg v u = #-f (g v) (g u) ∘ #-g v u #-gf : ∀ v u → v # u → g (f v) # g (f u) #-gf v u = #-g (f v) (f u) ∘ #-f v u default : ∀{k} → (v d : Bounded′ (csuc k)) → v # d → Bounded k default (suc l , l≺n) d _ = (l , l≺n) default (0 , _) (suc l , l≺n) _ = (l , l≺n) f- : Bounded m → Bounded n f- v = default (f (bsuc v)) (f bzro) (#-f (bsuc v) bzro _) g- : Bounded n → Bounded m g- v = default (g (bsuc v)) (g bzro) (#-g (bsuc v) bzro _) g-f-z : ∀ v u → g bzro ≡ bsuc v → g (bsuc u) ≡ bzro → g- u ≡ v g-f-z (l , l≺m) u p q with g (bsuc u) | g bzro | #-g (bsuc u) bzro _ ... | zero , _ | suc k , k≺m | #gf = λ where i .fst → predℕ (p i .fst) i .snd → isPropDep≺ m k≺m l≺m (cong (predℕ ∘ fst) p) i ... | w@(suc k , k≺m) | dg | #gf = rec (snotz (cong fst q)) g-f-s : ∀ v u → g (bsuc u) ≡ bsuc v → g- u ≡ v g-f-s (l , l≺m) u p with g (bsuc u) | #-g (bsuc u) bzro _ ... | suc k , k≺m | #gf = λ where i .fst → predℕ (p i .fst) i .snd → isPropDep≺ m k≺m l≺m (cong (predℕ ∘ fst) p) i ... | zero , k≺m | #gf = rec (znots (cong fst p)) g-f- : ∀ v → g- (f- v) ≡ v g-f- v@(i , i≺m) with f (bsuc v) | linv (bsuc v) | #-f (bsuc v) bzro _ ... | suc j , j≺m | p | #f = g-f-s v (j , j≺m) p ... | zero , _ | p | #f with f bzro | linv bzro ... | suc k , k≺n | q = g-f-z v (k , k≺n) p q f-g-z : ∀ v u → f bzro ≡ bsuc v → f (bsuc u) ≡ bzro → f- u ≡ v f-g-z (l , l≺n) u p q with f (bsuc u) | f bzro | #-f (bsuc u) bzro _ ... | zero , _ | suc k , k≺n | #fg = λ where i .fst → predℕ (p i .fst) i .snd → isPropDep≺ n k≺n l≺n (cong (predℕ ∘ fst) p) i ... | w@(suc k , k≺m) | df | #fg = rec (snotz (cong fst q)) f-g-s : ∀ v u → f (bsuc u) ≡ bsuc v → f- u ≡ v f-g-s (l , l≺n) u p with f (bsuc u) | #-f (bsuc u) bzro _ ... | suc k , k≺n | _ = λ where i .fst → predℕ (p i .fst) i .snd → isPropDep≺ n k≺n l≺n (cong (predℕ ∘ fst) p) i ... | zero , k≺m | _ = rec (znots (cong fst p)) f-g- : ∀ v → f- (g- v) ≡ v f-g- v@(i , i≺n) with g (bsuc v) | rinv (bsuc v) | #-g (bsuc v) bzro _ ... | suc j , j≺m | p | #g = f-g-s v (j , j≺m) p ... | zero , _ | p | #g with g bzro | rinv bzro ... | suc k , k≺m | q = f-g-z v (k , k≺m) p q open Iso iso- : Iso (Bounded m) (Bounded n) iso- .fun = f- iso- .inv = g- iso- .rightInv = f-g- iso- .leftInv = g-f- untangled : ∀{m n} → Iso (Bounded′ (csuc m)) (Bounded′ (csuc n)) → Iso (Bounded m) (Bounded n) untangled isom = Untangle.iso- fun inv rightInv leftInv where open Iso isom Bounded-inj-iso : ∀ m n → Iso (Bounded m) (Bounded n) → m ≡ n Bounded-inj-iso m n theIso i .force with force m | force n ... | czero | czero = czero ... | csuc l | csuc r = csuc (Bounded-inj-iso l r (untangled theIso) i) ... | czero | csuc r = rec {A = czero ≡ csuc r} (Iso.inv theIso (zero , _) .snd) i ... | csuc l | czero = rec {A = csuc l ≡ czero} (Iso.fun theIso (zero , _) .snd) i Bounded-inj : ∀ m n → Bounded m ≡ Bounded n → m ≡ n Bounded-inj m n = Bounded-inj-iso m n ∘ pathToIso