mirror of
https://github.com/ilyakooo0/Idris-dev.git
synced 2024-11-14 13:56:59 +03:00
Merge pull request #2531 from david-christiansen/sortBy
sortBy and docs for Prelude.List
This commit is contained in:
commit
89361719f1
@ -47,25 +47,35 @@ isCons (x::xs) = True
|
||||
-- Decidable Predicates
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
data NonEmpty : List a -> Type where
|
||||
IsNonEmpty : NonEmpty (x :: xs)
|
||||
||| Satisfiable if `xs` is non-empty (e.g., if `xs` is a cons).
|
||||
data NonEmpty : (xs : List a) -> Type where
|
||||
||| The proof that a cons cell is non-empty
|
||||
IsNonEmpty : NonEmpty (x :: xs)
|
||||
|
||||
private
|
||||
nonEmptyNil : NonEmpty [] -> Void
|
||||
nonEmptyNil IsNonEmpty impossible
|
||||
|
||||
||| Decide whether a list is non-empty
|
||||
nonEmpty : (xs : List a) -> Dec (NonEmpty xs)
|
||||
nonEmpty [] = No nonEmptyNil
|
||||
nonEmpty (x :: xs) = Yes IsNonEmpty
|
||||
|
||||
data InBounds : Nat -> List a -> Type where
|
||||
InFirst : InBounds Z (x :: xs)
|
||||
InLater : InBounds k xs -> InBounds (S k) (x :: xs)
|
||||
||| Satisfiable if `k` is a valid index into `xs`
|
||||
|||
|
||||
||| @ k the potential index
|
||||
||| @ xs the list into which k may be an index
|
||||
data InBounds : (k : Nat) -> (xs : List a) -> Type where
|
||||
||| Z is a valid index into any cons cell
|
||||
InFirst : InBounds Z (x :: xs)
|
||||
||| Valid indices can be extended
|
||||
InLater : InBounds k xs -> InBounds (S k) (x :: xs)
|
||||
|
||||
instance Uninhabited (InBounds k []) where
|
||||
uninhabited InFirst impossible
|
||||
|
||||
inBounds : (n : Nat) -> (xs : List a) -> Dec (InBounds n xs)
|
||||
||| Decide whether `k` is a valid index into `xs`
|
||||
inBounds : (k : Nat) -> (xs : List a) -> Dec (InBounds k xs)
|
||||
inBounds k [] = No uninhabited
|
||||
inBounds Z (x :: xs) = Yes InFirst
|
||||
inBounds (S k) (x :: xs) with (inBounds k xs)
|
||||
@ -339,7 +349,7 @@ mapMaybe f (x::xs) =
|
||||
instance Foldable List where
|
||||
foldr c n [] = n
|
||||
foldr c n (x::xs) = c x (foldr c n xs)
|
||||
|
||||
|
||||
foldl f q [] = q
|
||||
foldl f q (x::xs) = foldl f (f q x) xs
|
||||
|
||||
@ -377,8 +387,13 @@ intersperse sep (x::xs) = x :: intersperse' sep xs
|
||||
intersperse' sep [] = []
|
||||
intersperse' sep (y::ys) = sep :: y :: intersperse' sep ys
|
||||
|
||||
intercalate : List a -> List (List a) -> List a
|
||||
intercalate sep l = concat $ intersperse sep l
|
||||
||| Given a separator list and some more lists, produce a new list by
|
||||
||| placing the separator between each of the lists.
|
||||
|||
|
||||
||| @ sep the separator
|
||||
||| @ xss the lists between which the separator will be placed
|
||||
intercalate : (sep : List a) -> (xss : List (List a)) -> List a
|
||||
intercalate sep xss = concat $ intersperse sep xss
|
||||
|
||||
||| Transposes rows and columns of a list of lists.
|
||||
|||
|
||||
@ -483,15 +498,20 @@ findIndices = findIndices' Z
|
||||
else
|
||||
findIndices' (S cnt) p xs
|
||||
|
||||
||| Find the index of the first occurrence of an element in a list, using a custom equality test.
|
||||
elemIndexBy : (a -> a -> Bool) -> a -> List a -> Maybe Nat
|
||||
elemIndexBy p e = findIndex $ p e
|
||||
|
||||
||| Find the index of the first occurrence of an element in a list,
|
||||
||| using the default equality test for the type of list elements.
|
||||
elemIndex : Eq a => a -> List a -> Maybe Nat
|
||||
elemIndex = elemIndexBy (==)
|
||||
|
||||
||| Find all indices for an element in a list, using a custom equality test.
|
||||
elemIndicesBy : (a -> a -> Bool) -> a -> List a -> List Nat
|
||||
elemIndicesBy p e = findIndices $ p e
|
||||
|
||||
||| Find all indices for an element in a list, using the default equality test for the type of list elements.
|
||||
elemIndices : Eq a => a -> List a -> List Nat
|
||||
elemIndices = elemIndicesBy (==)
|
||||
|
||||
@ -682,7 +702,12 @@ replaceOn a b l = map (\c => if c == a then b else c) l
|
||||
-- Predicates
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
isPrefixOfBy : (a -> a -> Bool) -> List a -> List a -> Bool
|
||||
||| Check whether a list is a prefix of another according to a user-supplied equality test.
|
||||
|||
|
||||
||| @ eq the equality comparison
|
||||
||| @ left the potential prefix
|
||||
||| @ right the list that may have `left` as its prefix
|
||||
isPrefixOfBy : (eq : a -> a -> Bool) -> (left, right : List a) -> Bool
|
||||
isPrefixOfBy p [] right = True
|
||||
isPrefixOfBy p left [] = False
|
||||
isPrefixOfBy p (x::xs) (y::ys) =
|
||||
@ -718,6 +743,7 @@ isInfixOf n h = any (isPrefixOf n) (tails h)
|
||||
-- Sorting
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
||| Check whether a list is sorted with respect to the default ordering for the type of its elements.
|
||||
sorted : Ord a => List a -> Bool
|
||||
sorted [] = True
|
||||
sorted (x::xs) =
|
||||
@ -725,6 +751,9 @@ sorted (x::xs) =
|
||||
Nil => True
|
||||
(y::ys) => x <= y && sorted (y::ys)
|
||||
|
||||
||| Merge two sorted lists using an arbitrary comparison
|
||||
||| predicate. Note that the lists must have been sorted using this
|
||||
||| predicate already.
|
||||
mergeBy : (a -> a -> Ordering) -> List a -> List a -> List a
|
||||
mergeBy order [] right = right
|
||||
mergeBy order left [] = left
|
||||
@ -733,15 +762,21 @@ mergeBy order (x::xs) (y::ys) =
|
||||
then x :: mergeBy order xs (y::ys)
|
||||
else y :: mergeBy order (x::xs) ys
|
||||
|
||||
||| Merge two sorted lists using the default ordering for the type of their elements.
|
||||
merge : Ord a => List a -> List a -> List a
|
||||
merge = mergeBy compare
|
||||
|
||||
sort : Ord a => List a -> List a
|
||||
sort [] = []
|
||||
sort [x] = [x]
|
||||
sort xs = let (x, y) = split xs in
|
||||
merge (sort (assert_smaller xs x))
|
||||
(sort (assert_smaller xs y)) -- not structurally smaller, hence assert
|
||||
||| Sort a list using some arbitrary comparison predicate.
|
||||
|||
|
||||
||| @ cmp how to compare elements
|
||||
||| @ xs the list to sort
|
||||
sortBy : (cmp : a -> a -> Ordering) -> (xs : List a) -> List a
|
||||
sortBy cmp [] = []
|
||||
sortBy cmp [x] = [x]
|
||||
sortBy cmp xs = let (x, y) = split xs in
|
||||
mergeBy cmp
|
||||
(sortBy cmp (assert_smaller xs x))
|
||||
(sortBy cmp (assert_smaller xs y)) -- not structurally smaller, hence assert
|
||||
where
|
||||
splitRec : List a -> List a -> (List a -> List a) -> (List a, List a)
|
||||
splitRec (_::_::xs) (y::ys) zs = splitRec xs ys (zs . ((::) y))
|
||||
@ -750,6 +785,10 @@ sort xs = let (x, y) = split xs in
|
||||
split : List a -> (List a, List a)
|
||||
split xs = splitRec xs xs id
|
||||
|
||||
||| Sort a list using the default ordering for the type of its elements.
|
||||
sort : Ord a => List a -> List a
|
||||
sort = sortBy compare
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Conversions
|
||||
--------------------------------------------------------------------------------
|
||||
@ -763,6 +802,7 @@ listToMaybe (x::xs) = Just x
|
||||
-- Misc
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
||| Keep the `Just` elements in a list, discarding the `Nothing` elements.
|
||||
catMaybes : List (Maybe a) -> List a
|
||||
catMaybes [] = []
|
||||
catMaybes (x::xs) =
|
||||
@ -836,6 +876,7 @@ hasAnyByNilFalse p (x::xs) =
|
||||
hasAnyNilFalse : Eq a => (l : List a) -> hasAny [] l = False
|
||||
hasAnyNilFalse l = rewrite (hasAnyByNilFalse (==) l) in Refl
|
||||
|
||||
||| Implement foldl using foldr, for a later equality proof.
|
||||
foldlAsFoldr : (b -> a -> b) -> b -> List a -> b
|
||||
foldlAsFoldr f z t = foldr (flip (.) . flip f) id t z
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user