on 465cc1c help sign in
Idris-dev/libs/base/Data/VectType.idr
599 lines 21 kB history raw
1module Data.VectType
3import Data.Fin
5%access public
6%default total
8namespace Vect {
10infixr 7 ::
12%elim data Vect : Nat -> Type -> Type where
13 Nil : Vect Z a
14 (::) : (x : a) -> (xs : Vect n a) -> Vect (S n) a
16-- Hints for interactive editing
17%name Vect xs,ys,zs,ws
19--------------------------------------------------------------------------------
20-- Length
21--------------------------------------------------------------------------------
23||| Calculate the length of a `Vect`.
24|||
25||| **Note**: this is only useful if you don't already statically know the length
26||| and you want to avoid matching the implicit argument for erasure reasons.
27||| @ n the length (provably equal to the return value)
28||| @ xs the vector
29length : (xs : Vect n a) -> Nat
30length [] = 0
31length (x::xs) = 1 + length xs
33||| Show that the length function on vectors in fact calculates the length
34private lengthCorrect : (n : Nat) -> (xs : Vect n a) -> length xs = n
35lengthCorrect Z [] = Refl
36lengthCorrect (S n) (x :: xs) = rewrite lengthCorrect n xs in Refl
38--------------------------------------------------------------------------------
39-- Indexing into vectors
40--------------------------------------------------------------------------------
42||| All but the first element of the vector
43tail : Vect (S n) a -> Vect n a
44tail (x::xs) = xs
46||| Only the first element of the vector
47head : Vect (S n) a -> a
48head (x::xs) = x
50||| The last element of the vector
51last : Vect (S n) a -> a
52last (x::[]) = x
53last (x::y::ys) = last $ y::ys
55||| All but the last element of the vector
56init : Vect (S n) a -> Vect n a
57init (x::[]) = []
58init (x::y::ys) = x :: init (y::ys)
60||| Extract a particular element from a vector
61index : Fin n -> Vect n a -> a
62index FZ (x::xs) = x
63index (FS k) (x::xs) = index k xs
66||| Insert an element at a particular index
67insertAt : Fin (S n) -> a -> Vect n a -> Vect (S n) a
68insertAt FZ y xs = y :: xs
69insertAt (FS k) y (x::xs) = x :: insertAt k y xs
70insertAt (FS k) y [] = absurd k
72||| Construct a new vector consisting of all but the indicated element
73deleteAt : Fin (S n) -> Vect (S n) a -> Vect n a
74deleteAt FZ (x::xs) = xs
75deleteAt {n = S m} (FS k) (x::xs) = x :: deleteAt k xs
76deleteAt {n = Z} (FS k) (x::xs) = absurd k
77deleteAt _ [] impossible
79||| Replace an element at a particlar index with another
80replaceAt : Fin n -> t -> Vect n t -> Vect n t
81replaceAt FZ y (x::xs) = y :: xs
82replaceAt (FS k) y (x::xs) = x :: replaceAt k y xs
84||| Replace the element at a particular index with the result of applying a function to it
85||| @ i the index to replace at
86||| @ f the update function
87||| @ xs the vector to replace in
88updateAt : (i : Fin n) -> (f : t -> t) -> (xs : Vect n t) -> Vect n t
89updateAt FZ f (x::xs) = f x :: xs
90updateAt (FS k) f (x::xs) = x :: updateAt k f xs
92--------------------------------------------------------------------------------
93-- Subvectors
94--------------------------------------------------------------------------------
96||| Get the first m elements of a Vect
97||| @ m the number of elements to take
98take : (n : Nat) -> Vect (n + m) a -> Vect n a
99take Z xs = []
100take (S k) (x :: xs) = x :: take k xs
102||| Remove the first m elements of a Vect
103||| @ m the number of elements to remove
104drop : (n : Nat) -> Vect (n + m) a -> Vect m a
105drop Z xs = xs
106drop (S k) (x :: xs) = drop k xs
108||| Take the longest prefix of a Vect such that all elements satisfy some
109||| Boolean predicate.
110|||
111||| @ p the predicate
112takeWhile : (p : a -> Bool) -> Vect n a -> (q ** Vect q a)
113takeWhile p [] = (_ ** [])
114takeWhile p (x::xs) =
115 let (len ** ys) = takeWhile p xs
116 in if p x then
117 (S len ** x :: ys)
118 else
119 (_ ** [])
121||| Remove the longest prefix of a Vect such that all removed elements satisfy some
122||| Boolean predicate.
123|||
124||| @ p the predicate
125dropWhile : (p : a -> Bool) -> Vect n a -> (q ** Vect q a)
126dropWhile p [] = (_ ** [])
127dropWhile p (x::xs) =
128 if p x then
129 dropWhile p xs
130 else
131 (_ ** x::xs)
133--------------------------------------------------------------------------------
134-- Transformations
135--------------------------------------------------------------------------------
137||| Reverse the order of the elements of a vector
138reverse : Vect n a -> Vect n a
139reverse xs = go [] xs
140 where go : Vect n a -> Vect m a -> Vect (n+m) a
141 go {n} acc [] = rewrite plusZeroRightNeutral n in acc
142 go {n} {m=S m} acc (x :: xs) = rewrite sym $ plusSuccRightSucc n m
143 in go (x::acc) xs
145||| Alternate an element between the other elements of a vector
146||| @ sep the element to intersperse
147||| @ xs the vector to separate with `sep`
148intersperse : (sep : a) -> (xs : Vect n a) -> Vect (n + pred n) a
149intersperse sep [] = []
150intersperse sep (x::xs) = x :: intersperse' sep xs
151 where
152 intersperse' : a -> Vect n a -> Vect (n + n) a
153 intersperse' sep [] = []
154 intersperse' {n=S n} sep (x::xs) = rewrite sym $ plusSuccRightSucc n n
155 in sep :: x :: intersperse' sep xs
157--------------------------------------------------------------------------------
158-- Conversion from list (toList is provided by Foldable)
159--------------------------------------------------------------------------------
162fromList' : Vect n a -> (l : List a) -> Vect (length l + n) a
163fromList' ys [] = ys
164fromList' {n} ys (x::xs) =
165 rewrite (plusSuccRightSucc (length xs) n) ==>
166 Vect (plus (length xs) (S n)) a in
167 fromList' (x::ys) xs
169||| Convert a list to a vector.
170|||
171||| The length of the list should be statically known.
172fromList : (l : List a) -> Vect (length l) a
173fromList l =
174 rewrite (sym $ plusZeroRightNeutral (length l)) in
175 reverse $ fromList' [] l
177--------------------------------------------------------------------------------
178-- Building (bigger) vectors
179--------------------------------------------------------------------------------
181||| Append two vectors
182(++) : Vect m a -> Vect n a -> Vect (m + n) a
183(++) [] ys = ys
184(++) (x::xs) ys = x :: xs ++ ys
186||| Repeate some value n times
187||| @ n the number of times to repeat it
188||| @ x the value to repeat
189replicate : (n : Nat) -> (x : a) -> Vect n a
190replicate Z x = []
191replicate (S k) x = x :: replicate k x
193--------------------------------------------------------------------------------
194-- Zips and unzips
195--------------------------------------------------------------------------------
197||| Combine two equal-length vectors pairwise with some function
198zipWith : (a -> b -> c) -> Vect n a -> Vect n b -> Vect n c
199zipWith f [] [] = []
200zipWith f (x::xs) (y::ys) = f x y :: zipWith f xs ys
202||| Combine three equal-length vectors into a vector with some function
203zipWith3 : (a -> b -> c -> d) -> Vect n a -> Vect n b -> Vect n c -> Vect n d
204zipWith3 f [] [] [] = []
205zipWith3 f (x::xs) (y::ys) (z::zs) = f x y z :: zipWith3 f xs ys zs
207||| Combine two equal-length vectors pairwise
208zip : Vect n a -> Vect n b -> Vect n (a, b)
209zip = zipWith (\x,y => (x,y))
211||| Combine three equal-length vectors elementwise into a vector of tuples
212zip3 : Vect n a -> Vect n b -> Vect n c -> Vect n (a, b, c)
213zip3 = zipWith3 (\x,y,z => (x,y,z))
215||| Convert a vector of pairs to a pair of vectors
216unzip : Vect n (a, b) -> (Vect n a, Vect n b)
217unzip [] = ([], [])
218unzip ((l, r)::xs) with (unzip xs)
219 | (lefts, rights) = (l::lefts, r::rights)
221||| Convert a vector of three-tuples to a triplet of vectors
222unzip3 : Vect n (a, b, c) -> (Vect n a, Vect n b, Vect n c)
223unzip3 [] = ([], [], [])
224unzip3 ((l,c,r)::xs) with (unzip3 xs)
225 | (lefts, centers, rights) = (l::lefts, c::centers, r::rights)
227--------------------------------------------------------------------------------
228-- Equality
229--------------------------------------------------------------------------------
231instance (Eq a) => Eq (Vect n a) where
232 (==) [] [] = True
233 (==) (x::xs) (y::ys) =
234 if x == y then
235 xs == ys
236 else
237 False
240--------------------------------------------------------------------------------
241-- Order
242--------------------------------------------------------------------------------
244instance Ord a => Ord (Vect n a) where
245 compare [] [] = EQ
246 compare (x::xs) (y::ys) =
247 if x /= y then
248 compare x y
249 else
250 compare xs ys
253--------------------------------------------------------------------------------
254-- Maps
255--------------------------------------------------------------------------------
257instance Functor (Vect n) where
258 map f [] = []
259 map f (x::xs) = f x :: map f xs
262||| Map a partial function across a vector, returning those elements for which
263||| the function had a value.
264|||
265||| The first projection of the resulting pair (ie the length) will always be
266||| at most the length of the input vector. This is not, however, guaranteed
267||| by the type.
268|||
269||| @ f the partial function (expressed by returning `Maybe`)
270||| @ xs the vector to check for results
271mapMaybe : (f : a -> Maybe b) -> (xs : Vect n a) -> (m : Nat ** Vect m b)
272mapMaybe f [] = (_ ** [])
273mapMaybe f (x::xs) =
274 let (len ** ys) = mapMaybe f xs
275 in case f x of
276 Just y => (S len ** y :: ys)
277 Nothing => ( len ** ys)
280--------------------------------------------------------------------------------
281-- Folds
282--------------------------------------------------------------------------------
284total foldrImpl : (t -> acc -> acc) -> acc -> (acc -> acc) -> Vect n t -> acc
285foldrImpl f e go [] = go e
286foldrImpl f e go (x::xs) = foldrImpl f e (go . (f x)) xs
288instance Foldable (Vect n) where
289 foldr f e xs = foldrImpl f e id xs
291--------------------------------------------------------------------------------
292-- Special folds
293--------------------------------------------------------------------------------
295||| Flatten a vector of equal-length vectors
296concat : Vect m (Vect n a) -> Vect (m * n) a
297concat [] = []
298concat (v::vs) = v ++ concat vs
300||| Foldr without seeding the accumulator
301foldr1 : (t -> t -> t) -> Vect (S n) t -> t
302foldr1 f (x::xs) = foldr f x xs
304||| Foldl without seeding the accumulator
305foldl1 : (t -> t -> t) -> Vect (S n) t -> t
306foldl1 f (x::xs) = foldl f x xs
307--------------------------------------------------------------------------------
308-- Scans
309--------------------------------------------------------------------------------
311scanl : (b -> a -> b) -> b -> Vect n a -> Vect (S n) b
312scanl f q [] = [q]
313scanl f q (x::xs) = q :: scanl f (f q x) xs
315--------------------------------------------------------------------------------
316-- Membership tests
317--------------------------------------------------------------------------------
319||| Search for an item using a user-provided test
320||| @ p the equality test
321||| @ e the item to search for
322||| @ xs the vector to search in
323elemBy : (p : a -> a -> Bool) -> (e : a) -> (xs : Vect n a) -> Bool
324elemBy p e [] = False
325elemBy p e (x::xs) with (p e x)
326 | True = True
327 | False = elemBy p e xs
329||| Use the default Boolean equality on elements to search for an item
330||| @ x what to search for
331||| @ xs where to search
332elem : Eq a => (x : a) -> (xs : Vect n a) -> Bool
333elem = elemBy (==)
335||| Find the association of some key with a user-provided comparison
336||| @ p the comparison operator for keys (True if they match)
337||| @ e the key to look for
338lookupBy : (p : a -> a -> Bool) -> (e : a) -> (xs : Vect n (a, b)) -> Maybe b
339lookupBy p e [] = Nothing
340lookupBy p e ((l, r)::xs) with (p e l)
341 | True = Just r
342 | False = lookupBy p e xs
344||| Find the assocation of some key using the default Boolean equality test
345lookup : Eq a => a -> Vect n (a, b) -> Maybe b
346lookup = lookupBy (==)
348||| Check if any element of xs is found in elems by a user-provided comparison
349||| @ p the comparison operator
350||| @ elems the vector to search
351||| @ xs what to search for
352hasAnyBy : (p : a -> a -> Bool) -> (elems : Vect m a) -> (xs : Vect n a) -> Bool
353hasAnyBy p elems [] = False
354hasAnyBy p elems (x::xs) with (elemBy p x elems)
355 | True = True
356 | False = hasAnyBy p elems xs
358||| Check if any element of xs is found in elems using the default Boolean equality test
359hasAny : Eq a => Vect m a -> Vect n a -> Bool
360hasAny = hasAnyBy (==)
362--------------------------------------------------------------------------------
363-- Searching with a predicate
364--------------------------------------------------------------------------------
366||| Find the first element of the vector that satisfies some test
367||| @ p the test to satisfy
368find : (p : a -> Bool) -> (xs : Vect n a) -> Maybe a
369find p [] = Nothing
370find p (x::xs) with (p x)
371 | True = Just x
372 | False = find p xs
374||| Find the index of the first element of the vector that satisfies some test
375findIndex : (a -> Bool) -> Vect n a -> Maybe Nat
376findIndex = findIndex' 0
377 where
378 findIndex' : Nat -> (a -> Bool) -> Vect n a -> Maybe Nat
379 findIndex' cnt p [] = Nothing
380 findIndex' cnt p (x::xs) with (p x)
381 | True = Just cnt
382 | False = findIndex' (S cnt) p xs
384||| Find the indices of all elements that satisfy some test
385total findIndices : (a -> Bool) -> Vect m a -> (p ** Vect p Nat)
386findIndices = findIndices' 0
387 where
388 total findIndices' : Nat -> (a -> Bool) -> Vect m a -> (p ** Vect p Nat)
389 findIndices' cnt p [] = (_ ** [])
390 findIndices' cnt p (x::xs) with (findIndices' (S cnt) p xs)
391 | (_ ** tail) =
392 if p x then
393 (_ ** cnt::tail)
394 else
395 (_ ** tail)
397elemIndexBy : (a -> a -> Bool) -> a -> Vect m a -> Maybe Nat
398elemIndexBy p e = findIndex $ p e
400elemIndex : Eq a => a -> Vect m a -> Maybe Nat
401elemIndex = elemIndexBy (==)
403total elemIndicesBy : (a -> a -> Bool) -> a -> Vect m a -> (p ** Vect p Nat)
404elemIndicesBy p e = findIndices $ p e
406total elemIndices : Eq a => a -> Vect m a -> (p ** Vect p Nat)
407elemIndices = elemIndicesBy (==)
409--------------------------------------------------------------------------------
410-- Filters
411--------------------------------------------------------------------------------
413||| Find all elements of a vector that satisfy some test
414total filter : (a -> Bool) -> Vect n a -> (p ** Vect p a)
415filter p [] = ( _ ** [] )
416filter p (x::xs) with (filter p xs)
417 | (_ ** tail) =
418 if p x then
419 (_ ** x::tail)
420 else
421 (_ ** tail)
423||| Make the elements of some vector unique by some test
424nubBy : (a -> a -> Bool) -> Vect n a -> (p ** Vect p a)
425nubBy = nubBy' []
426 where
427 nubBy' : Vect m a -> (a -> a -> Bool) -> Vect n a -> (p ** Vect p a)
428 nubBy' acc p [] = (_ ** [])
429 nubBy' acc p (x::xs) with (elemBy p x acc)
430 | True = nubBy' acc p xs
431 | False with (nubBy' (x::acc) p xs)
432 | (_ ** tail) = (_ ** x::tail)
434||| Make the elements of some vector unique by the default Boolean equality
435nub : Eq a => Vect n a -> (p ** Vect p a)
436nub = nubBy (==)
438deleteBy : (a -> a -> Bool) -> a -> Vect n a -> (p ** Vect p a)
439deleteBy _ _ [] = (_ ** [])
440deleteBy eq x (y::ys) =
441 let (len ** zs) = deleteBy eq x ys
442 in if x `eq` y then (_ ** ys) else (S len ** y ::zs)
444delete : (Eq a) => a -> Vect n a -> (p ** Vect p a)
445delete = deleteBy (==)
447--------------------------------------------------------------------------------
448-- Splitting and breaking lists
449--------------------------------------------------------------------------------
451||| A tuple where the first element is a Vect of the n first elements and
452||| the second element is a Vect of the remaining elements of the original Vect
453||| It is equivalent to (take n xs, drop n xs)
454||| @ m the index to split at
455||| @ xs the Vect to split in two
456splitAt : (n : Nat) -> (xs : Vect (n + m) a) -> (Vect n a, Vect m a)
457splitAt n xs = (take n xs, drop n xs)
459partition : (a -> Bool) -> Vect n a -> ((p ** Vect p a), (q ** Vect q a))
460partition p [] = ((_ ** []), (_ ** []))
461partition p (x::xs) =
462 let ((leftLen ** lefts), (rightLen ** rights)) = partition p xs in
463 if p x then
464 ((S leftLen ** x::lefts), (rightLen ** rights))
465 else
466 ((leftLen ** lefts), (S rightLen ** x::rights))
468--------------------------------------------------------------------------------
469-- Predicates
470--------------------------------------------------------------------------------
472isPrefixOfBy : (a -> a -> Bool) -> Vect m a -> Vect n a -> Bool
473isPrefixOfBy p [] right = True
474isPrefixOfBy p left [] = False
475isPrefixOfBy p (x::xs) (y::ys) with (p x y)
476 | True = isPrefixOfBy p xs ys
477 | False = False
479isPrefixOf : Eq a => Vect m a -> Vect n a -> Bool
480isPrefixOf = isPrefixOfBy (==)
482isSuffixOfBy : (a -> a -> Bool) -> Vect m a -> Vect n a -> Bool
483isSuffixOfBy p left right = isPrefixOfBy p (reverse left) (reverse right)
485isSuffixOf : Eq a => Vect m a -> Vect n a -> Bool
486isSuffixOf = isSuffixOfBy (==)
488--------------------------------------------------------------------------------
489-- Conversions
490--------------------------------------------------------------------------------
492total maybeToVect : Maybe a -> (p ** Vect p a)
493maybeToVect Nothing = (_ ** [])
494maybeToVect (Just j) = (_ ** [j])
496total vectToMaybe : Vect n a -> Maybe a
497vectToMaybe [] = Nothing
498vectToMaybe (x::xs) = Just x
500--------------------------------------------------------------------------------
501-- Misc
502--------------------------------------------------------------------------------
504catMaybes : Vect n (Maybe a) -> (p ** Vect p a)
505catMaybes [] = (_ ** [])
506catMaybes (Nothing::xs) = catMaybes xs
507catMaybes ((Just j)::xs) with (catMaybes xs)
508 | (_ ** tail) = (_ ** j::tail)
510diag : Vect n (Vect n a) -> Vect n a
511diag [] = []
512diag ((x::xs)::xss) = x :: diag (map tail xss)
514range : Vect n (Fin n)
515range {n=Z} = []
516range {n=S _} = FZ :: map FS range
518||| Transpose a Vect of Vects, turning rows into columns and vice versa.
519|||
520||| As the types ensure rectangularity, this is an involution, unlike `Prelude.List.transpose`.
521transpose : Vect m (Vect n a) -> Vect n (Vect m a)
522transpose [] = replicate _ []
523transpose (x :: xs) = zipWith (::) x (transpose xs)
525--------------------------------------------------------------------------------
526-- Applicative/Monad/Traversable
527--------------------------------------------------------------------------------
529instance Applicative (Vect k) where
530 pure = replicate _
532 fs <*> vs = zipWith apply fs vs
534||| This monad is different from the List monad, (>>=)
535||| uses the diagonal.
536instance Monad (Vect n) where
537 m >>= f = diag (map f m)
539instance Traversable (Vect n) where
540 traverse f [] = pure Vect.Nil
541 traverse f (x::xs) = [| Vect.(::) (f x) (traverse f xs) |]
543--------------------------------------------------------------------------------
544-- Show
545--------------------------------------------------------------------------------
547instance Show a => Show (Vect n a) where
548 show = show . toList
550--------------------------------------------------------------------------------
551-- Properties
552--------------------------------------------------------------------------------
554vectConsCong : (x : a) -> (xs : Vect n a) -> (ys : Vect m a) -> (xs = ys) -> (x :: xs = x :: ys)
555vectConsCong x xs xs Refl = Refl
557vectNilRightNeutral : (xs : Vect n a) -> xs ++ [] = xs
558vectNilRightNeutral [] = Refl
559vectNilRightNeutral (x :: xs) =
560 vectConsCong _ _ _ (vectNilRightNeutral xs)
562vectAppendAssociative : (x : Vect xLen a) -> (y : Vect yLen a) -> (z : Vect zLen a) -> x ++ (y ++ z) = (x ++ y) ++ z
563vectAppendAssociative [] y z = Refl
564vectAppendAssociative (x :: xs) ys zs =
565 vectConsCong _ _ _ (vectAppendAssociative xs ys zs)
569--------------------------------------------------------------------------------
570-- DecEq
571--------------------------------------------------------------------------------
573total
574vectInjective1 : {xs, ys : Vect n a} -> {x, y : a} -> x :: xs = y :: ys -> x = y
575vectInjective1 {x=x} {y=x} {xs=xs} {ys=xs} Refl = Refl
577total
578vectInjective2 : {xs, ys : Vect n a} -> {x, y : a} -> x :: xs = y :: ys -> xs = ys
579vectInjective2 {x=x} {y=x} {xs=xs} {ys=xs} Refl = Refl
581instance DecEq a => DecEq (Vect n a) where
582 decEq [] [] = Yes Refl
583 decEq (x :: xs) (y :: ys) with (decEq x y)
584 decEq (x :: xs) (x :: ys) | Yes Refl with (decEq xs ys)
585 decEq (x :: xs) (x :: xs) | Yes Refl | Yes Refl = Yes Refl
586 decEq (x :: xs) (x :: ys) | Yes Refl | No neq = No (neq . vectInjective2)
587 decEq (x :: xs) (y :: ys) | No neq = No (neq . vectInjective1)
589{- The following definition is elaborated in a wrong case-tree. Examination pending.
590instance DecEq a => DecEq (Vect n a) where
591 decEq [] [] = Yes Refl
592 decEq (x :: xs) (y :: ys) with (decEq x y, decEq xs ys)
593 decEq (x :: xs) (x :: xs) | (Yes Refl, Yes Refl) = Yes Refl
594 decEq (x :: xs) (y :: ys) | (_, No nEqTl) = No (\p => nEqTl (vectInjective2 p))
595 decEq (x :: xs) (y :: ys) | (No nEqHd, _) = No (\p => nEqHd (vectInjective1 p))
596-}
598-- For the primitives, we have to cheat because we don't have access to their
599-- internal implementations.