An extended toolbox for working with lists: everything from the elm/core
List module plus Haskell-inspired helpers such as nub, intercalate, and
groupBy, all implemented the Elm way.
Extract the first element of a list.
head [ 1, 2, 3 ] == Just 1
head [] == NothingGet the last element of a list. Return Just the element if the list is
non-empty, or Nothing when the list is empty.
last [ 1, 2, 3 ] == Just 3
last [] == NothingExtract the rest of the list.
tail [ 1, 2, 3 ] == Just [ 2, 3 ]
tail [] == NothingReturn all but the last element of a list.
If the list is non-empty, returns Just the leading elements (possibly [] for a single-element list).
If the list is empty, returns Nothing.
init [ 1, 2, 3 ] == Just [ 1, 2 ]
init [ 1 ] == Just []
init [] == NothingDecompose a list into its first element and the remaining elements.
For a non-empty list, returns Just ( x, xs ).
For an empty list, returns Nothing.
uncons [ 1, 2, 3 ] == Just ( 1, [ 2, 3 ] )
uncons [] == NothingDecompose a list into its initial elements and its last element.
For a non-empty list, returns Just ( ys, y ) where ys ++ [ y ] reconstructs the original list.
For an empty list, returns Nothing.
unsnoc [ 1, 2, 3 ] == Just ( [ 1, 2 ], 3 )
unsnoc [ 1 ] == Just ( [], 1 )
unsnoc [] == NothingCreate a list with only one element
Determine if a list is empty.
isEmpty [] == TrueDetermine the length of a list.
length [ 1, 2, 3 ] == 3Compare the length of a list with an integer.
Return GT if the list is longer, LT if shorter, EQ if equal.
Any positive-length list is GT for a negative integer.
compareLength [ 1, 2, 3 ] 2 == GT
compareLength [ 1, 2 ] 2 == EQ
compareLength [ 1 ] 2 == LTApply a function to every element of a list.
map sqrt [ 1, 4, 9 ] == [ 1, 2, 3 ]
map not [ True, False, True ] == [ False, True, False ]So map func [ a, b, c ] is the same as [ func a, func b, func c ]
Combine two lists, combining them with the given function. If one list is longer, the extra elements are dropped.
totals : List Int -> List Int -> List Int
totals xs ys =
List.map2 (+) xs ys
-- totals [1,2,3] [4,5,6] == [5,7,9]
pairs : List a -> List b -> List ( a, b )
pairs xs ys =
List.map2 Tuple.pair xs ys
-- pairs ["alice","bob","chuck"] [2,5,7,8]
-- == [("alice",2),("bob",5),("chuck",7)]Same as map but the function is also applied to the index of each
element (starting at zero).
indexedMap Tuple.pair [ "Tom", "Sue", "Bob" ] == [ ( 0, "Tom" ), ( 1, "Sue" ), ( 2, "Bob" ) ]Reverse a list.
reverse [ 1, 2, 3, 4 ] == [ 4, 3, 2, 1 ]Places the given value between all members of the given list.
intersperse "on" [ "turtles", "turtles", "turtles" ] == [ "turtles", "on", "turtles", "on", "turtles" ]Concatenates the lists in the second argument, inserting the first argument between each adjacent pair.
intercalate [ 0, 1 ] [ [ 2, 3 ], [ 4, 5, 6 ], [] ] == [ 2, 3, 0, 1, 4, 5, 6, 0, 1 ]
intercalate [ 1, 2, 3 ] [ [], [] ] == [ 1, 2, 3 ]
let
s =
String.toList
in
intercalate (s ", ") [ s "Lorem", s "ipsum", s "dolor" ]
== s "Lorem, ipsum, dolor"Transpose the rows and columns of the argument list of lists.
transpose [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] == [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ]If some of the rows are shorter than the following rows, their elements are skipped:
transpose [ [ 10, 11 ], [ 20 ], [], [ 30, 31, 32 ] ] == [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ]Return the list of all subsequences of the argument.
let
s =
String.toList
in
subsequences (s "abc") == map s [ "", "a", "b", "ab", "c", "ac", "bc", "abc" ]Return the list of all permutations of the argument. Note that the order of permutations is not lexicographic.
map (take n)
(take (product (List.range 1 n)) (permutations (List.range 1 n)))
== permutations (range 1 n)permutations [ 1, 2 ] == [ [ 1, 2 ], [ 2, 1 ] ]
permutations [] == [ [] ]
let
s =
String.toList
in
permutations "abc" == [ "abc", "bac", "cba", "bca", "cab", "acb" ]Filter out certain values. For example, maybe you have a bunch of strings from an untrusted source and you want to turn them into numbers:
numbers : List Int
numbers =
filterMap String.toInt [ "3", "hi", "12", "4th", "May" ]
-- numbers == [3, 12]Reduce a list from the left.
foldl (+) 0 [ 1, 2, 3 ] == 6
foldl (::) [] [ 1, 2, 3 ] == [ 3, 2, 1 ]So foldl step state [1,2,3] is like saying:
state
|> step 1
|> step 2
|> step 3Reduce a list from the right.
foldr (+) 0 [ 1, 2, 3 ] == 6
foldr (::) [] [ 1, 2, 3 ] == [ 1, 2, 3 ]So foldr step state [1,2,3] is like saying:
state
|> step 3
|> step 2
|> step 1Concatenate a bunch of lists into a single list:
concat [ [ 1, 2 ], [ 3 ], [ 4, 5 ] ] == [ 1, 2, 3, 4, 5 ]Map a given function onto a list and flatten the resulting lists.
concatMap f xs == concat (map f xs)Return the logical conjunction of a list of Bools.
Evaluation of this function stops at the first occurrence of True, and the result is True.
and [] == True
and [ True ] == True
and [ False ] == False
and [ True, True, False ] == FalseReturn the logical disjunction of a list of Bools.
Evaluation of this function stops at the first occurrence of True, and the result is True.
or [] == False
or [ False ] == False
or [ True ] == True
or [ True, True, False ] == TrueDetermine if any elements satisfy some test.
any isEven [ 2, 3 ] == True
any isEven [ 1, 3 ] == False
any isEven [] == FalseDetermine if all elements satisfy some test.
all isEven [ 2, 4 ] == True
all isEven [ 2, 3 ] == False
all isEven [] == TrueGet the sum of the list elements.
sum [ 1, 2, 3 ] == 6
sum [ 1, 1, 1 ] == 3
sum [] == 0Get the product of the list elements.
product [ 2, 2, 2 ] == 8
product [ 3, 3, 3 ] == 27
product [] == 1Find the maximum element in a non-empty list.
maximum [ 1, 4, 2 ] == Just 4
maximum [] == NothingFind the minimum element in a non-empty list.
minimum [ 3, 2, 1 ] == Just 1
minimum [] == NothingThe list of successive reduced values from the left.
scanl f z [x1, x2, ...] == [z, f x1 z, f x2 (f x1 z), ...]last (scanl f z xs) == foldl f z xsscanl (+) 0 (List.range 1 4) == [ 0, 1, 3, 6, 10 ]
scanl (+) 42 [] == [ 42 ]
scanl (-) 100 (List.range 1 4) == [ 100, 99, 97, 94, 90 ]
scanl String.cons "foo" [ 'a', 'b', 'c', 'd' ]
== [ "foo", "afoo", "bafoo", "cbafoo", "dcbafoo" ]
scanl (+) 0 (range 1 10) == [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45 ]The right-to-left dual of scanl. Note that the order of parameters on the accumulating function are reversed compared to scanl. Also note that
head (scanr f z xs) == foldr f z xs.scanr (+) 0 (List.range 1 4) == [ 10, 9, 7, 4, 0 ]
scanr (+) 42 [] == [ 42 ]
scanr (-) 100 (List.range 1 4) == [ 98, -97, 99, -96, 100 ]
scanr String.cons "foo" [ 'a', 'b', 'c', 'd' ]
== [ "abcdfoo", "bcdfoo", "cdfoo", "dfoo", "foo" ]Behaves like a combination of map and foldl; it applies a function to
each element of a list, passing an accumulating parameter from left to right,
and returning a final value of this accumulator together with the new list.
mapAccumL (\a b -> ( a + b, a )) 0 (range 1 10)
== ( 55, [ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45 ] )
mapAccumL (\a b -> ( a ++ String.fromInt b, a )) "0" (range 1 5)
== ( "012345", [ "0", "01", "012", "0123", "01234" ] )Behaves like a combination of map and foldr; it applies a function to
each element of a list, passing an accumulating parameter from right to left,
and returning a final value of this accumulator together with the new list.
mapAccumR (\a b -> ( a + b, a )) 0 (range 1 10)
== ( 55, [ 54, 52, 49, 45, 40, 34, 27, 19, 10, 0 ] )
mapAccumR (\a b -> ( a ++ String.fromInt b, a )) "0" (range 1 5)
== ( "054321", [ "05432", "0543", "054", "05", "0" ] )n repeated applications f to x
iterate n f x == [x, f x, f (f x), ...]iterate 3 ((+) 1) 0 == [ 0, 1, 2 ]Create a list with n copies of a value:
repeat 3 ( 0, 0 ) == [ ( 0, 0 ), ( 0, 0 ), ( 0, 0 ) ]Create a list of numbers, every element increasing by one. You give the lowest and highest number that should be in the list.
range 3 6 == [ 3, 4, 5, 6 ]
range 3 3 == [ 3 ]
range 6 3 == []A dual to foldr: while foldr reduces a list to a summary value,
unfoldr builds a list from a seed value. The function takes the element
and returns Nothing if it is done producing the list or returns Just (a,b),
in which case, a is a prepended to the list
and b is used as the next element in a recursive call.
In some cases, unfoldr can undo a foldr operation:
unfoldr g (foldr f z xs) == xsif the following holds:
g (f x y) = Just (x,y)
g z = NothingFor example:
unfoldr
(\b ->
if b == 0 then
Nothing
else
Just ( b, b - 1 )
)
10
== [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]Take the first n members of a list.
take 2 [ 1, 2, 3, 4 ] == [ 1, 2 ]Drop the first n members of a list.
drop 2 [ 1, 2, 3, 4 ] == [ 3, 4 ]Return a tuple where first element is xs prefix of length n and second element is the remainder of the list:
splitAt 6 (String.toList "Hello World!")
== ( String.toList "Hello ", String.toList "World!" )
splitAt 3 [ 1, 2, 3, 4, 5 ] == ( [ 1, 2, 3 ], [ 4, 5 ] )
splitAt 1 [ 1, 2, 3 ] == ( [ 1 ], [ 2, 3 ] )
splitAt 3 [ 1, 2, 3 ] == ( [ 1, 2, 3 ], [] )
splitAt 4 [ 1, 2, 3 ] == ( [ 1, 2, 3 ], [] )
splitAt 0 [ 1, 2, 3 ] == ( [], [ 1, 2, 3 ] )
splitAt -1 [ 1, 2, 3 ] == ( [], [ 1, 2, 3 ] )Applied to a predicate p and a list xs, returns the longest prefix (possibly empty) of xs of elements that satisfy p.
takeWhile (\x -> x < 3) [ 1, 2, 3, 4, 1, 2, 3, 4 ] == [ 1, 2 ]
takeWhile (\x -> x < 9) [ 1, 2, 3 ] == [ 1, 2, 3 ]
takeWhile (\x -> x < 0) [ 1, 2, 3 ] == []Return the suffix remaining after takeWhile
dropWhile (\x -> x < 3) [ 1, 2, 3, 4, 5, 1, 2, 3 ] == [ 3, 4, 5, 1, 2, 3 ]
dropWhile (\x -> x < 9) [ 1, 2, 3 ] == []
dropWhile (\x -> x < 0) [ 1, 2, 3 ] == [ 1, 2, 3 ]Drops the largest suffix of a list in which the given predicate holds for all elements.
let
isSpace c =
0x09 <= Char.toCode c && Char.toCode c <= 0x0D
in
dropWhileEnd isSpace (String.toList "foo\n") == String.toList "foo"
let
isSpace c =
0x09 <= Char.toCode c && Char.toCode c <= 0x0D
in
dropWhileEnd isSpace (String.toList "foo bar") == String.toList "foo bar"
dropWhileEnd (\x -> x > 10) (List.range 1 20) == [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]Return a tuple where first element is the longest prefix (possibly empty) of xs of elements that satisfy p and second element is the remainder of the list.
span (\x -> x < 3) [ 1, 2, 3, 4, 1, 2, 3, 4 ] == ( [ 1, 2 ], [ 3, 4, 1, 2, 3, 4 ] )
span (\x -> x < 9) [ 1, 2, 3 ] == ( [ 1, 2, 3 ], [] )
span (\x -> x < 0) [ 1, 2, 3 ] == ( [], [ 1, 2, 3 ] )Return a tuple where first element is longest prefix (possibly empty) of xs of elements that do not satisfy p and second element is the remainder of the list:
break p
== span (not << p)
== ( takeWhile (not << p) xs, dropWhile (not << p) xs )break (\x -> x > 3) [ 1, 2, 3, 4, 1, 2, 3, 4 ] == ( [ 1, 2, 3 ], [ 4, 1, 2, 3, 4 ] )
break (\x -> x < 9) [ 1, 2, 3 ] == ( [], [ 1, 2, 3 ] )
break (\x -> x > 9) [ 1, 2, 3 ] == ( [ 1, 2, 3 ], [] )Drops the given prefix from a list. It returns Nothing if the list did not start with the prefix given, or Just the list after the prefix, if it does.
stripPrefix (String.toList "foo") (String.toList "foobar")
== Just (String.toList "bar")
stripPrefix (String.toList "foo") (String.toList "foo")
== Just (String.toList "")
stripPrefix (String.toList "foo") (String.toList "barfoo")
== Nothing
stripPrefix (String.toList "foo") (String.toList "barfoobaz")
== NothingReturn a list of lists such that the concatenation of the result is equal to the argument. Moreover, each sublist in the result is non-empty, all elements are equal to the first one, and consecutive equal elements of the input end up in the same element of the output list.
group is a special case of groupBy, which allows the programmer to supply
their own equality test.
group (String.toList "Mississippi")
|> map String.fromList
== [ "M", "i", "ss", "i", "ss", "i", "pp", "i" ]
group [ 1, 1, 1, 2, 2, 3, 4, 5, 5 ] == [ [ 1, 1, 1 ], [ 2, 2 ], [ 3 ], [ 4 ], [ 5, 5 ] ]Return all initial segments of the argument, shortest first. inits is semantically equivalent to
map reverse . scanl (flip (:)) [], but under the hood uses a queue to amortize costs of reverse.
inits (String.toList "abc")
|> map String.fromList
== [ "", "a", "ab", "abc" ]
inits [] == [ [] ]Return all final segments of the argument, longest first.
tails (String.toList "abc")
|> map String.fromList
== [ "abc", "bc", "c", "" ]
tails [ 1, 2, 3 ] == [ [ 1, 2, 3 ], [ 2, 3 ], [ 3 ], [] ]
tails [] == [ [] ]Takes two lists and returns True iff the first list is a prefix of the second.
isPrefixOf (String.toList "Hello") (String.toList "Hello World!") == True
isPrefixOf (String.toList "Hello") (String.toList "Wello Horld!") == FalseisPrefixOf shortcuts when the first argument is empty:
forall x, isPrefixOf [] x == TrueTakes two lists and returns True iff the first
list is a suffix of the second.
isSuffixOf (String.toList "ld!") (String.toList "Hello World!") == True
isSuffixOf (String.toList "World") (String.toList "Hello World!") == FalseTakes two lists and returns True iff the first list is contained,
wholly and intact, anywhere within the second.
isInfixOf (String.toList "Haskell")
(String.toList "I really like Haskell.")
== True
isInfixOf (String.toList "Ial")
(String.toList "I really like Haskell.")
== FalseReturn True if all the elements of the first list occur, in order,
in the second. The elements do not have to occur consecutively.
isSubsequenceOf x y == elem x (subsequences y)Note:
isSubsequenceOf is often used in infix form.isSubsequenceOf (String.toList "GHC")
(String.toList "The Glorious Haskell Compiler") == True
isSubsequenceOf ['a'..'z'] == True
isSubsequenceOf [1..10] [10,9..0] == FalseDoes the element occur in the structure?
Note:
elem is often used in infix form.elem 3 [] == False
elem 3 [ 1, 2 ] == False
elem 3 [ 1, 2, 3, 4, 5 ] == TrueThe negation of elem.
notElem 3 [] == True
notElem 3 [ 1, 2 ] == True
notElem 3 [ 1, 2, 3, 4, 5 ] == FalseLooks up the value associated with the key in an association list.
lookup 2 [] == Nothing
lookup 2 [ ( 1, "first" ) ] == Nothing
lookup 2 [ ( 1, "first" ), ( 2, "second" ), ( 3, "third" ) ]
== Just "second"Figure out whether a list contains a value.
member 9 [ 1, 2, 3, 4 ] == False
member 4 [ 1, 2, 3, 4 ] == TrueReturn the leftmost element of the list matching the predicate,
or Nothing if there is no such element.
find (\x -> x > 42) [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 ] == Just 45
find (\x -> x > 12) (range 1 7) == NothingKeep elements that satisfy the test.
filter isEven [ 1, 2, 3, 4, 5, 6 ] == [ 2, 4, 6 ]Partition a list based on some test. The first list contains all values that satisfy the test, and the second list contains all the value that do not.
partition (\x -> x < 3) [ 0, 1, 2, 3, 4, 5 ] == ( [ 0, 1, 2 ], [ 3, 4, 5 ] )
partition isEven [ 0, 1, 2, 3, 4, 5 ] == ( [ 0, 2, 4 ], [ 1, 3, 5 ] )Return the index of the first element in the given list which is equal to
the query element, or Nothing if there is no such element.
elemIndex 4 (range 0 10) == Just 4
elemIndex 'o' (String.toList "haskell") == NothingReturn the indicies of all elements equal to the query element, in ascending order.
elemIndices 'o' (String.toList "Hello World") == [ 4, 7 ]
elemIndices 1 [ 1, 2, 3, 1, 2, 3 ] == [ 0, 3 ]Return the index of the first element in the list satisfying the predicate,
or Nothing if there is no such element.
let
isSpace c =
0x09 <= Char.toCode c && Char.toCode c <= 0x0D
in
findIndex isSpace (String.toList "Hello World!") == Just 5
findIndex ((/=) 0 << modBy 2) [ 0, 2, 4, 6 ] == Nothing
findIndex ((==) 0 << modBy 2) [ 1, 2, 3, 4 ] == Just 1Extends findIndex, by returning the indices of all elements satisfying
the predicate, in ascending order.
findIndices (\x -> elem x (String.toList "aeiou"))
(String.toList "Hello World!")
== [ 1, 4, 7 ]
findIndices (\l -> String.length l > 3)
[ "a", "bcde", "fgh", "ijklmnop" ]
== [ 1, 3 ]Return a list of corresponding pairs.
zip [ 1, 2, 3 ] [ 'a', 'b', 'c' ] == [ ( 1, 'a' ), ( 2, 'b' ), ( 3, 'c' ) ]If one input list is shorter than the other, excess elements of the longer list are discarded.
zip [ 1 ] [ 'a', 'b' ] == [ ( 1, 'a' ) ]
zip [ 1, 2 ] [ 'a' ] == [ ( 1, 'a' ) ]
zip [] [ 1, 2, 3 ] == []
zip [ 1, 2, 3 ] [] == []generalises zip by zipping with the function given as the first argument, instead of a tupling function.
zipWith (,) xs ys == zip xs ys
zipWith f [x1,x2,x3..] [y1,y2,y3..] == [f x1 y1, f x2 y2, f x3 y3..]zipWith is right-lazy:
let
bot () =
bot ()
in
zipWith bot [] [ () ] == []zipWith (+) [ 1, 2, 3 ] [ 4, 5, 6 ] == [ 5, 7, 9 ]
zipWith (++) [ "hello ", "foo" ] [ "world!", "bar" ]
== [ "hello world!", "foobar" ]Combines three elements, as well as three lists and returns a list of the
function applied to corresponding elements, analogous to zipWith.
zipWith3 (\x y z -> ( x, y, z )) xs ys zs == zip3 xs ys zs
zipWith3 f [ x1, x2, x3 ] [ y1, y2, y3 ] [ z1, z2, z3 ]
== [ f x1 y1 z1, f x2 y2 z2, f x3 y3 z3 ]zipWith3 (\x y z -> [ x, y, z ])
(String.toList "123")
(String.toList "abc")
(String.toList "xyz")
|> map String.fromList
== [ "1ax", "2by", "3cz" ]
zipWith3 (\x y z -> (x * y) + z)
[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8, 9 ]
== [ 11, 18, 27 ]Decompose a list of tuples into a tuple of lists.
unzip [ ( 0, True ), ( 17, False ), ( 1337, True ) ] == ( [ 0, 17, 1337 ], [ True, False, True ] )Takes a list of triples and returns three lists of the respective
components, analogous to unzip.
unzip3 [] == ( [], [], [] )
unzip3 [ ( 1, 'a', True ), ( 2, 'b', False ) ]
== ( [ 1, 2 ], [ 'a', 'b' ], [ True, False ] )Remove duplicate elements from a list. In particular, it keeps only the first occurrence of each element. (The name nub means `essence'.)
This is a special case of nubBy, which allows the programmer to
supply their own equality test.
Performance: nub runs in O(n^2) time because it compares each element with
all preceding ones. If you do not need to preserve the original order and
elements are comparable, you can get O(nlogn) with:
filterMap head << group << sort`The result will be sorted rather than in the original order.
nub [ 1, 2, 3, 4, 3, 2, 1, 2, 4, 3, 5 ] == [ 1, 2, 3, 4, 5 ]
nub (String.toList "hello, world!") == String.toList "helo, wrd!"Removes the first occurrence of x from its list argument. It is a special case of deleteBy, which allows the programmer to supply their own equality test.
delete 'a' (String.toList "banana") |> String.fromList == "bnana"
delete "not" [ "haskell", "is", "not", "awesome" ] == [ "haskell", "is", "awesome" ]List difference (non-associative). In the result of delete xs ys, the
first occurrence of each element of ys in turn (if any) has been removed
from xs. Thus delete (xs ++ ys) xs == ys.
It is a special case of deleteFirstsBy, which allows the
programmer to supply their own equality test.
delete (String.toList "Hello World!") (String.toList "ell W")
|> String.fromList
== "Hoorld!"Return the list union of the two lists. It is a special case of
unionBy, which allows the programmer to supply their own
equality test.
union (String.toList "dog") (String.toList "cow")
|> String.fromList
== "dogcw"All elements in the first list are kept including duplicates. From the second list, each element is added only if it has not appeared earlier in the result.
union (String.toList "coot") (String.toList "duck")
|> String.fromList
== "cootduk"
union (String.toList "duck") (String.toList "coot")
|> String.fromList
== "duckot"Takes the list intersection of two lists. It is a special case of
intersectBy, which allows the programmer to supply their own
equality test.
intersect [ 1, 2, 3, 4 ] [ 2, 4, 6, 8 ] == [ 2, 4 ]If equal elements are present in both lists, an element from the first list will be used, and all duplicates from the second list quashed:
intersect [ 1, 1, 2 ] [ 1, 2, 3 ] == [ 1, 1, 2 ]However if the first list contains duplicates, so will the result.
intersect (String.toList "coot") (String.toList "heron")
|> String.fromList
== "oo"
intersect (String.toList "heron") (String.toList "coot")
|> String.fromList
== "o"Sort values from lowest to highest
sort [ 3, 1, 5 ] == [ 1, 3, 5 ]Sort a list by comparing the results of a key function applied to
each element. sortOn f is equivalent to
sortBy (\x y -> compare (f x) (f y)), but has the performance advantage of
only evaluating f once for each element in the input list. This is called the
decorate-sort-undecorate paradigm, or Schwartzian transform.
Elements are arranged from lowest to highest, keeping duplicates in the order they appeared in the input.
sortOn Tuple.first [ ( 2, "world" ), ( 4, "!" ), ( 1, "Hello" ) ]
== [ ( 1, "Hello" ), ( 2, "world" ), ( 4, "!" ) ]
sortOn String.length [ "jim", "creed", "pam", "michael", "dwight", "kevin" ]
== [ "jim", "pam", "creed", "kevin", "dwight", "michael" ]Inserts an element into a list at the first position where it is less
than or equal to the next element. In particular, if the list is sorted
before the call, the result will also be sorted. It is a special case of
insertBy, which allows the programmer to supply their own
comparison function.
insert -1 [ 1, 2, 3 ] == [ -1, 1, 2, 3 ]
insert 'd' (String.toList "abcefg") == String.toList "abcdefg"
insert 4 [ 1, 2, 3, 5, 6, 7 ] == [ 1, 2, 3, 4, 5, 6, 7 ]Behaves just like nub, except it uses a user-supplied equality predicate.
nubBy (\x y -> modBy 3 x == modBy 3 y) [ 1, 2, 4, 5, 6 ] == [ 1, 2, 6 ]
nubBy (/=) [ 2, 7, 1, 8, 2, 8, 1, 8, 2, 8 ] == [ 2, 2, 2 ]
nubBy (>) [ 1, 2, 3, 2, 1, 5, 4, 5, 3, 2 ] == [ 1, 2, 3, 5, 5 ]Behaves like delete, but takes a user-supplied equality
predicate.
deleteBy (<=) 4 (range 1 10) == [ 1, 2, 3, 5, 6, 7, 8, 9, 10 ]
deleteBy (/=) 5 [ 5, 5, 4, 3, 5, 2 ] == [ 5, 5, 3, 5, 2 ]Return the first list with the first occurrence of each element of the second list removed.
deleteFirsts == deleteFirstsBy (==)deleteFirstsBy (>) (range 1 10) [ 3, 4, 5 ] == [ 4, 5, 6, 7, 8, 9, 10 ]
deleteFirstsBy (/=) (range 1 10) [ 1, 3, 5 ] == [ 4, 5, 6, 7, 8, 9, 10 ]Return the list union of the two lists using given equality function.
If equal elements are present in both lists, an element from the first list will be used. If the second list contains equal elements, only the first one will be retained:
type Arg a b = Arg a b
eq (Arg a1 b1) (Arg a2 b2) = a1 == a2
unionBy eq [Arg () "dog"] [Arg () "cow"] == [Arg () "dog"]
unionBy eq [] [Arg () "dog", Arg () "cow"] == [Arg () "dog"]unionBy (>) [ 3, 4, 5 ] [ 1, 2, 3, 4, 5, 6 ] == [ 3, 4, 5, 4, 5, 6 ]Return the list intersection of two lists using given equality function.
If equal elements are present in both lists, an element from the first list will be used, and all duplicates from the second list quashed:
type Arg a b = Arg a b
eq (Arg a1 b1) (Arg a2 b2) = a1 == a2
intersect [Arg () "dog"] [Arg () "cow", Arg () "cat"] == [Arg () "dog"]Group adjacent elements according to the given equality function.
When a supplied relation is not transitive, it is important to remember that equality is checked against the first element in the group, not against the nearest neighbour:
groupBy (\a b -> b - a < 5) (range 0 19)
== [ [ 0, 1, 2, 3, 4 ]
, [ 5, 6, 7, 8, 9 ]
, [ 10, 11, 12, 13, 14 ]
, [ 15, 16, 17, 18, 19 ]
]groupBy (/=) [1, 1, 1, 2, 3, 1, 4, 4, 5
== [[1],[1],[1,2,3],[1,4,4,5]]
groupBy (>) [1, 3, 5, 1, 4, 2, 6, 5, 4]
== [[1],[3],[5,1,4,2],[6,5,4]]
groupBy (const not) [True, False, True, False, False, False, True]
== [[True,False],[True,False,False,False],[True]]Sort values by a derived property.
alice = { name="Alice", height=1.62 }
bob = { name="Bob" , height=1.85 }
chuck = { name="Chuck", height=1.76 }
sortBy .name [chuck,alice,bob] == [alice,bob,chuck]
sortBy .height [chuck,alice,bob] == [alice,chuck,bob]
sortBy String.length ["mouse","cat"] == ["cat","mouse"]Sort values with a custom comparison function.
sortWith flippedComparison [1,2,3,4,5] == [5,4,3,2,1]
flippedComparison a b =
case compare a b of
LT -> GT
EQ -> EQ
GT -> LTThis is also the most general sort function, allowing you
to define any other: sort == sortWith compare
Insert a value into a list using the given ordering function.
insertBy (\x y -> compare (length x) (length y))
[ 1, 2 ]
[ [ 1 ], [ 1, 2, 3 ], [ 1, 2, 3, 4 ] ]
== [ [ 1 ], [ 1, 2 ], [ 1, 2, 3 ], [ 1, 2, 3, 4 ] ]The largest element of a list if exists with respect to the given comparison function. If there are multiple largest elements, the rightmost of them is chosen.
maximumBy (\x y -> compare (String.length x) (String.length y))
[ "Hello", "World", "!", "Longest", "bar" ]
== Just "Longest"The least element of a list if exists with respect to the given comparison function. If there are multiple least elements, the leftmost of them is chosen.
minimumBy (\x y -> compare (String.length x) (String.length y))
[ "Hello", "World", "!", "Longest", "bar" ]
== Just "!"An overloaded version of length. In particular, instead of returning an
Int, it returns Float type.
(genericLength [ 1, 2, 3 ] == 3) == True
(genericLength [ 1, 2, 3 ] == 3.0) == True
Put two lists together.
You can also use the
(++)operator to append lists.