0 | module Misc
  1 |
  2 | import Data.Nat
  3 | import Data.List.Elem
  4 | import Data.Vect
  5 | import Data.Vect.Elem
  6 | import System.Random
  7 | import Data.Fin
  8 | import Data.List1
  9 | import Data.List.Quantifiers
 10 | import Data.Vect.Quantifiers
 11 | import Decidable.Equality
 12 | import Decidable.Equality.Core
 13 | import Data.List
 14 |
 15 | %hide Builtin.infixr.(#)
 16 | %hide Data.Vect.Quantifiers.All.index
 17 |
 18 | {-------------------------------------------------------------------------------
 19 | {-------------------------------------------------------------------------------
 20 | Various utilities necessary for TensorType, but that don't fit anywhere else
 21 | Does not depend on any other file within this project.
 22 |
 23 | Some of these feel like they should be in the Idris standard library
 24 |
 25 | -------------------------------------------------------------------------------}
 26 | -------------------------------------------------------------------------------}
 27 |
 28 | public export
 29 | constUnit : a -> Unit
 30 | constUnit _ = ()
 31 |
 32 | public export
 33 | const2Unit : a -> b -> Unit
 34 | const2Unit _ _ = ()
 35 |
 36 | public export
 37 | fromBool : Num a => Bool -> a
 38 | fromBool False = fromInteger 0
 39 | fromBool True = fromInteger 1
 40 |
 41 | public export
 42 | applyWhen : Bool -> (a -> a) -> a -> a
 43 | applyWhen False f a = a
 44 | applyWhen True f a = f a
 45 |
 46 | public export
 47 | updateAt : Eq a => (a -> b) -> (a, b) -> (a -> b)
 48 | updateAt f (i, val) i' = if i == i' then val else f i'
 49 |
 50 | ||| Graph of a dependent function
 51 | public export
 52 | graph : {t : a -> Type} ->
 53 |   (g : (x : a) -> t x) ->
 54 |   a -> (x : a ** t x)
 55 | graph g x = (x ** g x)
 56 |
 57 | ||| Version of `map` for dependent function
 58 | ||| Note that here `x : a` is identity in some sense, it comes from `f a`
 59 | public export
 60 | dependentMap : Functor f => {t : a -> Type} ->
 61 |   (g : (x : a) -> t x) ->
 62 |   f a -> f (x : a ** t x)
 63 | dependentMap g fa = map (graph g) fa
 64 |
 65 |
 66 | namespace IsNo
 67 |   ||| The proof that a decidable property leads to a contradiction
 68 |   ||| `IsNo` is a type Idris can automatically synthesise, unlike `Not`
 69 |   ||| See example below
 70 |   public export
 71 |   data IsNo : Dec a -> Type where
 72 |     ItIsNo : {prop : Type} -> 
 73 |       {contra : Not prop} ->
 74 |       IsNo (No {prop=prop} contra)
 75 |
 76 |   failing 
 77 |     thisOneFails : Not ("i" = "j")
 78 |     thisOneFails = %search
 79 |   
 80 |   thisOneDoesnt : IsNo (decEq "i" "j")
 81 |   thisOneDoesnt = %search
 82 |
 83 |   public export
 84 |   [UninhabitedIsNoRefl] {x : a} -> DecEq a =>
 85 |     Uninhabited (IsNo (decEq x x)) where
 86 |     uninhabited y with (decEq x x)
 87 |       _ | (Yes _) with (y)
 88 |         _ | ItIsNo impossible
 89 |       _ | (No contra) = contra Refl
 90 |   
 91 |   public export 
 92 |   isNoSym : DecEq a => {x, y : a} -> IsNo (decEq x y) -> IsNo (decEq y x)
 93 |   isNoSym z with (decEq x y) | (decEq y x)
 94 |     _ | (No contra1) | (Yes prf) = absurd (contra1 (sym prf))
 95 |     _ | _           | (No contra) = ItIsNo 
 96 |   
 97 |   ||| Proof of inequality yields IsNo
 98 |   public export
 99 |   proofIneqIsNo : {x, y : a} -> DecEq a =>
100 |     Not (x = y) -> IsNo (decEq x y)
101 |   proofIneqIsNo f with (decEq x y)
102 |     _ | (Yes prf) = absurd (f prf)
103 |     _ | (No contra) = ItIsNo
104 |
105 | namespace Maybe
106 |   public export
107 |   data IsNothing : Maybe a -> Type where
108 |     ItIsNothing : IsNothing Nothing
109 |
110 |   public export
111 |   maybeVoidIsNothing : (x : Maybe Void) -> IsNothing x
112 |   maybeVoidIsNothing Nothing = ItIsNothing
113 |   maybeVoidIsNothing (Just v) = absurd v
114 |
115 |   public export
116 |   Uninhabited (IsNothing (Just x)) where
117 |     uninhabited ItIsNothing impossible
118 |
119 |
120 | namespace NotElem
121 |   public export
122 |   data NotElem : DecEq a => (x : a) -> (xs : Vect n a) -> Type where
123 |     NotInEmptyVect : DecEq a => {0 x : a} -> NotElem x []
124 |     NotInNonEmptyVect : DecEq a => {0 x, y : a} ->
125 |       (xs : Vect n a) ->
126 |       IsNo (decEq x y) ->
127 |       (ne : NotElem x xs) =>
128 |       NotElem x (y :: xs)
129 |   
130 |   public export
131 |   notEqualNotElem : DecEq a =>
132 |     {0 x, y : a} ->
133 |     (neq : IsNo (decEq x y)) ->
134 |     NotElem x [y]
135 |   notEqualNotElem neq = NotInNonEmptyVect [] neq
136 |   
137 |   ||| If an element `i` is not in the singleton list `[j]`, then `j` is not in
138 |   ||| the singleton list `[i]`
139 |   public export
140 |   notElemSym : DecEq a => {i, j : a} -> NotElem i [j] -> NotElem j [i]
141 |   notElemSym (NotInNonEmptyVect [] isNo) = notEqualNotElem (isNoSym isNo)
142 |   
143 |   ||| If an element `i` is in the singleton list `[j]`, then `j` is in the 
144 |   ||| singleton list `[i]`
145 |   public export
146 |   elemSym : DecEq a => {i, j : a} -> Vect.Elem.Elem i [j] ->
147 |     Vect.Elem.Elem j [i]
148 |   elemSym Here = Here
149 |
150 |
151 | namespace Applicative
152 |   ||| Definition of liftA2 in terms of (<*>)
153 |   public export
154 |   liftA2 : Applicative f => f a -> f b -> f (a, b)
155 |   liftA2 fa fb = ((,) <$> fa) <*> fb
156 |   
157 |   ||| Tensorial strength
158 |   public export
159 |   strength : Applicative f => a -> f b -> f (a, b)
160 |   strength a fb = liftA2 (pure a) fb
161 |   
162 |   ||| Pointwise Num structure for Applicative functors
163 |   public export
164 |   [applicativeNum] Num a => Applicative f => Num (f a) where
165 |     xs + ys = uncurry (+) <$> liftA2 xs ys
166 |     xs * ys = uncurry (*) <$> liftA2 xs ys
167 |     fromInteger = pure . fromInteger
168 |
169 |
170 | namespace VectFoldable
171 |   ||| Implementation of Foldable for Vect that is denotationally equivalent to
172 |   ||| one in Data.Vect, but which does not use `foldrImpl` and therefore
173 |   ||| reduces in the typechecker
174 |   public export
175 |   [straightforward] Foldable (Vect n) where
176 |     foldr f z [] = z
177 |     foldr f z (x :: xs) = f x (foldr f z xs)
178 |
179 |   ||| toList with a different foldable implementation
180 |   public export
181 |   toList' : Vect n a -> List a
182 |   toList' = foldr @{straightforward} (::) []
183 |
184 |   public export
185 |   fromList' : (xs : List a) -> Vect (length xs) a
186 |   fromList' [] = []
187 |   fromList' (x :: xs) = x :: fromList' xs
188 |
189 | ||| Duplicate of utilities for Data.Vect in their Naperian form
190 | namespace Vect
191 |   public export
192 |   sum : Num a => Vect n a -> a
193 |   sum xs = foldr @{straightforward} (+) (fromInteger 0) xs
194 |   
195 |   -- Because of the way foldr for Vect is implemented in Idris 
196 |   -- we have to use this approach below, otherwise allSuccThenProdSucc breaks
197 |   public export 
198 |   prod : Num a => Vect n a -> a
199 |   prod xs = foldr @{straightforward} (*) (fromInteger 1) xs
200 |   -- prod [] = fromInteger 1
201 |   -- prod (x :: xs) = x * prod xs
202 |
203 |   public export
204 |   max : Ord a => Vect n a -> Maybe a
205 |   max [] = Nothing
206 |   max (x :: xs) = case max xs of
207 |     Nothing => Just x
208 |     Just y => Just (max x y)
209 |
210 |   public export
211 |   argmax : Ord a => IsSucc n => Vect n a -> Fin n 
212 |   argmax [x] = FZ
213 |   argmax (x :: x' :: xs) =
214 |     let maxRest = argmax (x' :: xs)
215 |     in case x > index maxRest (x' :: xs) of 
216 |       True => FZ
217 |       False => FS maxRest
218 |   
219 |   public export
220 |   argmin : Ord a => IsSucc n => Vect n a -> Fin n
221 |   argmin = argmax @{Reverse} 
222 |   
223 |   ||| Dual to concat from Data.Vect
224 |   public export
225 |   unConcat : {n, m : Nat} -> Vect (n * m) a -> Vect n (Vect m a)
226 |   unConcat {n = 0} _ = []
227 |   unConcat {n = (S k)} xs = let (f, s) = splitAt m xs
228 |                             in f :: unConcat s
229 |
230 |   ||| Trim a specified trailing value
231 |   public export
232 |   dropFromEnd : Eq a => a -> Vect n a -> List a
233 |   dropFromEnd c row = reverse (dropWhile (== c) (reverse (toList row)))
234 |   
235 |   ||| Combination of `cons` and `snoc`: adds an element in front, and at the end
236 |   public export
237 |   consSnoc : Vect n a -> a -> a -> Vect (2 + n) a
238 |   consSnoc xs a b = a :: snoc xs b
239 |   
240 |   ||| Pad a vector with a specified element to exactly `targetSize`
241 |   public export
242 |   padToSize : Vect size a -> (targetSize : Nat) -> a ->
243 |     LTE size targetSize => 
244 |     Vect targetSize a
245 |   padToSize [] Z c = []
246 |   padToSize [] (S k) c = c :: padToSize [] k c
247 |   padToSize (x :: xs) (S k) c = x :: padToSize xs k c @{fromLteSucc %search}
248 |
249 |   ||| Drop the first i elements of a vector
250 |   ||| Analogous to Data.Vect.drop, except the index is Fin n instead of Nat
251 |   public export
252 |   drop : (i : Fin (S n)) -> Vect n a -> Vect (minus n (finToNat i)) a
253 |   drop FZ xs = rewrite minusZeroRight n in xs
254 |   drop (FS i) (x :: xs) = drop i xs
255 |   
256 |   namespace DropElem
257 |     ||| Drop all the elements up and until the element `x` from a vector
258 |     public export
259 |     drop : DecEq a =>
260 |       (xs : Vect n a) ->
261 |       (elem : Elem x xs) ->
262 |       Vect (n `minus` (finToNat (FS (elemToFin elem)))) a
263 |     drop {n=S k} (_ :: xs) Here = rewrite minusZeroRight k in xs
264 |     drop (_ :: xs) (There later) = drop xs later
265 |
266 |
267 | namespace List
268 |   public export
269 |   sum : Num a => List a -> a
270 |   sum = foldr (+) (fromInteger 0) 
271 |
272 |   public export
273 |   prod : Num a => List a -> a
274 |   prod = foldr (*) (fromInteger 1)
275 |
276 |   public export
277 |   listZip : List a -> List b -> List (a, b)
278 |   listZip (x :: xs) (y :: ys) = (x, y) :: listZip xs ys
279 |   listZip _ _ = []
280 |
281 |   ||| Map each element along with its zero-based position in the list.
282 |   public export
283 |   mapWithIndex : (Nat -> a -> b) -> List a -> List b
284 |   mapWithIndex f = go 0
285 |     where
286 |       go : Nat -> List a -> List b
287 |       go _ []        = []
288 |       go i (x :: xs) = f i x :: go (S i) xs
289 |
290 |   ||| Split a list into consecutive chunks of size `n` (clamped to at least 1).
291 |   ||| The final chunk may be shorter than `n`, this is why the length of the
292 |   ||| list is needed as upper bound.
293 |   public export
294 |   chunksOf : (n : Nat) -> List a -> List (List a)
295 |   chunksOf n xs = go (max 1 n) xs (length xs)
296 |     where
297 |       go : Nat -> List a -> (len : Nat) -> List (List a)
298 |       go _  []          _     = []
299 |       go _  ys@(_ :: _) Z     = [ys]
300 |       go sz ys@(_ :: _) (S f) = case splitAt sz ys of
301 |                                   (h, t) => h :: go sz t f
302 |   
303 |   public export
304 |   max : Ord a => List a -> Maybe a
305 |   max [] = Nothing
306 |   max (x :: xs) = case max xs of
307 |     Nothing => Just x
308 |     Just y => Just (max x y)
309 |
310 |   namespace NonEmpty
311 |     public export
312 |     max : Ord a => (xs : List a) -> (ne : NonEmpty xs) => a
313 |     max [x] {ne=IsNonEmpty} = x
314 |     max (x :: y :: xs) {ne=IsNonEmpty} = max x (max (y :: xs))
315 |
316 |   ||| Trim a specified trailing value
317 |   public export
318 |   dropFromEnd : Eq a => a -> List a -> List a
319 |   dropFromEnd c row = reverse (dropWhile (== c) (reverse row))
320 |
321 |   ||| Combination of `cons` and `snoc`: adds an element in front, and at the end
322 |   public export
323 |   consSnoc : List a -> a -> a -> List a
324 |   consSnoc xs x y = x :: snoc xs y
325 |
326 |   ||| Pad a list with a specified element to at least `targetSize`
327 |   public export
328 |   padToSize : Nat -> a -> List a -> List a
329 |   padToSize targetSize padValue xs =
330 |     xs ++ replicate (minus targetSize (length xs)) padValue
331 |
332 |   ||| Drop all the elements after the element `x` from a list
333 |   public export
334 |   dropAfterElem : (xs : List a) -> (elem : Elem x xs) -> List a
335 |   dropAfterElem (x :: _) Here = [x]
336 |   dropAfterElem (y :: xs) (There p) = y :: dropAfterElem xs p
337 |
338 | namespace VectNaperianUtils
339 |   ||| Analogue of `(::)`
340 |   public export
341 |   cons : x -> (Fin l -> x) -> (Fin (S l) -> x)
342 |   cons x _ FZ = x
343 |   cons _ f (FS k') = f k'
344 |
345 |   -- dcons : x -> ((i : Fin k) -> i' i) -> ((i : Fin (S k)) -> i' (cons x i'))
346 |   
347 |   public export
348 |   head : (Fin (S l) -> x) -> x
349 |   head f = f FZ
350 |   
351 |   public export
352 |   tail : (Fin (S l) -> x) -> (Fin l -> x)
353 |   tail f = f . FS
354 |   
355 |   ||| All but the last element
356 |   public export
357 |   init : (Fin (S n) -> a) -> Fin n -> a
358 |   init f x = f (weaken x)
359 |   
360 |   ||| Analogus to `Data.Vect.take`
361 |   public export 
362 |   takeFin : (s : Fin (S n)) -> Vect n a -> Vect (finToNat s) a
363 |   takeFin FZ _ = []
364 |   takeFin (FS s) (x :: xs) = x :: takeFin s xs
365 |
366 |   public export
367 |   sum : Num a => {n : Nat} -> (Fin n -> a) -> a
368 |   sum {n = 0} _ = 0
369 |   sum {n = (S k)} content = content FZ + sum (content . FS)
370 |
371 |   public export
372 |   prod : Num a => {n : Nat} -> (Fin n -> a) -> a
373 |   prod = prod . tabulate
374 |
375 |   public export
376 |   toList : {n : Nat} -> (Fin n -> a) -> List a
377 |   toList = toList' . tabulate
378 |
379 | namespace FinArithmetic
380 |   ||| Proof that subtracting from a successor is the same as taking the sucessor
381 |   ||| of the subtraction
382 |   public export
383 |   minusSuccLTE : {n, m : Nat} -> LTE n m ->
384 |     minus (S m) n = S (minus m n)
385 |   minusSuccLTE {m = 0, n = 0} LTEZero = Refl
386 |   minusSuccLTE {m = (S k), n = 0} LTEZero = Refl
387 |   minusSuccLTE {m = (S k), n = (S left)} (LTESucc x) = minusSuccLTE x
388 |
389 |   ||| A version of `weakenN` from Data.Fin with `n` on the other side of `+`
390 |   public export
391 |   weakenN' : (0 n : Nat) -> Fin m -> Fin (n + m)
392 |   weakenN' n x = rewrite plusCommutative n m in weakenN n x
393 |
394 |   ||| Variant of `weakenN` from `Data.Fin`, but for multiplication
395 |   ||| Like shiftMul, but without changing the value of the index
396 |   public export
397 |   weakenMultN : {n : Nat} ->
398 |     (m : Nat) -> {auto prf : IsSucc m} ->
399 |     (i : Fin n) -> Fin (m * n)
400 |   weakenMultN (S 0) {prf = ItIsSucc} i = rewrite multOneLeftNeutral n in i
401 |   weakenMultN (S (S k)) {prf = ItIsSucc} i = weakenN' n (weakenMultN (S k) i)
402 |
403 |   multRightUnit : (m : Nat) -> m * 1 = m
404 |   multRightUnit 0 = Refl
405 |   multRightUnit (S k) = cong S (multRightUnit k)
406 |
407 |   multRightZeroCancel : (m : Nat) -> m * 0 = 0
408 |   multRightZeroCancel 0 = Refl
409 |   multRightZeroCancel (S k) = multRightZeroCancel k
410 |
411 |   ||| Variant of `shift` from Data.Fin, but for multiplication
412 |   ||| Given a stride and an index `i : Fin n`, it returns a stride-sized step
413 |   ||| That is, it returns `stride * i` : Fin (stride * n)
414 |   ||| Implemented by recursing on i, adding stride each time
415 |   public export
416 |   shiftMul : (stride : Nat) -> (prf : IsSucc stride) =>
417 |     (i : Fin n) -> Fin (n * stride)
418 |   shiftMul (S s) {prf = ItIsSucc} FZ = FZ
419 |   shiftMul stride (FS i) = shift stride (shiftMul stride i)
420 |
421 |   shiftMulTest : shiftMul {n=3} 5 1 = 5
422 |   shiftMulTest = Refl
423 |
424 |   ||| Analogue of `strengthen` from Data.Fin
425 |   ||| Attempts to strengthen the bound on Fin (m + n) to Fin m
426 |   ||| If it doesn't succeed, then returns the remainder in Fin n
427 |   public export
428 |   strengthenN : {m, n : Nat} -> Fin (m + n) -> Either (Fin m) (Fin n)
429 |   strengthenN {m = 0} x = Right x
430 |   strengthenN {m = (S k)} FZ = Left FZ
431 |   strengthenN {m = (S k)} (FS x) with (strengthenN x)
432 |     _ | (Left p) = Left $ FS p
433 |     _ | (Right q) = Right q
434 |
435 |   ||| Analogue of `finS` from `Data.Fin`, but without without wrapping
436 |   ||| That is, `finS' last = last`
437 |   public export
438 |   finS' : {n : Nat} -> Fin n -> Fin n
439 |   finS' {n = 1} x = x
440 |   finS' {n = S (S k)} FZ = FS FZ
441 |   finS' {n = S (S k)} (FS x) = FS (finS' x)
442 |   --finS' {n = S _} x = case strengthen x of
443 |   --    Nothing => x
444 |   --    Just y => FS y
445 |
446 |   finS'test1 : finS' {n=10} 4 = 5
447 |   finS'test1 = Refl
448 |
449 |   finS'lastIsLast : {n : Nat} -> finS' {n=S n} Fin.last = Fin.last
450 |   finS'lastIsLast {n = 0} = Refl
451 |   finS'lastIsLast {n = (S k)} = cong FS finS'lastIsLast
452 |
453 |   ||| This can be implemented using `Data.Fin.Order`, but it doesn't seem worth
454 |   ||| the effort, as the typechecker ends up needing a lot of extra hand holding
455 |   public export
456 |   lastBiggerThanOthers : {n : Nat} ->
457 |     (i : Fin (S n)) ->
458 |     So (Fin.last >= i)
459 |   lastBiggerThanOthers {n = 0} FZ = Oh
460 |   lastBiggerThanOthers {n = (S k)} FZ = Oh
461 |   lastBiggerThanOthers {n = (S k)} (FS x) = lastBiggerThanOthers x
462 |   
463 |   -- lastBiggerThanOthers {n = 0} FZ = FromNatPrf LTEZero
464 |   -- lastBiggerThanOthers {n = (S k)} FZ = FromNatPrf LTEZero
465 |   -- lastBiggerThanOthers {n = (S k)} (FS x) = FSFinLTE (lastBiggerThanOthers x)
466 |
467 |   ||| Adds two bounded numbers, bounds the result
468 |   ||| That is, `addFinsBounded {n=5} 3 4 = 4`
469 |   ||| `assert_smaller` is only needed for totality checking
470 |   public export
471 |   addFinsBounded : {n : Nat} -> Fin n -> Fin n -> Fin n
472 |   addFinsBounded x FZ = x
473 |   addFinsBounded x (FS y) = addFinsBounded (finS' x)
474 |     (assert_smaller (FS y) (weaken y))
475 |
476 |   finSTest : finS' {n = 5} 3 = 4
477 |   finSTest = Refl
478 |
479 |   finSTest2 : finS' {n = 5} 4 = 4
480 |   finSTest2 = Refl
481 |
482 |   ||| Divides a Fin by 2, rounding down
483 |   ||| `half {n=10} 6 = 3`
484 |   ||| `half {n=10} 5 = 2`
485 |   ||| `half {n=10} 4 = 2`
486 |   ||| `half {n=10} 3 = 1`
487 |   ||| `half {n=10} 2 = 1`
488 |   ||| `half {n=10} 1 = 0`
489 |   public export
490 |   half : Fin n -> Fin n
491 |   half FZ = FZ
492 |   half (FS FZ) = FZ
493 |   half (FS (FS x)) = weaken (FS (half x))
494 |
495 |   ||| Computes the midway index between two bounds
496 |   public export
497 |   mid : (low, high : Fin n) ->
498 |     So (high >= low) =>
499 |     Fin n
500 |   mid FZ high = half high
501 |   mid (FS x) (FS y) @{prf} = FS (mid x y)
502 |
503 |   -- ||| There is a similar function in Data.Fin.Arith, which has the smallest
504 |   -- ||| possible bound. This one does not, but has a simpler type signature.
505 |   -- public export
506 |   -- multFin : {m, n : Nat} -> Fin m -> Fin n -> Fin (m * n)
507 |   -- multFin {n = (S _)} FZ y = FZ
508 |   -- multFin {n = (S _)} (FS x) y = FinArith.(+) y (weaken (multFin x y))
509 |
510 | public export
511 | multSucc : {m, n : Nat} -> IsSucc m -> IsSucc n -> IsSucc (m * n)
512 | multSucc {m = S m'} {n = S n'} ItIsSucc ItIsSucc = ItIsSucc
513 |
514 | public export
515 | allSuccThenProdSucc : (xs : List Nat) ->
516 |   (ps : All IsSucc xs) =>
517 |   IsSucc (prod xs)
518 | allSuccThenProdSucc [] {ps = []} = ItIsSucc
519 | allSuccThenProdSucc (_ :: xs') {ps = p :: _} = multSucc p (allSuccThenProdSucc xs')
520 |
521 | ||| Data structure storing a lower and upper bound during a search
522 | record Range (n : Nat) where
523 |   constructor MkRange
524 |   lowerBound : Fin n
525 |   higherBound : Fin n
526 |   {auto prf : So (higherBound >= lowerBound)}
527 |
528 | ||| Given a non-empty sorted vector `xs`, an element `x` and a lower and upper
529 | ||| bound, it finds the "right bin", i.e. the index of the smallest element 
530 | ||| between the bounds that's bigger than `x`
531 | ||| If `x` is bigger than the largest element, returns `Nothing`
532 | ||| `findBinBetween [2,7,10] 1 (MkRange 0 2) = Just 0`
533 | ||| `findBinBetween [2,7,10] 3 (MkRange 0 2) = Just 1`
534 | ||| `findBinBetween [2,7,10] 9 (MkRange 0 2) = Just 2`
535 | ||| `findBinBetween [2,7,10] 7 (MkRange 0 2) = Just 2`
536 | ||| `findbinbetween [2,7,15] 7 (MkRange 0 2) = Nothing`
537 | ||| `findBinBetween [1,2,3,4,5] 6 (MkRange 0 4) = Nothing`
538 | ||| Done using binary search
539 | public export
540 | findBinBetween : Ord a => {n : Nat} -> (is : IsSucc n) =>
541 |   (xs : Vect n a) -> -- we assume this is sorted
542 |   (x : a) ->
543 |   (range : Range n) ->
544 |   Maybe (Fin n)
545 | findBinBetween {is = ItIsSucc {n=k}} xs x r@(MkRange lowInd highInd)
546 |   = case x > index highInd xs of
547 |   True => Nothing -- There are no elements bigger than `x`
548 |   False => case x <= index lowInd xs of
549 |     True => Just lowInd
550 |     False => let midInd = mid lowInd highInd
551 |              in case compare x (index midInd xs) of
552 |                LT => let newRange = MkRange lowInd midInd {prf = believe_me ()}
553 |                      in findBinBetween xs x (assert_smaller r newRange)
554 |                EQ => Just (finS' midInd) -- we need the next index after the middle one
555 |                GT => let newRange = MkRange (finS' midInd) highInd {prf = believe_me ()}
556 |                      in findBinBetween xs x (assert_smaller r newRange)
557 |
558 | namespace FindBinTests
559 |   findBinTest1 : findBinBetween [2,7,10] 1 (MkRange 0 2) = Just 0
560 |   findBinTest1 = Refl
561 |
562 |   findBinTest2 : findBinBetween [2,7,10] 3 (MkRange 0 2) = Just 1
563 |   findBinTest2 = Refl
564 |
565 |   findBinTest3 : findBinBetween [2,7,10] 9 (MkRange 0 2) = Just 2
566 |   findBinTest3 = Refl
567 |
568 |   findBinTest4 : findBinBetween [2,7,10] 7 (MkRange 0 2) = Just 2
569 |   findBinTest4 = Refl
570 |
571 |   findBinTest5 : findBinBetween [2,7,10] 15 (MkRange 0 2) = Nothing
572 |   findBinTest5 = Refl
573 |
574 |   findBinTest6 : findBinBetween [1,2,3,4,5] 6 (MkRange 0 4) = Nothing
575 |   findBinTest6 = Refl
576 |
577 | ||| Todo can this eventually be generalised to non-cubical tensors?
578 | ||| Given a non-empty sorted vector `xs` and an element `x` it finds the 
579 | ||| "right bin", i.e. the index of the smallest element that's bigger than `x`
580 | ||| If `x` is bigger than the highest element, returns `Nothing`
581 | ||| `findBin [2,7,10] 1 = Just 0`
582 | ||| `findBin [2,7,10] 3 = Just 1`
583 | ||| `findBin [2,4,6,8] 7 = Just 3`
584 | public export
585 | findBin : Ord a => {n : Nat} -> (is : IsSucc n) =>
586 |   (xs : Vect n a) -> (x : a) -> Maybe (Fin n)
587 | findBin {is = ItIsSucc {n=k}} xs x
588 |   = findBinBetween xs x (MkRange 0 last {prf=lastBiggerThanOthers {n=k} 0})
589 |  
590 |
591 | -- t : Double -> Type
592 | -- t 4 = Double
593 | -- t _ = String
594 | -- 
595 | -- th : (x : Double ** t x)
596 | -- th = (4 ** 5)
597 | -- 
598 | -- thh : (x : Double) -> Show (t x)
599 | -- thh x = ?thh_rhs
600 |
601 | public export
602 | mkDepPairShow : Show a => (ss : (x : a) -> Show (b x)) => (DPair a b -> String)
603 | mkDepPairShow = \(x ** y=> "\{show x} ** \{show (y)}"
604 |
605 | public export
606 | Show a => ((x : a) -> Show (b x)) => Show (DPair a b) where
607 |    show = mkDepPairShow
608 |
609 | public export
610 | runIf: HasIO io => Bool -> io () -> io ()
611 | runIf True action = action
612 | runIf False action = pure ()
613 |
614 | public export
615 | pairIO : HasIO io => io a -> io b -> io (a, b)
616 | pairIO a b = do
617 |   a <- a
618 |   b <- b
619 |   pure (a, b)
620 |
621 |
622 | namespace RandomUtils
623 |   public export
624 |   Random Unit where
625 |     randomIO = pure ()
626 |     randomRIO _ = pure ()
627 |
628 |   public export
629 |   Random a => Random b => Random (a, b) where
630 |     randomIO = pairIO randomIO randomIO
631 |     randomRIO ((loA, loB), (hiA, hiB))
632 |       = pairIO (randomRIO (loA, hiA)) (randomRIO (loB, hiB))
633 |
634 | -- Probably there's a faster way to do this
635 | -- public export
636 | -- {n : Nat} -> Random a => Random (Vect n a) where
637 | --   randomIO = sequence $ replicate n randomIO
638 | --   randomRIO (lo, hi) = sequence $ zipWith (\l, h => randomRIO (l, h)) lo hi
639 |
640 |
641 | namespace All
642 |   namespace Vect
643 |     public export
644 |     rewriteAllMap : {xs : Vect n a} ->
645 |       All p (f <$> xs) ->
646 |       All (p . f) xs
647 |     rewriteAllMap {xs = []} [] = []
648 |     rewriteAllMap {xs = (x :: xs)} (a :: as) = a :: rewriteAllMap as
649 |
650 |     public export
651 |     rewriteAllMap' : {xs : Vect n a} ->
652 |       All (p . f) xs ->
653 |       All p (f <$> xs)
654 |     rewriteAllMap' {xs = []} [] = []
655 |     rewriteAllMap' {xs = (x :: xs)} (a :: as) = a :: rewriteAllMap' as
656 |   
657 |   namespace List
658 |     public export
659 |     rewriteAllMap : {xs : List a} ->
660 |       All p (f <$> xs) ->
661 |       All (p . f) xs
662 |     rewriteAllMap {xs = []} [] = []
663 |     rewriteAllMap {xs = (x :: xs)} (a :: as) = a :: rewriteAllMap as
664 |
665 |   ||| Cnvert an all to a vector if it's made out of replicated things
666 |   public export
667 |   allToVect : Vect.Quantifiers.All.All p (replicate n a) -> Vect n (p a)
668 |   allToVect [] = []
669 |   allToVect (aa :: aaps) = aa :: allToVect aaps
670 |
671 |   public export
672 |   constantToVect : {xs : Vect n a} ->
673 |     Vect.Quantifiers.All.All (const b) xs -> Vect n b
674 |   constantToVect [] = []
675 |   constantToVect (bb :: bbs) = bb :: constantToVect bbs
676 |
677 |
678 | ||| Dependent parametric traverse
679 | public export
680 | dTraverse : Applicative f =>
681 |   ((p : pType) -> f (q p)) ->
682 |   (xs : Vect n pType) ->
683 |   f (All q xs)
684 | dTraverse f [] = pure []
685 | dTraverse f (p :: ps) = [| f p :: dTraverse f ps |]
686 |
687 |
688 | public export
689 | record Iso (a, b : Type) where
690 |   constructor MkIso
691 |   forward : a -> b
692 |   backward : b -> a
693 |   forwardBackward : (: a) -> backward (forward x) = x
694 |   backwardForward : (: b) -> forward (backward y) = y
695 |
696 | -- ||| Duplicate of `index` from Data.Vect.Quantifiers.All, but with an
697 | -- ||| additional `public` export modifier
698 | public export
699 | index : (i : Fin k) -> Vect.Quantifiers.All.All p ts -> p (Vect.index i ts)
700 | index FZ (x :: xs) = x
701 | index (FS j) (x :: xs) = index j xs
702 |
703 |
704 | {-
705 |
706 | interface Comult (f : Type -> Type) a where
707 |   comult : f a -> f (f a)
708 |
709 | {shape : Vect n Nat} -> Num a => Comult (TensorA shape) a where
710 |   comult t = ?eir
711 |
712 | gg : TensorA [3] Double -> TensorA [3, 3] Double
713 | gg (TS xs) = TS $ map ?fn ?gg_rhs_0
714 |
715 | -- [1, 2, 3]
716 | -- can we even do outer product?
717 | -- we wouldn't need reduce, but something like multiply?
718 | outer : {f : Type -> Type} -> {a : Type}
719 |   -> (Num a, Applicative f, Algebra f a)
720 |   => f a -> f a -> f (f a)
721 | outer xs ys = let t = liftA2 xs ys
722 |               in ?outer_rhs 
723 |   
724 |  -}
725 |
726 | |||| filter' works without `with`?
727 | filter' : (a -> Bool) -> Vect n a -> (p ** Vect p a)
728 | filter' p [] = (0 ** [])
729 | filter' p (x :: xs) = case filter' p xs of 
730 |   (_ ** xs'=> if p x then (_ ** x :: xs'else (_ ** xs')
731 |
732 | ||| filter'' implemented with `with`
733 | filter'' : (a -> Bool) -> Vect n a -> (p ** Vect p a)
734 | filter'' p [] = (0 ** [])
735 | filter'' p (x :: xs) with (filter' p xs)
736 |   _ | (_ ** xs'= if p x then (_ ** x :: xs'else (_ ** xs')
737 |
738 | {-
739 | Prelude.absurd : Uninhabited t => t -> a
740 | believe_me : a -> b
741 | -}
742 |
743 |
744 |
745 |
746 |
747 | namespace Linearity
748 |   ll1 : {n : Nat} -> Vect n a -> Nat
749 |   ll1 {n} _ = n
750 |   
751 |   -- Should this be detected as `using` the variable `n`?
752 |   -- in pattern matching, we'd have to unify type of `xs` which has in itself `len`
753 |   -- and `n` which in this case is computed to be `S len`?
754 |   -- this step of `ll2` is decomposing `n` only one level down, but the entire recursion ends up using the entire `n`
755 |   ll2 : {0 n : Nat} -> Vect n a -> Nat
756 |   ll2 [] = 0
757 |   ll2 {n=S t} (x :: xs) = 1 + ll2 xs
758 |
759 |
760 |
761 | public export
762 | testFun : Nat -> (m : Nat ** Vect m Nat)
763 |
764 | testFun2 : Nat -> Vect m Nat
765 |
766 | consume : Vect m a -> Type
767 |
768 | composed : (p : a -> Bool) ->
769 |   (xs : Vect n a) ->
770 |   consume (snd (filter p xs))
771 | composed p xs = ?composed_rhs
772 |
773 | -- public export
774 | -- filter : (elem -> Bool) -> Vect len elem -> (p ** Vect p elem)
775 | -- filter p []      = ( _ ** [] )
776 | -- filter p (x::xs) =
777 | --   let (_ ** tail) = filter p xs
778 | --    in if p x then
779 | --         (_ ** x::tail)
780 | --       else
781 | --         (_ ** tail)
782 |
783 | public export
784 | filter2 : (a -> Bool) -> Vect len a -> Vect p a
785 | filter2 f xs = ?filter2_rhs
786 |
787 | -- ||| Splits xs at each occurence of delimeter (general version for lists)
788 | -- public export
789 | -- splitList : Eq a =>
790 | --   (xs : List a) -> (delimeter : List a) -> (n : Nat ** Vect n (List a))
791 | -- splitList xs delimeter = 
792 | --   if delimeter == []
793 | --     then (1 ** [xs]) -- Empty delimiter returns original list
794 | --     else case isInfixOfList delimeter xs of
795 | --       False => (1 ** [xs]) -- Delimiter not found, return original list
796 | --       True => 
797 | --         let (before, after) = breakOnList delimeter xs
798 | --         in case after of
799 | --           [] => (1 ** [before]) -- No more occurrences
800 | --           _  => let (restCount ** restVect) = splitList (drop (length delimeter) after) delimeter
801 | --                 in (S restCount ** before :: restVect)
802 | --   where
803 | --     -- Check if list starts with delimiter
804 | --     isPrefixOfList : List a -> List a -> Bool
805 | --     isPrefixOfList [] _ = True
806 | --     isPrefixOfList _ [] = False
807 | --     isPrefixOfList (d :: ds) (x :: xs) = d == x && isPrefixOfList ds xs
808 | --     
809 | --     -- Check if delimiter occurs anywhere in the list
810 | --     isInfixOfList : List a -> List a -> Bool
811 | --     isInfixOfList del [] = del == []
812 | --     isInfixOfList del xs@(_ :: xs') = 
813 | --       isPrefixOfList del xs || isInfixOfList del xs'
814 | --     
815 | --     -- Break list at first occurrence of delimiter
816 | --     breakOnList : List a -> List a -> (List a, List a)
817 | --     breakOnList del xs = breakOnListAcc del xs []
818 | --       where
819 | --         breakOnListAcc : List a -> List a -> List a -> (List a, List a)
820 | --         breakOnListAcc del remaining acc = 
821 | --           case isPrefixOfList del remaining of
822 | --             True => (reverse acc, remaining)
823 | --             False => case remaining of
824 | --               [] => (reverse acc, [])
825 | --               (c :: cs) => breakOnListAcc del cs (c :: acc)
826 | -- 
827 | -- ||| Splits xs at each occurence of delimeter (string version)
828 | -- public export
829 | -- splitString : (xs : String) -> (delimeter : String) -> (n : Nat ** Vect n String)
830 | -- splitString xs delimeter = 
831 | --   let (n ** result) = splitList (unpack xs) (unpack delimeter)
832 | --   in (n ** pack <$> result)
833 | -- 
834 | -- ||| Simple string replacement function
835 | -- public export
836 | -- replaceString : String -> String -> String -> String
837 | -- replaceString old new str = 
838 | --   let chars = unpack str
839 | --       oldChars = unpack old
840 | --       newChars = unpack new
841 | --   in pack (replaceInList oldChars newChars chars)
842 | --   where
843 | --     replaceInList : List Char -> List Char -> List Char -> List Char
844 | --     replaceInList [] _ xs = xs
845 | --     replaceInList old new [] = []
846 | --     replaceInList old new xs@(x :: rest) =
847 | --       if isPrefixOf old xs
848 | --         then new ++ replaceInList old new (drop (length old) xs)
849 | --         else x :: replaceInList old new rest
850 |
851 |