{-# OPTIONS --no-exact-split --safe #-}
module Cubical.Data.BinNat.BinNat where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Univalence
open import Cubical.Foundations.Isomorphism
open import Cubical.Data.Nat
open import Cubical.Data.Bool
open import Cubical.Data.Empty
open import Cubical.Relation.Nullary
data Binℕ : Type₀
data Pos : Type₀
data Binℕ where
binℕ0 : Binℕ
binℕpos : Pos → Binℕ
data Pos where
x0 : Pos → Pos
x1 : Binℕ → Pos
pattern pos1 = x1 binℕ0
pattern x1-pos n = x1 (binℕpos n)
Binℕ⇒Pos : Binℕ → Pos
sucPos : Pos → Pos
Binℕ⇒Pos binℕ0 = pos1
Binℕ⇒Pos (binℕpos n) = sucPos n
sucPos (x0 ps) = x1-pos ps
sucPos (x1 ps) = x0 (Binℕ⇒Pos ps)
Binℕ→ℕ : Binℕ → ℕ
Pos⇒ℕ : Pos → ℕ
Pos→ℕ : Pos → ℕ
Binℕ→ℕ binℕ0 = zero
Binℕ→ℕ (binℕpos x) = Pos→ℕ x
Pos→ℕ ps = suc (Pos⇒ℕ ps)
Pos⇒ℕ (x0 ps) = suc (doubleℕ (Pos⇒ℕ ps))
Pos⇒ℕ (x1 ps) = doubleℕ (Binℕ→ℕ ps)
posInd : {P : Pos → Type₀} → P pos1 → ((p : Pos) → P p → P (sucPos p)) → (p : Pos) → P p
posInd {P} h1 hs ps = f ps
where
H : (p : Pos) → P (x0 p) → P (x0 (sucPos p))
H p hx0p = hs (x1-pos p) (hs (x0 p) hx0p)
f : (ps : Pos) → P ps
f pos1 = h1
f (x0 ps) = posInd (hs pos1 h1) H ps
f (x1-pos ps) = hs (x0 ps) (posInd (hs pos1 h1) H ps)
Binℕ⇒Pos⇒ℕ : (p : Binℕ) → Pos⇒ℕ (Binℕ⇒Pos p) ≡ Binℕ→ℕ p
Binℕ⇒Pos⇒ℕ binℕ0 = refl
Binℕ⇒Pos⇒ℕ (binℕpos (x0 p)) = refl
Binℕ⇒Pos⇒ℕ (binℕpos (x1 x)) = λ i → suc (doubleℕ (Binℕ⇒Pos⇒ℕ x i))
Pos⇒ℕsucPos : (p : Pos) → Pos⇒ℕ (sucPos p) ≡ suc (Pos⇒ℕ p)
Pos⇒ℕsucPos p = Binℕ⇒Pos⇒ℕ (binℕpos p)
Pos→ℕsucPos : (p : Pos) → Pos→ℕ (sucPos p) ≡ suc (Pos→ℕ p)
Pos→ℕsucPos p = cong suc (Binℕ⇒Pos⇒ℕ (binℕpos p))
ℕ⇒Pos : ℕ → Pos
ℕ⇒Pos zero = pos1
ℕ⇒Pos (suc n) = sucPos (ℕ⇒Pos n)
ℕ→Pos : ℕ → Pos
ℕ→Pos zero = pos1
ℕ→Pos (suc n) = ℕ⇒Pos n
Pos⇒ℕ⇒Pos : (p : Pos) → ℕ⇒Pos (Pos⇒ℕ p) ≡ p
Pos⇒ℕ⇒Pos p = posInd refl hs p
where
hs : (p : Pos) → ℕ⇒Pos (Pos⇒ℕ p) ≡ p → ℕ⇒Pos (Pos⇒ℕ (sucPos p)) ≡ sucPos p
hs p hp =
ℕ⇒Pos (Pos⇒ℕ (sucPos p)) ≡⟨ cong ℕ⇒Pos (Pos⇒ℕsucPos p) ⟩
sucPos (ℕ⇒Pos (Pos⇒ℕ p)) ≡⟨ cong sucPos hp ⟩
sucPos p ∎
ℕ⇒Pos⇒ℕ : (n : ℕ) → Pos⇒ℕ (ℕ⇒Pos n) ≡ n
ℕ⇒Pos⇒ℕ zero = refl
ℕ⇒Pos⇒ℕ (suc n) =
Pos⇒ℕ (ℕ⇒Pos (suc n)) ≡⟨ Pos⇒ℕsucPos (ℕ⇒Pos n) ⟩
suc (Pos⇒ℕ (ℕ⇒Pos n)) ≡⟨ cong suc (ℕ⇒Pos⇒ℕ n) ⟩
suc n ∎
ℕ→Binℕ : ℕ → Binℕ
ℕ→Binℕ zero = binℕ0
ℕ→Binℕ (suc n) = binℕpos (ℕ⇒Pos n)
ℕ→Binℕ→ℕ : (n : ℕ) → Binℕ→ℕ (ℕ→Binℕ n) ≡ n
ℕ→Binℕ→ℕ zero = refl
ℕ→Binℕ→ℕ (suc n) = cong suc (ℕ⇒Pos⇒ℕ n)
Binℕ→ℕ→Binℕ : (n : Binℕ) → ℕ→Binℕ (Binℕ→ℕ n) ≡ n
Binℕ→ℕ→Binℕ binℕ0 = refl
Binℕ→ℕ→Binℕ (binℕpos p) = cong binℕpos (Pos⇒ℕ⇒Pos p)
Binℕ≃ℕ : Binℕ ≃ ℕ
Binℕ≃ℕ = isoToEquiv (iso Binℕ→ℕ ℕ→Binℕ ℕ→Binℕ→ℕ Binℕ→ℕ→Binℕ)
Binℕ≡ℕ : Binℕ ≡ ℕ
Binℕ≡ℕ = ua Binℕ≃ℕ
sucBinℕ : Binℕ → Binℕ
sucBinℕ x = binℕpos (Binℕ⇒Pos x)
Binℕ→ℕsuc : (x : Binℕ) → suc (Binℕ→ℕ x) ≡ Binℕ→ℕ (sucBinℕ x)
Binℕ→ℕsuc binℕ0 = refl
Binℕ→ℕsuc (binℕpos x) = sym (Pos→ℕsucPos x)
_+Binℕ_ : Binℕ → Binℕ → Binℕ
_+Binℕ_ = transport (λ i → Binℕ≡ℕ (~ i) → Binℕ≡ℕ (~ i) → Binℕ≡ℕ (~ i)) _+_
private
_ : binℕpos (x0 (x0 pos1)) +Binℕ binℕpos pos1 ≡ binℕpos (x1-pos (x0 pos1))
_ = refl
oddBinℕ : Binℕ → Bool
oddBinℕ binℕ0 = false
oddBinℕ (binℕpos (x0 _)) = false
oddBinℕ (binℕpos (x1 _)) = true
evenBinℕ : Binℕ → Bool
evenBinℕ n = oddBinℕ (sucBinℕ n)
oddBinℕnotEvenBinℕ : (n : Binℕ) → oddBinℕ n ≡ not (evenBinℕ n)
oddBinℕnotEvenBinℕ binℕ0 = refl
oddBinℕnotEvenBinℕ (binℕpos (x0 x)) = refl
oddBinℕnotEvenBinℕ (binℕpos (x1 x)) = refl
private
oddn : ℕ → Bool
oddn zero = true
oddn (suc x) = not (oddn x)
evenn : ℕ → Bool
evenn n = not (oddn n)
oddnSuc : (n : ℕ) → oddn n ≡ not (evenn n)
oddnSuc zero = refl
oddnSuc (suc n) = cong not (oddnSuc n)
oddℕ : ℕ → Bool
oddℕ = transport (λ i → Binℕ≡ℕ i → Bool) oddBinℕ
evenℕ : ℕ → Bool
evenℕ = transport (λ i → Binℕ≡ℕ i → Bool) evenBinℕ
oddℕnotEvenℕ : (n : ℕ) → oddℕ n ≡ not (evenℕ n)
oddℕnotEvenℕ =
let
oddp : PathP (λ i → Binℕ≡ℕ i → Bool) oddBinℕ oddℕ
oddp i = transp (λ j → Binℕ≡ℕ (i ∧ j) → Bool) (~ i) oddBinℕ
evenp : PathP (λ i → Binℕ≡ℕ i → Bool) evenBinℕ evenℕ
evenp i = transp (λ j → Binℕ≡ℕ (i ∧ j) → Bool) (~ i) evenBinℕ
in
transport (λ i → (n : Binℕ≡ℕ i) → oddp i n ≡ not (evenp i n)) oddBinℕnotEvenBinℕ
addp : PathP (λ i → Binℕ≡ℕ (~ i) → Binℕ≡ℕ (~ i) → Binℕ≡ℕ (~ i)) _+_ _+Binℕ_
addp i = transp (λ j → Binℕ≡ℕ (~ i ∨ ~ j) → Binℕ≡ℕ (~ i ∨ ~ j) → Binℕ≡ℕ (~ i ∨ ~ j)) (~ i) _+_
+Binℕ-assoc : ∀ m n o → m +Binℕ (n +Binℕ o) ≡ (m +Binℕ n) +Binℕ o
+Binℕ-assoc =
transport (λ i → (m n o : Binℕ≡ℕ (~ i))
→ addp i m (addp i n o) ≡ addp i (addp i m n) o) +-assoc
record NatImpl (A : Type₀) : Type₀ where
field
z : A
s : A → A
open NatImpl
NatImplℕ : NatImpl ℕ
z NatImplℕ = zero
s NatImplℕ = suc
NatImplBinℕ : NatImpl Binℕ
z NatImplBinℕ = binℕ0
s NatImplBinℕ = sucBinℕ
NatImplℕ≡Binℕ : PathP (λ i → NatImpl (Binℕ≡ℕ (~ i))) NatImplℕ NatImplBinℕ
z (NatImplℕ≡Binℕ i) = transp (λ j → Binℕ≡ℕ (~ i ∨ ~ j)) (~ i) zero
s (NatImplℕ≡Binℕ i) =
λ x → glue (λ { (i = i0) → suc x
; (i = i1) → sucBinℕ x })
(hcomp (λ j → λ { (i = i0) → suc x
; (i = i1) → Binℕ→ℕsuc x j })
(suc (unglue (i ∨ ~ i) x)))
+Binℕ-suc : ∀ m n → m +Binℕ sucBinℕ n ≡ sucBinℕ (m +Binℕ n)
+Binℕ-suc =
transport (λ i → (m n : Binℕ≡ℕ (~ i))
→ addp i m (NatImplℕ≡Binℕ i .s n) ≡ NatImplℕ≡Binℕ i .s (addp i m n)) +-suc
record Double {ℓ} (A : Type ℓ) : Type (ℓ-suc ℓ) where
field
double : A → A
elt : A
open Double
doubles : ∀ {ℓ} {A : Type ℓ} (D : Double A) → ℕ → A → A
doubles D n x = iter n (double D) x
Doubleℕ : Double ℕ
double Doubleℕ = doubleℕ
elt Doubleℕ = n1024
where
n1024 : ℕ
n1024 = doublesℕ 8 4
doubleBinℕ : Binℕ → Binℕ
doubleBinℕ binℕ0 = binℕ0
doubleBinℕ (binℕpos x) = binℕpos (x0 x)
DoubleBinℕ : Double Binℕ
double DoubleBinℕ = doubleBinℕ
elt DoubleBinℕ = bin1024
where
bin1024 : Binℕ
bin1024 = binℕpos (x0 (x0 (x0 (x0 (x0 (x0 (x0 (x0 (x0 (x0 pos1))))))))))
Binℕ→ℕdouble : (x : Binℕ) → doubleℕ (Binℕ→ℕ x) ≡ Binℕ→ℕ (doubleBinℕ x)
Binℕ→ℕdouble binℕ0 = refl
Binℕ→ℕdouble (binℕpos x) = refl
DoubleBinℕ≡Doubleℕ : PathP (λ i → Double (Binℕ≡ℕ i)) DoubleBinℕ Doubleℕ
double (DoubleBinℕ≡Doubleℕ i) =
λ x → glue (λ { (i = i0) → doubleBinℕ x
; (i = i1) → doubleℕ x })
(hcomp (λ j → λ { (i = i0) → Binℕ→ℕdouble x j
; (i = i1) → doubleℕ x })
(doubleℕ (unglue (i ∨ ~ i) x)))
elt (DoubleBinℕ≡Doubleℕ i) = transp (λ j → Binℕ≡ℕ (i ∨ ~ j)) i (Doubleℕ .elt)
record propDouble {ℓ} {A : Type ℓ} (D : Double A) : Type ℓ where
field
proof : doubles D 20 (elt D) ≡ doubles D 5 (doubles D 15 (elt D))
open propDouble
propDoubleBinℕ : propDouble DoubleBinℕ
proof propDoubleBinℕ = refl
propDoubleℕ : propDouble Doubleℕ
propDoubleℕ = transport (λ i → propDouble (DoubleBinℕ≡Doubleℕ i)) propDoubleBinℕ
data binnat : Type₀ where
zero : binnat
consOdd : binnat → binnat
consEven : binnat → binnat
binnat→ℕ : binnat → ℕ
binnat→ℕ zero = 0
binnat→ℕ (consOdd n) = suc (doubleℕ (binnat→ℕ n))
binnat→ℕ (consEven n) = suc (suc (doubleℕ (binnat→ℕ n)))
suc-binnat : binnat → binnat
suc-binnat zero = consOdd zero
suc-binnat (consOdd n) = consEven n
suc-binnat (consEven n) = consOdd (suc-binnat n)
ℕ→binnat : ℕ → binnat
ℕ→binnat zero = zero
ℕ→binnat (suc n) = suc-binnat (ℕ→binnat n)
binnat→ℕ-suc : (n : binnat) → binnat→ℕ (suc-binnat n) ≡ suc (binnat→ℕ n)
binnat→ℕ-suc zero = refl
binnat→ℕ-suc (consOdd n) = refl
binnat→ℕ-suc (consEven n) = λ i → suc (doubleℕ (binnat→ℕ-suc n i))
ℕ→binnat→ℕ : (n : ℕ) → binnat→ℕ (ℕ→binnat n) ≡ n
ℕ→binnat→ℕ zero = refl
ℕ→binnat→ℕ (suc n) = (binnat→ℕ-suc (ℕ→binnat n)) ∙ (cong suc (ℕ→binnat→ℕ n))
suc-ℕ→binnat-double : (n : ℕ) → suc-binnat (ℕ→binnat (doubleℕ n)) ≡ consOdd (ℕ→binnat n)
suc-ℕ→binnat-double zero = refl
suc-ℕ→binnat-double (suc n) = λ i → suc-binnat (suc-binnat (suc-ℕ→binnat-double n i))
binnat→ℕ→binnat : (n : binnat) → ℕ→binnat (binnat→ℕ n) ≡ n
binnat→ℕ→binnat zero = refl
binnat→ℕ→binnat (consOdd n) =
(suc-ℕ→binnat-double (binnat→ℕ n)) ∙ (cong consOdd (binnat→ℕ→binnat n))
binnat→ℕ→binnat (consEven n) =
(λ i → suc-binnat (suc-ℕ→binnat-double (binnat→ℕ n) i)) ∙ (cong consEven (binnat→ℕ→binnat n))
ℕ≃binnat : ℕ ≃ binnat
ℕ≃binnat = isoToEquiv (iso ℕ→binnat binnat→ℕ binnat→ℕ→binnat ℕ→binnat→ℕ)
ℕ≡binnat : ℕ ≡ binnat
ℕ≡binnat = ua ℕ≃binnat
_+binnat_ : binnat → binnat → binnat
_+binnat_ = transport (λ i → ℕ≡binnat i → ℕ≡binnat i → ℕ≡binnat i) _+_
_ : consEven (consOdd zero) +binnat consOdd zero ≡ consOdd (consEven zero)
_ = refl
oddbinnat : binnat → Bool
oddbinnat zero = false
oddbinnat (consOdd _) = true
oddbinnat (consEven _) = false
oddℕ' : ℕ → Bool
oddℕ' = transport (λ i → ℕ≡binnat (~ i) → Bool) oddbinnat
private
NatImplbinnat : NatImpl binnat
z NatImplbinnat = zero
s NatImplbinnat = suc-binnat
NatImplℕ≡NatImplbinnat : PathP (λ i → NatImpl (ℕ≡binnat i)) NatImplℕ NatImplbinnat
z (NatImplℕ≡NatImplbinnat i) = transp (λ j → ℕ≡binnat (i ∨ ~ j)) i zero
s (NatImplℕ≡NatImplbinnat i) =
λ x → glue (λ { (i = i0) → suc x
; (i = i1) → suc-binnat x })
(suc-binnat (unglue (i ∨ ~ i) x))
oddSuc : (n : binnat) → oddbinnat n ≡ not (oddbinnat (suc-binnat n))
oddSuc zero = refl
oddSuc (consOdd _) = refl
oddSuc (consEven _) = refl
oddℕSuc' : (n : ℕ) → oddℕ' n ≡ not (oddℕ' (suc n))
oddℕSuc' =
let eq : (i : I) → ℕ≡binnat (~ i) → Bool
eq i = transp (λ j → ℕ≡binnat (~ i ∨ ~ j) → Bool) (~ i) oddbinnat
in transport
(λ i → (n : ℕ≡binnat (~ i)) → eq i n ≡ not (eq i (NatImplℕ≡NatImplbinnat (~ i) .NatImpl.s n)))
oddSuc