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