{-# OPTIONS --safe #-}
module Data.Fin.Properties where
open import Prelude
open import Data.Pushout
open import Relation.Binary
private variable
n : ℕ
import Data.Nat.Order as ℕ
infix 4 _<ᵇ_ _<_ _≮ᵇ_ _≮_ _≤ᵇ_ _≤_
_<ᵇ_ : Fin n → Fin n → Bool
n <ᵇ m = FinToℕ n .fst ℕ.<ᵇ FinToℕ m .fst
_<_ : Fin n → Fin n → Type
n < m = T (n <ᵇ m)
_≮ᵇ_ : Fin n → Fin n → Bool
n ≮ᵇ m = ! (n <ᵇ m)
_≮_ : Fin n → Fin n → Type
n ≮ m = T (n ≮ᵇ m)
_≤ᵇ_ : Fin n → Fin n → Bool
n ≤ᵇ m = FinToℕ n .fst ℕ.≤ᵇ FinToℕ m .fst
_≤_ : Fin n → Fin n → Type
n ≤ m = T (n ≤ᵇ m)
suc-injective : (x y : Fin n) → suc x ≡ suc y → x ≡ y
suc-injective x y = cong {A = Fin _} λ { zero → x ; (suc z) → z }
foldFin : ∀ {n} → A → (Fin n → A → A) → A
foldFin {n = zero} e f = e
foldFin {n = suc n} e f = f zero (foldFin e (λ x a → f (suc x) a))
import Data.Nat.Properties as ℕ
zero≢suc : {x : Fin n} → zero ≢ suc x
zero≢suc = ℕ.zero≢suc ∘ cong (fst ∘ FinToℕ)
suc≢zero : {x : Fin n} → suc x ≢ zero
suc≢zero = ℕ.suc≢zero ∘ cong (fst ∘ FinToℕ)
private variable m : ℕ
open import Isomorphism.Properties
Fin⊥ : Fin 0 ⇔ ⊥
Fin⊥ .fun ()
Fin⊥ .inv ()
Fin⊥ .rightInv ()
Fin⊥ .leftInv ()
isPropFin1 : isProp (Fin 1)
isPropFin1 zero zero = refl
Finsuc : Fin (suc n) ⇔ (⊤ ⊎ Fin n)
Finsuc .fun zero = inl tt
Finsuc .fun (suc n) = inr n
Finsuc .inv (inl x) = zero
Finsuc .inv (inr x) = suc x
Finsuc .rightInv (inl x) = refl
Finsuc .rightInv (inr x) = refl
Finsuc .leftInv zero = refl
Finsuc .leftInv (suc x) = refl
fin-+ : (Fin n ⊎ Fin m) ⇔ Fin (n ℕ.+ m)
fin-+ {n = zero} {m = m} = cong-⇔ (_⊎ Fin m) Fin⊥ ⟨ trans-⇔ ⟩ ⊎-idˡ
fin-+ {n = suc n} {m = m} = cong-⇔ (_⊎ Fin m) Finsuc
⟨ trans-⇔ ⟩ ⊎-assoc
⟨ trans-⇔ ⟩ cong-⇔ (⊤ ⊎_) fin-+
⟨ trans-⇔ ⟩ sym-⇔ Finsuc
fin-× : (Fin n × Fin m) ⇔ Fin (n ℕ.* m)
fin-× {n = zero } {m = m} = cong-⇔ (_× Fin m) Fin⊥ ⟨ trans-⇔ ⟩ ×-annˡ ⟨ trans-⇔ ⟩ sym-⇔ Fin⊥
fin-× {n = suc n} {m = m} = cong-⇔ (_× Fin m) Finsuc
⟨ trans-⇔ ⟩ swap-×
⟨ trans-⇔ ⟩ ×-distrib-⊎
⟨ trans-⇔ ⟩ cong-⇔ (_⊎ (Fin m × Fin n)) (swap-× ⟨ trans-⇔ ⟩ ×-idˡ)
⟨ trans-⇔ ⟩ cong-⇔ (Fin m ⊎_) swap-×
⟨ trans-⇔ ⟩ cong-⇔ (Fin m ⊎_) (fin-× {n = n} {m = m})
⟨ trans-⇔ ⟩ fin-+ {n = m} {m = n ℕ.* m}