0 | module Data.ArrayVect
  1 |
  2 | import Data.Array.Core as Core
  3 | import Data.Array.Indexed as Array
  4 | import Data.Nat
  5 | import Data.Vect as Vect
  6 |
  7 | %default total
  8 |
  9 | ||| A fixed-length vector.
 10 | |||
 11 | ||| The constructors are the source-level specification. The exported
 12 | ||| operations below are transformed during code generation so transformed
 13 | ||| producers and consumers use `IArray` as their runtime representation.
 14 | ||| Complexity notes on operations describe that transformed runtime path.
 15 | export
 16 | data ArrayVect : Nat -> Type -> Type where
 17 |   Nil  : ArrayVect 0 a
 18 |   (::) : a -> ArrayVect n a -> ArrayVect (S n) a
 19 |
 20 | %name ArrayVect xs, ys, zs
 21 |
 22 | %inline
 23 | unsafeFromArray : Core.IArray n a -> ArrayVect n a
 24 | unsafeFromArray = believe_me
 25 |
 26 | %inline
 27 | unsafeToArray : ArrayVect n a -> Core.IArray n a
 28 | unsafeToArray = believe_me
 29 |
 30 | ||| Runtime after transform: O(n). Allocates n array elements.
 31 | export
 32 | fromVect : {n : Nat} -> Vect n a -> ArrayVect n a
 33 | fromVect []        = []
 34 | fromVect (x :: xs) = x :: fromVect xs
 35 |
 36 | %inline
 37 | fromVectArray : {n : Nat} -> Vect n a -> ArrayVect n a
 38 | fromVectArray xs = unsafeFromArray (Array.array xs)
 39 |
 40 | %transform "arrayVectFromVect" Data.ArrayVect.fromVect = Data.ArrayVect.fromVectArray
 41 |
 42 | ||| Runtime after transform: O(n). Allocates an n-element `Vect`.
 43 | export
 44 | toVect : {n : Nat} -> ArrayVect n a -> Vect n a
 45 | toVect []        = []
 46 | toVect (x :: xs) = x :: toVect xs
 47 |
 48 | %inline
 49 | toVectArray : {n : Nat} -> ArrayVect n a -> Vect n a
 50 | toVectArray xs = Array.toVect (unsafeToArray xs)
 51 |
 52 | %transform "arrayVectToVect" Data.ArrayVect.toVect = Data.ArrayVect.toVectArray
 53 |
 54 | ||| Runtime after transform: O(n). Allocates n array elements.
 55 | export
 56 | fromList : (xs : List a) -> ArrayVect (length xs) a
 57 | fromList xs = fromVect (Vect.fromList xs)
 58 |
 59 | %inline
 60 | fromListArray : (xs : List a) -> ArrayVect (length xs) a
 61 | fromListArray xs = unsafeFromArray (Array.arrayL xs)
 62 |
 63 | %transform "arrayVectFromList" Data.ArrayVect.fromList = Data.ArrayVect.fromListArray
 64 |
 65 | ||| Runtime after transform: O(n). Allocates n list cons cells.
 66 | export
 67 | toList : {n : Nat} -> ArrayVect n a -> List a
 68 | toList []        = []
 69 | toList (x :: xs) = x :: toList xs
 70 |
 71 | %inline
 72 | toListArray : {n : Nat} -> ArrayVect n a -> List a
 73 | toListArray xs = Prelude.toList (unsafeToArray xs)
 74 |
 75 | %transform "arrayVectToList" Data.ArrayVect.toList = Data.ArrayVect.toListArray
 76 |
 77 | ||| Runtime after transform: O(1). Allocates an empty array.
 78 | export
 79 | empty : ArrayVect 0 a
 80 | empty = []
 81 |
 82 | %inline
 83 | emptyArray : ArrayVect 0 a
 84 | emptyArray = unsafeFromArray Array.empty
 85 |
 86 | %transform "arrayVectEmpty" Data.ArrayVect.empty = Data.ArrayVect.emptyArray
 87 |
 88 | ||| Runtime after transform: O(1). Allocates a one-element array.
 89 | export
 90 | singleton : a -> ArrayVect 1 a
 91 | singleton x = x :: []
 92 |
 93 | %inline
 94 | singletonArray : a -> ArrayVect 1 a
 95 | singletonArray x = unsafeFromArray (Array.fill 1 x)
 96 |
 97 | %transform "arrayVectSingleton" Data.ArrayVect.singleton = Data.ArrayVect.singletonArray
 98 |
 99 | ||| Runtime after transform: O(n). Allocates n array elements.
100 | export
101 | replicate : (n : Nat) -> a -> ArrayVect n a
102 | replicate 0     _ = []
103 | replicate (S k) x = x :: replicate k x
104 |
105 | %inline
106 | replicateArray : (n : Nat) -> a -> ArrayVect n a
107 | replicateArray n x = unsafeFromArray (Array.fill n x)
108 |
109 | %transform "arrayVectReplicate" Data.ArrayVect.replicate = Data.ArrayVect.replicateArray
110 |
111 | ||| Runtime after transform: O(n), plus callback cost. Allocates n array elements.
112 | export
113 | generate : (n : Nat) -> (Fin n -> a) -> ArrayVect n a
114 | generate n f = fromVect (Vect.Fin.tabulate f)
115 |
116 | %inline
117 | generateArray : (n : Nat) -> (Fin n -> a) -> ArrayVect n a
118 | generateArray n f = unsafeFromArray (Array.generate n f)
119 |
120 | %transform "arrayVectGenerate" Data.ArrayVect.generate = Data.ArrayVect.generateArray
121 |
122 | iterVect : (n : Nat) -> (a -> a) -> a -> Vect n a
123 | iterVect 0     _ x = []
124 | iterVect (S k) f x = x :: iterVect k f (f x)
125 |
126 | ||| Runtime after transform: O(n), plus callback cost. Allocates n array elements.
127 | export
128 | iterate : (n : Nat) -> (a -> a) -> a -> ArrayVect n a
129 | iterate n f x = fromVect (iterVect n f x)
130 |
131 | %inline
132 | iterateArray : (n : Nat) -> (a -> a) -> a -> ArrayVect n a
133 | iterateArray n f x = unsafeFromArray (Array.iterate n f x)
134 |
135 | %transform "arrayVectIterate" Data.ArrayVect.iterate = Data.ArrayVect.iterateArray
136 |
137 | ||| Runtime after transform: O(1). Allocates nothing.
138 | export
139 | length : {n : Nat} -> ArrayVect n a -> Nat
140 | length []        = 0
141 | length (_ :: xs) = S (length xs)
142 |
143 | %inline
144 | lengthArray : {n : Nat} -> ArrayVect n a -> Nat
145 | lengthArray {n} _ = n
146 |
147 | %transform "arrayVectLength" Data.ArrayVect.length = Data.ArrayVect.lengthArray
148 |
149 | ||| Runtime after transform: O(1). Allocates nothing.
150 | export
151 | null : {n : Nat} -> ArrayVect n a -> Bool
152 | null []       = True
153 | null (_ :: _) = False
154 |
155 | %inline
156 | nullArray : {n : Nat} -> ArrayVect n a -> Bool
157 | nullArray {n} _ = n == 0
158 |
159 | %transform "arrayVectNull" Data.ArrayVect.null = Data.ArrayVect.nullArray
160 |
161 | ||| Runtime after transform: O(1). Allocates nothing.
162 | export
163 | index : {n : Nat} -> Fin n -> ArrayVect n a -> a
164 | index FZ     (x :: _)  = x
165 | index (FS k) (_ :: xs) = index k xs
166 |
167 | %inline
168 | indexArray : {n : Nat} -> Fin n -> ArrayVect n a -> a
169 | indexArray i xs = Core.at (unsafeToArray xs) i
170 |
171 | %transform "arrayVectIndex" Data.ArrayVect.index = Data.ArrayVect.indexArray
172 |
173 | ||| Runtime after transform: O(1). Allocates nothing.
174 | export
175 | head : {n : Nat} -> ArrayVect (S n) a -> a
176 | head (x :: _) = x
177 |
178 | %inline
179 | headArray : {n : Nat} -> ArrayVect (S n) a -> a
180 | headArray xs = Core.at (unsafeToArray xs) FZ
181 |
182 | %transform "arrayVectHead" Data.ArrayVect.head = Data.ArrayVect.headArray
183 |
184 | ||| Runtime after transform: O(n) for a tail of length n.
185 | ||| Allocates n array elements.
186 | export
187 | tail : {n : Nat} -> ArrayVect (S n) a -> ArrayVect n a
188 | tail (_ :: xs) = xs
189 |
190 | %inline
191 | tailArray : {n : Nat} -> ArrayVect (S n) a -> ArrayVect n a
192 | tailArray {n} xs =
193 |   rewrite sym (minusZeroRight n) in unsafeFromArray (Array.drop 1 (unsafeToArray xs))
194 |
195 | %transform "arrayVectTail" Data.ArrayVect.tail = Data.ArrayVect.tailArray
196 |
197 | ||| Runtime after transform: O(n), plus callback cost. Allocates n array elements.
198 | export
199 | map : {n : Nat} -> (a -> b) -> ArrayVect n a -> ArrayVect n b
200 | map f []        = []
201 | map f (x :: xs) = f x :: map f xs
202 |
203 | %inline
204 | mapArray : {n : Nat} -> (a -> b) -> ArrayVect n a -> ArrayVect n b
205 | mapArray f xs = unsafeFromArray (Prelude.map f (unsafeToArray xs))
206 |
207 | %transform "arrayVectMap" Data.ArrayVect.map = Data.ArrayVect.mapArray
208 |
209 | ||| Runtime after transform: O(n), plus callback cost. Allocates n array elements.
210 | export
211 | mapWithIndex : {n : Nat} -> (Fin n -> a -> b) -> ArrayVect n a -> ArrayVect n b
212 | mapWithIndex f xs = generate n (\i => f i (index i xs))
213 |
214 | %inline
215 | mapWithIndexArray : {n : Nat} -> (Fin n -> a -> b) -> ArrayVect n a -> ArrayVect n b
216 | mapWithIndexArray f xs = unsafeFromArray (Array.mapWithIndex f (unsafeToArray xs))
217 |
218 | %transform "arrayVectMapWithIndex" Data.ArrayVect.mapWithIndex = Data.ArrayVect.mapWithIndexArray
219 |
220 | ||| Runtime after transform: O(n), plus callback cost.
221 | ||| Copies the whole array and allocates n array elements.
222 | export
223 | updateAt : {n : Nat} -> Fin n -> (a -> a) -> ArrayVect n a -> ArrayVect n a
224 | updateAt FZ     f (x :: xs) = f x :: xs
225 | updateAt (FS k) f (x :: xs) = x :: updateAt k f xs
226 |
227 | %inline
228 | updateAtArray : {n : Nat} -> Fin n -> (a -> a) -> ArrayVect n a -> ArrayVect n a
229 | updateAtArray i f xs = unsafeFromArray (Array.updateAt i f (unsafeToArray xs))
230 |
231 | %transform "arrayVectUpdateAt" Data.ArrayVect.updateAt = Data.ArrayVect.updateAtArray
232 |
233 | ||| Runtime after transform: O(n).
234 | ||| Copies the whole array and allocates n array elements.
235 | export
236 | replaceAt : {n : Nat} -> Fin n -> a -> ArrayVect n a -> ArrayVect n a
237 | replaceAt i x xs = updateAt i (const x) xs
238 |
239 | %inline
240 | replaceAtArray : {n : Nat} -> Fin n -> a -> ArrayVect n a -> ArrayVect n a
241 | replaceAtArray i x xs = unsafeFromArray (Array.setAt i x (unsafeToArray xs))
242 |
243 | %transform "arrayVectReplaceAt" Data.ArrayVect.replaceAt = Data.ArrayVect.replaceAtArray
244 |
245 | ||| Runtime after transform: O(m + n). Allocates m + n array elements.
246 | export
247 | (++) : {m, n : Nat} -> ArrayVect m a -> ArrayVect n a -> ArrayVect (m + n) a
248 | []        ++ ys = ys
249 | (x :: xs) ++ ys = x :: (xs ++ ys)
250 |
251 | %inline
252 | appendArray : {m, n : Nat} -> ArrayVect m a -> ArrayVect n a -> ArrayVect (m + n) a
253 | appendArray xs ys = unsafeFromArray (Array.append (unsafeToArray xs) (unsafeToArray ys))
254 |
255 | %transform "arrayVectAppend" Data.ArrayVect.(++) = Data.ArrayVect.appendArray
256 |
257 | ||| Runtime after transform: O(1). Allocates nothing and reuses the array prefix.
258 | export
259 | take : {n : Nat} -> (m : Nat) -> ArrayVect (m + n) a -> ArrayVect m a
260 | take 0     xs        = []
261 | take (S k) (x :: xs) = x :: take k xs
262 |
263 | %inline
264 | takeArray : {n : Nat} -> (m : Nat) -> ArrayVect (m + n) a -> ArrayVect m a
265 | takeArray m xs = unsafeFromArray (Core.take m (unsafeToArray xs) @{lteAddRight m})
266 |
267 | %transform "arrayVectTake" Data.ArrayVect.take = Data.ArrayVect.takeArray
268 |
269 | ||| Runtime after transform: O(n `minus` m). Allocates n `minus` m array elements.
270 | export
271 | drop : {n : Nat} -> (m : Nat) -> ArrayVect n a -> ArrayVect (n `minus` m) a
272 | drop 0       xs        = rewrite minusZeroRight n in xs
273 | drop (S _)   []        = []
274 | drop (S k)   (_ :: xs) = drop k xs
275 |
276 | %inline
277 | dropArray : {n : Nat} -> (m : Nat) -> ArrayVect n a -> ArrayVect (n `minus` m) a
278 | dropArray m xs = unsafeFromArray (Array.drop m (unsafeToArray xs))
279 |
280 | %transform "arrayVectDrop" Data.ArrayVect.drop = Data.ArrayVect.dropArray
281 |
282 | ||| Runtime after transform: O(n), plus callback cost. Allocates n array elements.
283 | export
284 | zipWith : {n : Nat} -> (a -> b -> c) -> ArrayVect n a -> ArrayVect n b -> ArrayVect n c
285 | zipWith f []        []        = []
286 | zipWith f (x :: xs) (y :: ys) = f x y :: zipWith f xs ys
287 |
288 | %inline
289 | zipWithArray : {n : Nat} -> (a -> b -> c) -> ArrayVect n a -> ArrayVect n b -> ArrayVect n c
290 | zipWithArray f xs ys =
291 |   unsafeFromArray (Array.generate n (\i => f (Core.at (unsafeToArray xs) i) (Core.at (unsafeToArray ys) i)))
292 |
293 | %transform "arrayVectZipWith" Data.ArrayVect.zipWith = Data.ArrayVect.zipWithArray
294 |
295 | ||| Runtime after transform: O(n), plus callback cost. Allocates nothing.
296 | export
297 | foldr : {n : Nat} -> (a -> acc -> acc) -> acc -> ArrayVect n a -> acc
298 | foldr f z []        = z
299 | foldr f z (x :: xs) = f x (foldr f z xs)
300 |
301 | %inline
302 | foldrArray : {n : Nat} -> (a -> acc -> acc) -> acc -> ArrayVect n a -> acc
303 | foldrArray f z xs = Prelude.foldr f z (unsafeToArray xs)
304 |
305 | %transform "arrayVectFoldr" Data.ArrayVect.foldr = Data.ArrayVect.foldrArray
306 |
307 | ||| Runtime after transform: O(n), plus callback cost. Allocates nothing.
308 | export
309 | foldl : {n : Nat} -> (acc -> a -> acc) -> acc -> ArrayVect n a -> acc
310 | foldl f z []        = z
311 | foldl f z (x :: xs) = foldl f (f z x) xs
312 |
313 | %inline
314 | foldlArray : {n : Nat} -> (acc -> a -> acc) -> acc -> ArrayVect n a -> acc
315 | foldlArray f z xs = Prelude.foldl f z (unsafeToArray xs)
316 |
317 | %transform "arrayVectFoldl" Data.ArrayVect.foldl = Data.ArrayVect.foldlArray
318 |
319 | ||| Runtime after transform: O(n), plus predicate cost.
320 | ||| Allocates an n-slot result buffer; the returned vector length is the number retained.
321 | export
322 | filter : {n : Nat} -> (a -> Bool) -> ArrayVect n a -> (m ** ArrayVect m a)
323 | filter p [] = (_ ** [])
324 | filter p (x :: xs) =
325 |   let (m ** ys= filter p xs in
326 |     if p x then (S m ** x :: yselse (m ** ys)
327 |
328 | %inline
329 | filterArray : {n : Nat} -> (a -> Bool) -> ArrayVect n a -> (m ** ArrayVect m a)
330 | filterArray p xs =
331 |   case Array.filter p (unsafeToArray xs) of
332 |     A m ys => (m ** unsafeFromArray ys)
333 |
334 | %transform "arrayVectFilter" Data.ArrayVect.filter = Data.ArrayVect.filterArray
335 |
336 | ||| Runtime after transform: O(n), plus callback cost.
337 | ||| Allocates an n-slot result buffer; the returned vector length is the number produced.
338 | export
339 | mapMaybe : {n : Nat} -> (a -> Maybe b) -> ArrayVect n a -> (m ** ArrayVect m b)
340 | mapMaybe f [] = (_ ** [])
341 | mapMaybe f (x :: xs) =
342 |   let (m ** ys= mapMaybe f xs in
343 |     case f x of
344 |       Just y  => (S m ** y :: ys)
345 |       Nothing => (m ** ys)
346 |
347 | %inline
348 | mapMaybeArray : {n : Nat} -> (a -> Maybe b) -> ArrayVect n a -> (m ** ArrayVect m b)
349 | mapMaybeArray f xs =
350 |   case Array.mapMaybe f (unsafeToArray xs) of
351 |     A m ys => (m ** unsafeFromArray ys)
352 |
353 | %transform "arrayVectMapMaybe" Data.ArrayVect.mapMaybe = Data.ArrayVect.mapMaybeArray
354 |
355 | ||| Runtime after transform: O(n) worst case. Allocates nothing.
356 | export
357 | equals : {n : Nat} -> Eq a => ArrayVect n a -> ArrayVect n a -> Bool
358 | equals []        []        = True
359 | equals (x :: xs) (y :: ys) = x == y && equals xs ys
360 |
361 | %inline
362 | equalsArray : {n : Nat} -> Eq a => ArrayVect n a -> ArrayVect n a -> Bool
363 | equalsArray xs ys = unsafeToArray xs == unsafeToArray ys
364 |
365 | %transform "arrayVectEquals" Data.ArrayVect.equals = Data.ArrayVect.equalsArray
366 |
367 | ||| Runtime after transform: O(n) worst case. Allocates nothing.
368 | export
369 | compare : {n : Nat} -> Ord a => ArrayVect n a -> ArrayVect n a -> Ordering
370 | compare []        []        = EQ
371 | compare (x :: xs) (y :: ys) =
372 |   case Prelude.compare x y of
373 |     EQ => compare xs ys
374 |     r  => r
375 |
376 | %inline
377 | compareArray : {n : Nat} -> Ord a => ArrayVect n a -> ArrayVect n a -> Ordering
378 | compareArray xs ys = Prelude.compare (unsafeToArray xs) (unsafeToArray ys)
379 |
380 | %transform "arrayVectCompare" Data.ArrayVect.compare = Data.ArrayVect.compareArray
381 |
382 | ||| Runtime after transform: O(n), plus element rendering.
383 | ||| Allocates an intermediate n-element `Vect`.
384 | showPrecAV : {n : Nat} -> Show a => Prec -> ArrayVect n a -> String
385 | showPrecAV p xs = showPrec p (toVect xs)
386 |
387 | %inline
388 | showPrecAVArray : {n : Nat} -> Show a => Prec -> ArrayVect n a -> String
389 | showPrecAVArray p xs = showPrec p (Array.toVect (unsafeToArray xs))
390 |
391 | %transform "arrayVectShowPrec" Data.ArrayVect.showPrecAV = Data.ArrayVect.showPrecAVArray
392 |
393 | ||| Runtime after transform: `(==)` is O(n) worst case and allocates nothing.
394 | public export
395 | {n : Nat} -> Eq a => Eq (ArrayVect n a) where
396 |   (==) = equals
397 |
398 | ||| Runtime after transform: `compare` is O(n) worst case and allocates nothing.
399 | public export
400 | {n : Nat} -> Ord a => Ord (ArrayVect n a) where
401 |   compare = Data.ArrayVect.compare
402 |
403 | ||| Runtime after transform: `showPrec` and `show` are O(n), plus element rendering.
404 | ||| They allocate an intermediate n-element `Vect`.
405 | public export
406 | {n : Nat} -> Show a => Show (ArrayVect n a) where
407 |   showPrec = showPrecAV
408 |
409 | ||| Runtime after transform: `map` is O(n), plus callback cost.
410 | ||| It allocates n array elements.
411 | public export
412 | {n : Nat} -> Functor (ArrayVect n) where
413 |   map = Data.ArrayVect.map
414 |
415 | ||| Runtime after transform: `foldr`, `foldl`, and `toList` are O(n);
416 | ||| `null` is O(1). Folds allocate nothing, while `toList` allocates n cons cells.
417 | public export
418 | {n : Nat} -> Foldable (ArrayVect n) where
419 |   foldr = Data.ArrayVect.foldr
420 |   foldl = Data.ArrayVect.foldl
421 |   toList = Data.ArrayVect.toList
422 |   null = Data.ArrayVect.null
423 |
424 | ||| Runtime after transform: `pure` is O(n), and `(<*>)` is O(n), plus function
425 | ||| application cost. Both allocate n array elements.
426 | public export
427 | {n : Nat} -> Applicative (ArrayVect n) where
428 |   pure = replicate n
429 |   fs <*> xs = zipWith apply fs xs
430 |