Idris2/libs/base/Data/Vect/AtIndex.idr
2021-09-09 10:45:11 +01:00

95 lines
2.5 KiB
Idris

||| Indexing Vectors.
|||
||| `Elem` proofs give existential quantification that a given element
||| *is* in the list, but not where in the list it is! Here we give a
||| predicate that presents proof that a given index of a vector,
||| given by a `Fin` instance, will return a certain element.
|||
||| Two decidable decision procedures are presented:
|||
||| 1. Check that a given index points to the provided element in the
||| presented vector.
|||
||| 2. Find the element at the given index in the presented vector.
module Data.Vect.AtIndex
import Data.Vect
import Decidable.Equality
%default total
public export
data AtIndex : (idx : Fin n)
-> (xs : Vect n type)
-> (x : type)
-> Type
where
Here : AtIndex FZ (x::xs) x
There : (later : AtIndex rest xs x)
-> AtIndex (FS rest) (y::xs) x
namespace Check
public export
elemDiffers : (y = x -> Void)
-> AtIndex FZ (y :: xs) x
-> Void
elemDiffers f Here
= f Refl
public export
elemNotInRest : (AtIndex z xs x -> Void)
-> AtIndex (FS z) (y :: xs) x
-> Void
elemNotInRest f (There later)
= f later
||| Is the element at the given index?
|||
public export
index : DecEq type
=> (idx : Fin n)
-> (x : type)
-> (xs : Vect n type)
-> Dec (AtIndex idx xs x)
index FZ _ [] impossible
index (FS y) _ [] impossible
index FZ x (y :: xs) with (decEq y x)
index FZ x (x :: xs) | (Yes Refl)
= Yes Here
index FZ x (y :: xs) | (No contra)
= No (elemDiffers contra)
index (FS z) x (y :: xs) with (Check.index z x xs)
index (FS z) x (y :: xs) | (Yes prf)
= Yes (There prf)
index (FS z) x (y :: xs) | (No contra)
= No (elemNotInRest contra)
namespace Find
public export
elemNotInRest : (DPair type (AtIndex x xs) -> Void)
-> DPair type (AtIndex (FS x) (y :: xs)) -> Void
elemNotInRest f (MkDPair i (There later))
= f (MkDPair i later)
||| What is the element at the given index?
|||
public export
index : DecEq type
=> (idx : Fin n)
-> (xs : Vect n type)
-> Dec (DPair type (AtIndex idx xs))
index FZ (x :: xs)
= Yes (MkDPair x Here)
index (FS x) (y :: xs) with (Find.index x xs)
index (FS x) (y :: xs) | (Yes (MkDPair i idx))
= Yes (MkDPair i (There idx))
index (FS x) (y :: xs) | (No contra) = No (elemNotInRest contra)
-- [ EOF ]