17 | %hide Data.Vect.Quantifiers.All.index
19 | {-------------------------------------------------------------------------------
20 | {-------------------------------------------------------------------------------
21 | Various utilities necessary for TensorType, which don't fit anywhere else.
22 | This file does not depend on any other file within this project.
24 | Some of these feel like they should be in the Idris standard library
25 | -------------------------------------------------------------------------------}
26 | -------------------------------------------------------------------------------}
57 | ||| Graph of a dependent function
64 | ||| Version of `map` for dependent function
65 | ||| Note that here `x : a` is identity in some sense, it comes from `f a`
72 | ||| Dependent parametric traverse
82 | ||| The empty type has (vacuously) decidable equality
87 | ||| This should probably be in `Decidable.Equality`?
88 | ||| Though search cannot find this, so often we have to pass this explicitly
98 | ||| The proof that a decidable property leads to a contradiction
99 | ||| `IsNo` is a type Idris can automatically synthesise, unlike `Not`
100 | ||| See example below
107 | failing
128 | ||| Proof of inequality yields IsNo
168 | ||| If an element `i` is not in the singleton list `[j]`, then `j` is not in
169 | ||| the singleton list `[i]`
174 | ||| If an element `i` is in the singleton list `[j]`, then `j` is in the
175 | ||| singleton list `[i]`
183 | ||| Tensorial strength
190 | ||| Implementation of Foldable for Vect that is denotationally equivalent to
191 | ||| one in Data.Vect, but which does not use `foldrImpl` and therefore
192 | ||| reduces in the typechecker
198 | ||| toList with a different foldable implementation
208 | ||| Duplicate of utilities for Data.Vect in their Naperian form
214 | -- Because of the way foldr for Vect is implemented in Idris
215 | -- we have to use this approach below, otherwise allSuccThenProdSucc breaks
219 | -- prod [] = fromInteger 1
220 | -- prod (x :: xs) = x * prod xs
229 | ||| Dual to concat from Data.Vect
236 | ||| Trim a specified trailing value
241 | ||| Combination of `cons` and `snoc`: adds an element in front, and at the end
246 | ||| Pad a vector with a specified element to exactly `targetSize`
255 | ||| Drop the first i elements of a vector
256 | ||| Analogous to Data.Vect.drop, except the index is Fin n instead of Nat
263 | ||| Drop all the elements up and until the element `x` from a vector
286 | ||| Map each element along with its zero-based position in the list.
290 | where
295 | ||| Split a list into consecutive chunks of size `n` (clamped to at least 1).
296 | ||| The final chunk may be shorter than `n`, this is why the length of the
297 | ||| list is needed as upper bound.
301 | where
321 | ||| Trim a specified trailing value
326 | ||| Combination of `cons` and `snoc`: adds an element in front, and at the end
331 | ||| Pad a list with a specified element to at least `targetSize`
337 | ||| Drop all the elements after the element `x` from a list
344 | ||| Analogue of `(::)`
350 | -- dcons : x -> ((i : Fin k) -> i' i) -> ((i : Fin (S k)) -> i' (cons x i'))
360 | ||| All but the last element
365 | ||| Analogus to `Data.Vect.take`
385 | ||| Proof that subtracting from a successor is the same as taking the sucessor
386 | ||| of the subtraction
394 | ||| A version of `weakenN` from Data.Fin with `n` on the other side of `+`
399 | ||| Variant of `weakenN` from `Data.Fin`, but for multiplication
400 | ||| Like shiftMul, but without changing the value of the index
416 | ||| Variant of `shift` from Data.Fin, but for multiplication
417 | ||| Given a stride and an index `i : Fin n`, it returns a stride-sized step
418 | ||| That is, it returns `stride * i` : Fin (stride * n)
419 | ||| Implemented by recursing on i, adding stride each time
429 | ||| Analogue of `strengthen` from Data.Fin
430 | ||| Attempts to strengthen the bound on Fin (m + n) to Fin m
431 | ||| If it doesn't succeed, then returns the remainder in Fin n
440 | ||| Analogue of `finS` from `Data.Fin`, but without without wrapping
441 | ||| That is, `finS' last = last`
447 | --finS' {n = S _} x = case strengthen x of
448 | -- Nothing => x
449 | -- Just y => FS y
458 | ||| This can be implemented using `Data.Fin.Order`, but it doesn't seem worth
459 | ||| the effort, as the typechecker ends up needing a lot of extra hand holding
468 | -- lastBiggerThanOthers {n = 0} FZ = FromNatPrf LTEZero
469 | -- lastBiggerThanOthers {n = (S k)} FZ = FromNatPrf LTEZero
470 | -- lastBiggerThanOthers {n = (S k)} (FS x) = FSFinLTE (lastBiggerThanOthers x)
472 | ||| Adds two bounded numbers, bounds the result
473 | ||| That is, `addFinsBounded {n=5} 3 4 = 4`
474 | ||| `assert_smaller` is only needed for totality checking
487 | ||| Divides a Fin by 2, rounding down
488 | ||| `half {n=10} 6 = 3`
489 | ||| `half {n=10} 5 = 2`
490 | ||| `half {n=10} 4 = 2`
491 | ||| `half {n=10} 3 = 1`
492 | ||| `half {n=10} 2 = 1`
493 | ||| `half {n=10} 1 = 0`
500 | ||| Computes the midway index between two bounds
508 | -- ||| There is a similar function in Data.Fin.Arith, which has the smallest
509 | -- ||| possible bound. This one does not, but has a simpler type signature.
510 | -- public export
511 | -- multFin : {m, n : Nat} -> Fin m -> Fin n -> Fin (m * n)
512 | -- multFin {n = (S _)} FZ y = FZ
513 | -- multFin {n = (S _)} (FS x) y = FinArith.(+) y (weaken (multFin x y))
530 | ||| Data structure storing a lower and upper bound during a search
537 | ||| Given a non-empty sorted vector `xs`, an element `x` and a lower and upper
538 | ||| bound, it finds the "right bin", i.e. the index of the smallest element
539 | ||| between the bounds that's bigger than `x`
540 | ||| If `x` is bigger than the largest element, returns `Nothing`
541 | ||| `findBinBetween [2,7,10] 1 (MkRange 0 2) = Just 0`
542 | ||| `findBinBetween [2,7,10] 3 (MkRange 0 2) = Just 1`
543 | ||| `findBinBetween [2,7,10] 9 (MkRange 0 2) = Just 2`
544 | ||| `findBinBetween [2,7,10] 7 (MkRange 0 2) = Just 2`
545 | ||| `findBinBetween [2,7,10] 15 (MkRange 0 2) = Nothing`
546 | ||| `findBinBetween [1,2,3,4,5] 6 (MkRange 0 4) = Nothing`
547 | ||| Done using binary search
586 | ||| Todo can this eventually be generalised to non-cubical tensors?
587 | ||| Given a non-empty sorted vector `xs` and an element `x` it finds the
588 | ||| "right bin", i.e. the index of the smallest element that's bigger than `x`
589 | ||| If `x` is bigger than the highest element, returns `Nothing`
590 | ||| `findBin [2,7,10] 1 = Just 0`
591 | ||| `findBin [2,7,10] 3 = Just 1`
592 | ||| `findBin [2,4,6,8] 7 = Just 3`
643 | ||| Cnvert an all to a vector if it's made out of replicated things
663 | ||| The identity isomorphism
668 | -- ||| Duplicate of `index` from Data.Vect.Quantifiers.All, but with an
669 | -- ||| additional `public` export modifier
675 | ||| `Fin n` without ordering, i.e. a set. Quotient not implemented, simply a
676 | ||| wrapped around `Fin n` to make `Bag` and `List` containers not reduce to
677 | ||| the same type. Once quotient containers are implemented this will not be
678 | ||| necessary.
685 | ||| Used to color/style terminal output. Wraps a string in the given SGR
686 | ||| attributes from `Control.ANSI.SGR`
687 | export
691 | export
695 | export
699 | export
703 | export
707 | export
711 | {-
713 | interface Comult (f : Type -> Type) a where
714 | comult : f a -> f (f a)
716 | {shape : Vect n Nat} -> Num a => Comult (TensorA shape) a where
717 | comult t = ?eir
719 | gg : TensorA [3] Double -> TensorA [3, 3] Double
720 | gg (TS xs) = TS $ map ?fn ?gg_rhs_0
722 | -- [1, 2, 3]
723 | -- can we even do outer product?
724 | -- we wouldn't need reduce, but something like multiply?
725 | outer : {f : Type -> Type} -> {a : Type}
726 | -> (Num a, Applicative f, Algebra f a)
727 | => f a -> f a -> f (f a)
728 | outer xs ys = let t = liftA2 xs ys
729 | in ?outer_rhs
730 | -}
732 | |||| filter' works without `with`?
738 | ||| filter'' implemented with `with`
744 | {-
745 | Prelude.absurd : Uninhabited t => t -> a
746 | believe_me : a -> b
747 | -}
753 | -- Should this be detected as `using` the variable `n`?
754 | -- in pattern matching, we'd have to unify type of `xs` which has in itself `len`
755 | -- and `n` which in this case is computed to be `S len`?
756 | -- this step of `ll2` is decomposing `n` only one level down, but the entire recursion ends up using the entire `n`
763 | -- public export
764 | -- filter : (elem -> Bool) -> Vect len elem -> (p ** Vect p elem)
765 | -- filter p [] = ( _ ** [] )
766 | -- filter p (x::xs) =
767 | -- let (_ ** tail) = filter p xs
768 | -- in if p x then
769 | -- (_ ** x::tail)
770 | -- else
771 | -- (_ ** tail)
777 | -- ||| Splits xs at each occurence of delimeter (general version for lists)
778 | -- public export
779 | -- splitList : Eq a =>
780 | -- (xs : List a) -> (delimeter : List a) -> (n : Nat ** Vect n (List a))
781 | -- splitList xs delimeter =
782 | -- if delimeter == []
783 | -- then (1 ** [xs]) -- Empty delimiter returns original list
784 | -- else case isInfixOfList delimeter xs of
785 | -- False => (1 ** [xs]) -- Delimiter not found, return original list
786 | -- True =>
787 | -- let (before, after) = breakOnList delimeter xs
788 | -- in case after of
789 | -- [] => (1 ** [before]) -- No more occurrences
790 | -- _ => let (restCount ** restVect) = splitList (drop (length delimeter) after) delimeter
791 | -- in (S restCount ** before :: restVect)
792 | -- where
793 | -- -- Check if list starts with delimiter
794 | -- isPrefixOfList : List a -> List a -> Bool
795 | -- isPrefixOfList [] _ = True
796 | -- isPrefixOfList _ [] = False
797 | -- isPrefixOfList (d :: ds) (x :: xs) = d == x && isPrefixOfList ds xs
798 | --
799 | -- -- Check if delimiter occurs anywhere in the list
800 | -- isInfixOfList : List a -> List a -> Bool
801 | -- isInfixOfList del [] = del == []
802 | -- isInfixOfList del xs@(_ :: xs') =
803 | -- isPrefixOfList del xs || isInfixOfList del xs'
804 | --
805 | -- -- Break list at first occurrence of delimiter
806 | -- breakOnList : List a -> List a -> (List a, List a)
807 | -- breakOnList del xs = breakOnListAcc del xs []
808 | -- where
809 | -- breakOnListAcc : List a -> List a -> List a -> (List a, List a)
810 | -- breakOnListAcc del remaining acc =
811 | -- case isPrefixOfList del remaining of
812 | -- True => (reverse acc, remaining)
813 | -- False => case remaining of
814 | -- [] => (reverse acc, [])
815 | -- (c :: cs) => breakOnListAcc del cs (c :: acc)
816 | --
817 | -- ||| Splits xs at each occurence of delimeter (string version)
818 | -- public export
819 | -- splitString : (xs : String) -> (delimeter : String) -> (n : Nat ** Vect n String)
820 | -- splitString xs delimeter =
821 | -- let (n ** result) = splitList (unpack xs) (unpack delimeter)
822 | -- in (n ** pack <$> result)
823 | --
824 | -- ||| Simple string replacement function
825 | -- public export
826 | -- replaceString : String -> String -> String -> String
827 | -- replaceString old new str =
828 | -- let chars = unpack str
829 | -- oldChars = unpack old
830 | -- newChars = unpack new
831 | -- in pack (replaceInList oldChars newChars chars)
832 | -- where
833 | -- replaceInList : List Char -> List Char -> List Char -> List Char
834 | -- replaceInList [] _ xs = xs
835 | -- replaceInList old new [] = []
836 | -- replaceInList old new xs@(x :: rest) =
837 | -- if isPrefixOf old xs
838 | -- then new ++ replaceInList old new (drop (length old) xs)
839 | -- else x :: replaceInList old new rest