module Data.Fin.Properties where
open import Algebra
open import Data.Empty using (⊥-elim)
open import Data.Fin
open import Data.Nat as ℕ using (ℕ; zero; suc; s≤s; z≤n; _∸_) renaming
(_≤_ to _ℕ≤_
; _<_ to _ℕ<_
; _+_ to _ℕ+_)
import Data.Nat.Properties as ℕₚ
open import Data.Product
open import Function
open import Function.Equality as FunS using (_⟨$⟩_)
open import Function.Injection using (_↣_)
open import Algebra.FunctionProperties
open import Relation.Nullary
import Relation.Nullary.Decidable as Dec
open import Relation.Binary
open import Relation.Binary.PropositionalEquality as P
using (_≡_; _≢_; refl; cong; subst)
open import Category.Functor
open import Category.Applicative
infix 4 _≟_
suc-injective : ∀ {o} {m n : Fin o} → Fin.suc m ≡ suc n → m ≡ n
suc-injective refl = refl
_≟_ : {n : ℕ} → Decidable {A = Fin n} _≡_
zero ≟ zero = yes refl
zero ≟ suc y = no λ()
suc x ≟ zero = no λ()
suc x ≟ suc y with x ≟ y
... | yes x≡y = yes (cong suc x≡y)
... | no x≢y = no (x≢y ∘ suc-injective)
preorder : ℕ → Preorder _ _ _
preorder n = P.preorder (Fin n)
setoid : ℕ → Setoid _ _
setoid n = P.setoid (Fin n)
isDecEquivalence : ∀ {n} → IsDecEquivalence (_≡_ {A = Fin n})
isDecEquivalence = record
{ isEquivalence = P.isEquivalence
; _≟_ = _≟_
}
decSetoid : ℕ → DecSetoid _ _
decSetoid n = record
{ Carrier = Fin n
; _≈_ = _≡_
; isDecEquivalence = isDecEquivalence
}
to-from : ∀ n → toℕ (fromℕ n) ≡ n
to-from zero = refl
to-from (suc n) = cong suc (to-from n)
from-to : ∀ {n} (i : Fin n) → fromℕ (toℕ i) ≡ strengthen i
from-to zero = refl
from-to (suc i) = cong suc (from-to i)
toℕ-strengthen : ∀ {n} (i : Fin n) → toℕ (strengthen i) ≡ toℕ i
toℕ-strengthen zero = refl
toℕ-strengthen (suc i) = cong suc (toℕ-strengthen i)
toℕ-injective : ∀ {n} {i j : Fin n} → toℕ i ≡ toℕ j → i ≡ j
toℕ-injective {zero} {} {} _
toℕ-injective {suc n} {zero} {zero} eq = refl
toℕ-injective {suc n} {zero} {suc j} ()
toℕ-injective {suc n} {suc i} {zero} ()
toℕ-injective {suc n} {suc i} {suc j} eq =
cong suc (toℕ-injective (cong ℕ.pred eq))
bounded : ∀ {n} (i : Fin n) → toℕ i ℕ< n
bounded zero = s≤s z≤n
bounded (suc i) = s≤s (bounded i)
prop-toℕ-≤ : ∀ {n} (i : Fin n) → toℕ i ℕ≤ ℕ.pred n
prop-toℕ-≤ zero = z≤n
prop-toℕ-≤ (suc {n = zero} ())
prop-toℕ-≤ (suc {n = suc n} i) = s≤s (prop-toℕ-≤ i)
prop-toℕ-≤′ : ∀ {n} (i : Fin n) → toℕ i ℕ≤ ℕ.pred n
prop-toℕ-≤′ i = ℕₚ.<⇒≤pred (bounded i)
fromℕ≤-toℕ : ∀ {m} (i : Fin m) (i<m : toℕ i ℕ< m) → fromℕ≤ i<m ≡ i
fromℕ≤-toℕ zero (s≤s z≤n) = refl
fromℕ≤-toℕ (suc i) (s≤s (s≤s m≤n)) = cong suc (fromℕ≤-toℕ i (s≤s m≤n))
toℕ-fromℕ≤ : ∀ {m n} (m<n : m ℕ< n) → toℕ (fromℕ≤ m<n) ≡ m
toℕ-fromℕ≤ (s≤s z≤n) = refl
toℕ-fromℕ≤ (s≤s (s≤s m<n)) = cong suc (toℕ-fromℕ≤ (s≤s m<n))
fromℕ-def : ∀ n → fromℕ n ≡ fromℕ≤ ℕₚ.≤-refl
fromℕ-def zero = refl
fromℕ-def (suc n) = cong suc (fromℕ-def n)
fromℕ≤≡fromℕ≤″ :
∀ {m n} (m<n : m ℕ< n) (m<″n : m ℕ.<″ n) →
fromℕ≤ m<n ≡ fromℕ≤″ m m<″n
fromℕ≤≡fromℕ≤″ (s≤s z≤n) (ℕ.less-than-or-equal refl) = refl
fromℕ≤≡fromℕ≤″ (s≤s (s≤s m<n)) (ℕ.less-than-or-equal refl) =
cong suc (fromℕ≤≡fromℕ≤″ (s≤s m<n) (ℕ.less-than-or-equal refl))
≤-reflexive : ∀ {n} → _≡_ ⇒ (_≤_ {n})
≤-reflexive refl = ℕₚ.≤-refl
≤-refl : ∀ {n} → Reflexive (_≤_ {n})
≤-refl = ≤-reflexive refl
≤-trans : ∀ {n} → Transitive (_≤_ {n})
≤-trans = ℕₚ.≤-trans
≤-antisym : ∀ {n} → Antisymmetric _≡_ (_≤_ {n})
≤-antisym x≤y y≤x = toℕ-injective (ℕₚ.≤-antisym x≤y y≤x)
≤-total : ∀ {n} → Total (_≤_ {n})
≤-total x y = ℕₚ.≤-total (toℕ x) (toℕ y)
≤-isPreorder : ∀ {n} → IsPreorder _≡_ (_≤_ {n})
≤-isPreorder = record
{ isEquivalence = P.isEquivalence
; reflexive = ≤-reflexive
; trans = ≤-trans
}
≤-isPartialOrder : ∀ {n} → IsPartialOrder _≡_ (_≤_ {n})
≤-isPartialOrder = record
{ isPreorder = ≤-isPreorder
; antisym = ≤-antisym
}
≤-isTotalOrder : ∀ {n} → IsTotalOrder _≡_ (_≤_ {n})
≤-isTotalOrder = record
{ isPartialOrder = ≤-isPartialOrder
; total = ≤-total
}
≤-irrelevance : ∀ {n} → P.IrrelevantRel (_≤_ {n})
≤-irrelevance = ℕₚ.≤-irrelevance
≤-isDecTotalOrder : ∀ {n} → IsDecTotalOrder _≡_ (_≤_ {n})
≤-isDecTotalOrder = record
{ isTotalOrder = ≤-isTotalOrder
; _≟_ = _≟_
; _≤?_ = _≤?_
}
<-irrefl : ∀ {n} → Irreflexive _≡_ (_<_ {n})
<-irrefl refl = ℕₚ.<-irrefl refl
<-asym : ∀ {n} → Asymmetric (_<_ {n})
<-asym = ℕₚ.<-asym
<-trans : ∀ {n} → Transitive (_<_ {n})
<-trans = ℕₚ.<-trans
<-cmp : ∀ {n} → Trichotomous _≡_ (_<_ {n})
<-cmp zero zero = tri≈ (λ()) refl (λ())
<-cmp zero (suc j) = tri< (s≤s z≤n) (λ()) (λ())
<-cmp (suc i) zero = tri> (λ()) (λ()) (s≤s z≤n)
<-cmp (suc i) (suc j) with <-cmp i j
... | tri< lt ¬eq ¬gt = tri< (s≤s lt) (¬eq ∘ suc-injective) (¬gt ∘ ℕ.≤-pred)
... | tri> ¬lt ¬eq gt = tri> (¬lt ∘ ℕ.≤-pred) (¬eq ∘ suc-injective) (s≤s gt)
... | tri≈ ¬lt eq ¬gt = tri≈ (¬lt ∘ ℕ.≤-pred) (cong suc eq) (¬gt ∘ ℕ.≤-pred)
_<?_ : ∀ {n} → Decidable (_<_ {n})
m <? n = suc (toℕ m) ℕ.≤? toℕ n
<-isStrictTotalOrder : ∀ {n} → IsStrictTotalOrder _≡_ (_<_ {n})
<-isStrictTotalOrder = record
{ isEquivalence = P.isEquivalence
; trans = <-trans
; compare = <-cmp
}
<-strictTotalOrder : ℕ → StrictTotalOrder _ _ _
<-strictTotalOrder n = record
{ Carrier = Fin n
; _≈_ = _≡_
; _<_ = _<_
; isStrictTotalOrder = <-isStrictTotalOrder
}
<-irrelevance : ∀ {n} → P.IrrelevantRel (_<_ {n})
<-irrelevance = ℕₚ.<-irrelevance
nℕ-ℕi≤n : ∀ n i → n ℕ-ℕ i ℕ≤ n
nℕ-ℕi≤n n zero = ℕₚ.≤-refl
nℕ-ℕi≤n zero (suc ())
nℕ-ℕi≤n (suc n) (suc i) = begin
n ℕ-ℕ i ≤⟨ nℕ-ℕi≤n n i ⟩
n ≤⟨ ℕₚ.n≤1+n n ⟩
suc n ∎
where open ℕₚ.≤-Reasoning
inject-lemma : ∀ {n} {i : Fin n} (j : Fin′ i) →
toℕ (inject j) ≡ toℕ j
inject-lemma {i = zero} ()
inject-lemma {i = suc i} zero = refl
inject-lemma {i = suc i} (suc j) = cong suc (inject-lemma j)
inject+-lemma : ∀ {m} n (i : Fin m) → toℕ i ≡ toℕ (inject+ n i)
inject+-lemma n zero = refl
inject+-lemma n (suc i) = cong suc (inject+-lemma n i)
inject₁-lemma : ∀ {m} (i : Fin m) → toℕ (inject₁ i) ≡ toℕ i
inject₁-lemma zero = refl
inject₁-lemma (suc i) = cong suc (inject₁-lemma i)
inject≤-lemma : ∀ {m n} (i : Fin m) (le : m ℕ≤ n) →
toℕ (inject≤ i le) ≡ toℕ i
inject≤-lemma zero (s≤s le) = refl
inject≤-lemma (suc i) (s≤s le) = cong suc (inject≤-lemma i le)
inject≤-refl : ∀ {n} (i : Fin n) (n≤n : n ℕ≤ n) → inject≤ i n≤n ≡ i
inject≤-refl zero (s≤s _ ) = refl
inject≤-refl (suc i) (s≤s n≤n) = cong suc (inject≤-refl i n≤n)
≺⇒<′ : _≺_ ⇒ ℕ._<′_
≺⇒<′ (n ≻toℕ i) = ℕₚ.≤⇒≤′ (bounded i)
<′⇒≺ : ℕ._<′_ ⇒ _≺_
<′⇒≺ {n} ℕ.≤′-refl = subst (λ i → i ≺ suc n) (to-from n)
(suc n ≻toℕ fromℕ n)
<′⇒≺ (ℕ.≤′-step m≤′n) with <′⇒≺ m≤′n
<′⇒≺ (ℕ.≤′-step m≤′n) | n ≻toℕ i =
subst (λ i → i ≺ suc n) (inject₁-lemma i) (suc n ≻toℕ (inject₁ i))
toℕ-raise : ∀ {m} n (i : Fin m) → toℕ (raise n i) ≡ n ℕ+ toℕ i
toℕ-raise zero i = refl
toℕ-raise (suc n) i = cong suc (toℕ-raise n i)
infixl 6 _+′_
_+′_ : ∀ {m n} (i : Fin m) (j : Fin n) → Fin (ℕ.pred m ℕ+ n)
i +′ j = inject≤ (i + j) (ℕₚ.+-mono-≤ (prop-toℕ-≤ i) ℕₚ.≤-refl)
reverse : ∀ {n} → Fin n → Fin n
reverse {zero} ()
reverse {suc n} i = inject≤ (n ℕ- i) (ℕₚ.n∸m≤n (toℕ i) (suc n))
reverse-prop : ∀ {n} → (i : Fin n) → toℕ (reverse i) ≡ n ∸ suc (toℕ i)
reverse-prop {zero} ()
reverse-prop {suc n} i = begin
toℕ (inject≤ (n ℕ- i) _) ≡⟨ inject≤-lemma _ _ ⟩
toℕ (n ℕ- i) ≡⟨ toℕ‿ℕ- n i ⟩
n ∸ toℕ i ∎
where
open P.≡-Reasoning
toℕ‿ℕ- : ∀ n i → toℕ (n ℕ- i) ≡ n ∸ toℕ i
toℕ‿ℕ- n zero = to-from n
toℕ‿ℕ- zero (suc ())
toℕ‿ℕ- (suc n) (suc i) = toℕ‿ℕ- n i
reverse-involutive : ∀ {n} → Involutive _≡_ (reverse {n})
reverse-involutive {zero} ()
reverse-involutive {suc n} i = toℕ-injective (begin
toℕ (reverse (reverse i)) ≡⟨ reverse-prop (reverse i) ⟩
n ∸ (toℕ (reverse i)) ≡⟨ P.cong (n ∸_) (reverse-prop i) ⟩
n ∸ (n ∸ (toℕ i)) ≡⟨ ℕₚ.m∸[m∸n]≡n (ℕ.≤-pred (bounded i)) ⟩
toℕ i ∎)
where open P.≡-Reasoning
reverse-suc : ∀{n}{i : Fin n} → toℕ (reverse (suc i)) ≡ toℕ (reverse i)
reverse-suc {n}{i} = begin
toℕ (reverse (suc i)) ≡⟨ reverse-prop (suc i) ⟩
suc n ∸ suc (toℕ (suc i)) ≡⟨⟩
n ∸ toℕ (suc i) ≡⟨⟩
n ∸ suc (toℕ i) ≡⟨ P.sym (reverse-prop i) ⟩
toℕ (reverse i) ∎
where
open P.≡-Reasoning
eq? : ∀ {a n} {A : Set a} → A ↣ Fin n → Decidable {A = A} _≡_
eq? inj = Dec.via-injection inj _≟_
sequence : ∀ {F n} {P : Fin n → Set} → RawApplicative F →
(∀ i → F (P i)) → F (∀ i → P i)
sequence {F} RA = helper _ _
where
open RawApplicative RA
helper : ∀ n (P : Fin n → Set) → (∀ i → F (P i)) → F (∀ i → P i)
helper zero P ∀iPi = pure (λ())
helper (suc n) P ∀iPi =
combine <$> ∀iPi zero ⊛ helper n (λ n → P (suc n)) (∀iPi ∘ suc)
where
combine : P zero → (∀ i → P (suc i)) → ∀ i → P i
combine z s zero = z
combine z s (suc i) = s i
private
sequence⁻¹ : ∀ {F}{A} {P : A → Set} → RawFunctor F →
F (∀ i → P i) → ∀ i → F (P i)
sequence⁻¹ RF F∀iPi i = (λ f → f i) <$> F∀iPi
where open RawFunctor RF
punchOut-injective : ∀ {m} {i j k : Fin (suc m)}
(i≢j : i ≢ j) (i≢k : i ≢ k) →
punchOut i≢j ≡ punchOut i≢k → j ≡ k
punchOut-injective {_} {zero} {zero} {_} i≢j _ _ = ⊥-elim (i≢j refl)
punchOut-injective {_} {zero} {_} {zero} _ i≢k _ = ⊥-elim (i≢k refl)
punchOut-injective {_} {zero} {suc j} {suc k} _ _ pⱼ≡pₖ = cong suc pⱼ≡pₖ
punchOut-injective {zero} {suc ()}
punchOut-injective {suc n} {suc i} {zero} {zero} _ _ _ = refl
punchOut-injective {suc n} {suc i} {zero} {suc k} _ _ ()
punchOut-injective {suc n} {suc i} {suc j} {zero} _ _ ()
punchOut-injective {suc n} {suc i} {suc j} {suc k} i≢j i≢k pⱼ≡pₖ =
cong suc (punchOut-injective (i≢j ∘ cong suc) (i≢k ∘ cong suc) (suc-injective pⱼ≡pₖ))
punchIn-injective : ∀ {m} i (j k : Fin m) →
punchIn i j ≡ punchIn i k → j ≡ k
punchIn-injective zero _ _ refl = refl
punchIn-injective (suc i) zero zero _ = refl
punchIn-injective (suc i) zero (suc k) ()
punchIn-injective (suc i) (suc j) zero ()
punchIn-injective (suc i) (suc j) (suc k) ↑j+1≡↑k+1 =
cong suc (punchIn-injective i j k (suc-injective ↑j+1≡↑k+1))
punchIn-punchOut : ∀ {m} {i j : Fin (suc m)} (i≢j : i ≢ j) →
punchIn i (punchOut i≢j) ≡ j
punchIn-punchOut {_} {zero} {zero} 0≢0 = ⊥-elim (0≢0 refl)
punchIn-punchOut {_} {zero} {suc j} _ = refl
punchIn-punchOut {zero} {suc ()}
punchIn-punchOut {suc m} {suc i} {zero} i≢j = refl
punchIn-punchOut {suc m} {suc i} {suc j} i≢j =
cong suc (punchIn-punchOut (i≢j ∘ cong suc))
punchInᵢ≢i : ∀ {m} i (j : Fin m) → punchIn i j ≢ i
punchInᵢ≢i zero _ ()
punchInᵢ≢i (suc i) zero ()
punchInᵢ≢i (suc i) (suc j) = punchInᵢ≢i i j ∘ suc-injective
cmp = <-cmp
strictTotalOrder = <-strictTotalOrder