eldesh/alt-core-elm/1.0.0

NOTE: the latest version is 1.2.0

Data.List

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.

Definition

List

Basic functions

append : List a -> List a -> List a

Put two lists together.

append [ 1, 1, 2 ] [ 3, 5, 8 ] == [ 1, 1, 2, 3, 5, 8 ]


append [ 'a', 'b' ] [ 'c' ] == [ 'a', 'b', 'c' ]

You can also use the (++) operator to append lists.

last : List a -> Maybe a

Get 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 [] == Nothing
tail : List a -> Maybe (List a)

Extract the rest of the list.

tail [ 1, 2, 3 ] == Just [ 2, 3 ]


tail [] == Nothing
init : List a -> Maybe (List a)

Return 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 [] == Nothing
uncons : List a -> Maybe ( a, List a )

Decompose 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 [] == Nothing
unsnoc : List a -> Maybe ( List a, a )

Decompose 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 [] == Nothing
singleton : a -> List a

Create a list with only one element

null : List a -> Bool

Determine whether a list is empty.

null [] == True


null [ 1 ] == False

Alias of isEmpty.

isEmpty : List a -> Bool

Determine if a list is empty.

isEmpty [] == True
length : List a -> Int

Determine the length of a list.

length [ 1, 2, 3 ] == 3
compareLength : List a -> Int -> Order

Compare 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 == LT

List transformations

map : (a -> b) -> List a -> List b

Apply 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 ]

map2 : (a -> b -> result) -> List a -> List b -> List result

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)]
map3 : (a -> b -> c -> result) -> List a -> List b -> List c -> List result
(a -> b -> c -> d -> result)
-> List a
-> List b
-> List c
-> List d
-> List result
(a -> b -> c -> d -> e -> result)
-> List a
-> List b
-> List c
-> List d
-> List e
-> List result
indexedMap : (Int -> a -> b) -> List a -> List b

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 : List a -> List a

Reverse a list.

reverse [ 1, 2, 3, 4 ] == [ 4, 3, 2, 1 ]
intersperse : a -> List a -> List a

Places the given value between all members of the given list.

intersperse "on" [ "turtles", "turtles", "turtles" ] == [ "turtles", "on", "turtles", "on", "turtles" ]
intercalate : List a -> List (List a) -> List a

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 : List (List a) -> List (List a)

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 ] ]
subsequences : List a -> List (List a)

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" ]
permutations : List a -> List (List a)

Return the list of all permutations of the argument. Note that the order of permutations is not lexicographic.

Properties

map (take n)
    (take (product (List.range 1 n)) (permutations (List.range 1 n)))
    == permutations (range 1 n)

Examples

permutations [ 1, 2 ] == [ [ 1, 2 ], [ 2, 1 ] ]


permutations [] == [ [] ]


let
    s =
        String.toList
in
permutations "abc" == [ "abc", "bac", "cba", "bca", "cab", "acb" ]
filterMap : (a -> Maybe b) -> List a -> List b

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]

Reducing lists

foldl : (a -> b -> b) -> b -> List a -> b

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 3
foldr : (a -> b -> b) -> b -> List a -> b

Reduce 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 1

Special folds

concat : List (List a) -> List a

Concatenate a bunch of lists into a single list:

concat [ [ 1, 2 ], [ 3 ], [ 4, 5 ] ] == [ 1, 2, 3, 4, 5 ]
concatMap : (a -> List b) -> List a -> List b

Map a given function onto a list and flatten the resulting lists.

concatMap f xs == concat (map f xs)
and : List Bool -> Bool

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 ] == False
or : List Bool -> Bool

Return 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 ] == True
any : (a -> Bool) -> List a -> Bool

Determine if any elements satisfy some test.

any isEven [ 2, 3 ] == True


any isEven [ 1, 3 ] == False


any isEven [] == False
all : (a -> Bool) -> List a -> Bool

Determine if all elements satisfy some test.

all isEven [ 2, 4 ] == True


all isEven [ 2, 3 ] == False


all isEven [] == True
sum : List number -> number

Get the sum of the list elements.

sum [ 1, 2, 3 ] == 6


sum [ 1, 1, 1 ] == 3


sum [] == 0
product : List number -> number

Get the product of the list elements.

product [ 2, 2, 2 ] == 8


product [ 3, 3, 3 ] == 27


product [] == 1
maximum : List comparable -> Maybe comparable

Find the maximum element in a non-empty list.

maximum [ 1, 4, 2 ] == Just 4


maximum [] == Nothing
minimum : List comparable -> Maybe comparable

Find the minimum element in a non-empty list.

minimum [ 3, 2, 1 ] == Just 1


minimum [] == Nothing

Building lists (Scans)

scanl : (a -> b -> b) -> b -> List a -> List b

The list of successive reduced values from the left.

scanl f z [x1, x2, ...] == [z, f x1 z, f x2 (f x1 z), ...]

Properties

last (scanl f z xs) == foldl f z xs

Examples

scanl (+) 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 ]
scanr : (a -> b -> b) -> b -> List a -> List b

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.

Examples

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" ]

Building lists (Accumulating maps)

mapAccumL : (s -> a -> ( s, b )) -> s -> List a -> ( s, List b )

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" ] )
mapAccumR : (s -> a -> ( s, b )) -> s -> List a -> ( s, List b )

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" ] )

Building lists (infinite lists)

iterate : Int -> (a -> a) -> a -> List a

n repeated applications f to x

Properties

iterate n f x == [x, f x, f (f x), ...]

Examples

iterate 3 ((+) 1) 0 == [ 0, 1, 2 ]
repeat : Int -> a -> List a

Create a list with n copies of a value:

repeat 3 ( 0, 0 ) == [ ( 0, 0 ), ( 0, 0 ), ( 0, 0 ) ]
range : Int -> Int -> List Int

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 == []
replicate : Int -> a -> List a

Alias to repeat

Building lists (Unfolding)

unfoldr : (b -> Maybe ( a, b )) -> b -> List a

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) == xs

if the following holds:

g (f x y) = Just (x,y)
g z       = Nothing

For example:

unfoldr
    (\b ->
        if b == 0 then
            Nothing


        else
            Just ( b, b - 1 )
    )
    10
    == [ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]

Sublists (Extracting sublists)

take : Int -> List a -> List a

Take the first n members of a list.

take 2 [ 1, 2, 3, 4 ] == [ 1, 2 ]
drop : Int -> List a -> List a

Drop the first n members of a list.

drop 2 [ 1, 2, 3, 4 ] == [ 3, 4 ]
splitAt : Int -> List a -> ( List a, List a )

Return a tuple where first element is xs prefix of length n and second element is the remainder of the list:

Examples

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 ] )
takeWhile : (a -> Bool) -> List a -> List a

Applied to a predicate p and a list xs, returns the longest prefix (possibly empty) of xs of elements that satisfy p.

Examples

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 ] == []
dropWhile : (a -> Bool) -> List a -> List a

Return the suffix remaining after takeWhile

Examples

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 ]
dropWhileEnd : (a -> Bool) -> List a -> List a

Drops the largest suffix of a list in which the given predicate holds for all elements.

Examples

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 ]
span : (a -> Bool) -> List a -> ( List a, List a )

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.

Examples

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 ] )
break : (a -> Bool) -> List a -> ( List a, List a )

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:

Properties

break p
    == span (not << p)
    == ( takeWhile (not << p) xs, dropWhile (not << p) xs )

Examples

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 ], [] )
stripPrefix : List a -> List a -> Maybe (List a)

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.

Examples

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")
    == Nothing
group : List a -> List (List a)

Return 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.

Examples

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 ] ]
inits : List a -> List (List a)

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.

Examples

inits (String.toList "abc")
    |> map String.fromList
    == [ "", "a", "ab", "abc" ]


inits [] == [ [] ]
tails : List a -> List (List a)

Return all final segments of the argument, longest first.

Examples

tails (String.toList "abc")
    |> map String.fromList
    == [ "abc", "bc", "c", "" ]


tails [ 1, 2, 3 ] == [ [ 1, 2, 3 ], [ 2, 3 ], [ 3 ], [] ]


tails [] == [ [] ]

Sublists (Predicates)

isPrefixOf : List a -> List a -> Bool

Takes two lists and returns True iff the first list is a prefix of the second.

Examples

isPrefixOf (String.toList "Hello") (String.toList "Hello World!") == True


isPrefixOf (String.toList "Hello") (String.toList "Wello Horld!") == False

isPrefixOf shortcuts when the first argument is empty:

forall x, isPrefixOf [] x == True
isSuffixOf : List a -> List a -> Bool

Takes two lists and returns True iff the first list is a suffix of the second.

Examples

isSuffixOf (String.toList "ld!") (String.toList "Hello World!") == True


isSuffixOf (String.toList "World") (String.toList "Hello World!") == False
isInfixOf : List a -> List a -> Bool

Takes two lists and returns True iff the first list is contained, wholly and intact, anywhere within the second.

Examples

isInfixOf (String.toList "Haskell")
    (String.toList "I really like Haskell.")
    == True


isInfixOf (String.toList "Ial")
    (String.toList "I really like Haskell.")
    == False
isSubsequenceOf : List a -> List a -> Bool

Return True if all the elements of the first list occur, in order, in the second. The elements do not have to occur consecutively.

Properties

isSubsequenceOf x y == elem x (subsequences y)

Note:

isSubsequenceOf is often used in infix form.

Examples

isSubsequenceOf (String.toList "GHC")
    (String.toList "The Glorious Haskell Compiler") == True
isSubsequenceOf ['a'..'z'] == True
isSubsequenceOf [1..10] [10,9..0] == False

Searching lists (Searching by equality)

elem : a -> List a -> Bool

Does the element occur in the structure?

Note:

elem is often used in infix form.

Examples

elem 3 [] == False


elem 3 [ 1, 2 ] == False


elem 3 [ 1, 2, 3, 4, 5 ] == True
notElem : a -> List a -> Bool

The negation of elem.

Examples

notElem 3 [] == True


notElem 3 [ 1, 2 ] == True


notElem 3 [ 1, 2, 3, 4, 5 ] == False
lookup : a -> List ( a, b ) -> Maybe b

Looks up the value associated with the key in an association list.

Examples

lookup 2 [] == Nothing


lookup 2 [ ( 1, "first" ) ] == Nothing


lookup 2 [ ( 1, "first" ), ( 2, "second" ), ( 3, "third" ) ]
    == Just "second"
member : a -> List a -> Bool

Figure out whether a list contains a value.

member 9 [ 1, 2, 3, 4 ] == False


member 4 [ 1, 2, 3, 4 ] == True

Searching lists (Searching with a predicate)

find : (a -> Bool) -> List a -> Maybe a

Return the leftmost element of the list matching the predicate, or Nothing if there is no such element.

Examples

find (\x -> x > 42) [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50 ] == Just 45


find (\x -> x > 12) (range 1 7) == Nothing
filter : (a -> Bool) -> List a -> List a

Keep elements that satisfy the test.

filter isEven [ 1, 2, 3, 4, 5, 6 ] == [ 2, 4, 6 ]
partition : (a -> Bool) -> List a -> ( List a, List a )

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 ] )

Indexing lists

elemIndex : a -> List a -> Maybe Int

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.

Examples

elemIndex 4 (range 0 10) == Just 4


elemIndex 'o' (String.toList "haskell") == Nothing
elemIndices : a -> List a -> List Int

Return the indicies of all elements equal to the query element, in ascending order.

Examples

elemIndices 'o' (String.toList "Hello World") == [ 4, 7 ]


elemIndices 1 [ 1, 2, 3, 1, 2, 3 ] == [ 0, 3 ]
findIndex : (a -> Bool) -> List a -> Maybe Int

Return the index of the first element in the list satisfying the predicate, or Nothing if there is no such element.

Examples

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 1
findIndices : (a -> Bool) -> List a -> List Int

Extends findIndex, by returning the indices of all elements satisfying the predicate, in ascending order.

Examples

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 ]

Zipping and unzipping lists

zip : List a -> List b -> List ( a, b )

Return a list of corresponding pairs.

Examples

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 ] [] == []
zip3 : List a -> List b -> List c -> List ( a, b, c )

Return a list of triples, analogous to zip.

zipWith : (a -> b -> c) -> List a -> List b -> List c

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 [] [ () ] == []

Examples

zipWith (+) [ 1, 2, 3 ] [ 4, 5, 6 ] == [ 5, 7, 9 ]


zipWith (++) [ "hello ", "foo" ] [ "world!", "bar" ]
    == [ "hello world!", "foobar" ]
zipWith3 : (a -> b -> c -> d) -> List a -> List b -> List c -> List d

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 ]

Examples

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 ]
unzip : List ( a, b ) -> ( List a, List b )

Decompose a list of tuples into a tuple of lists.

unzip [ ( 0, True ), ( 17, False ), ( 1337, True ) ] == ( [ 0, 17, 1337 ], [ True, False, True ] )
unzip3 : List ( a, b, c ) -> ( List a, List b, List c )

Takes a list of triples and returns three lists of the respective components, analogous to unzip.

Examples

unzip3 [] == ( [], [], [] )


unzip3 [ ( 1, 'a', True ), ( 2, 'b', False ) ]
    == ( [ 1, 2 ], [ 'a', 'b' ], [ True, False ] )

Special lists ("Set" operations)

nub : List a -> List a

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.

Examples

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!"
delete : a -> List a -> List a

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.

Examples

delete 'a' (String.toList "banana") |> String.fromList == "bnana"


delete "not" [ "haskell", "is", "not", "awesome" ] == [ "haskell", "is", "awesome" ]
deleteFirsts : List a -> List a -> List a

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.

Examples

delete (String.toList "Hello World!") (String.toList "ell W")
    |> String.fromList
    == "Hoorld!"
union : List a -> List a -> List a

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.

Examples

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"
intersect : List a -> List a -> List a

Takes the list intersection of two lists. It is a special case of intersectBy, which allows the programmer to supply their own equality test.

Examples

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"

Special lists (Ordered lists)

sort : List comparable -> List comparable

Sort values from lowest to highest

sort [ 3, 1, 5 ] == [ 1, 3, 5 ]
sortOn : (a -> comparable) -> List a -> List a

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.

Examples

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" ]
insert : comparable -> List comparable -> List comparable

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.

Examples

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 ]

Generalized functions (The "By" operations)

nubBy : (a -> a -> Bool) -> List a -> List a

Behaves just like nub, except it uses a user-supplied equality predicate.

Examples

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 ]
deleteBy : (a -> a -> Bool) -> a -> List a -> List a

Behaves like delete, but takes a user-supplied equality predicate.

Examples

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 ]
deleteFirstsBy : (a -> a -> Bool) -> List a -> List a -> List a

Return the first list with the first occurrence of each element of the second list removed.

Properties

deleteFirsts == deleteFirstsBy (==)

Examples

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 ]
unionBy : (a -> a -> Bool) -> List a -> List a -> List a

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"]

Examples

unionBy (>) [ 3, 4, 5 ] [ 1, 2, 3, 4, 5, 6 ] == [ 3, 4, 5, 4, 5, 6 ]
intersectBy : (a -> a -> Bool) -> List a -> List a -> List a

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"]
groupBy : (a -> a -> Bool) -> List a -> List (List a)

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 ]
       ]

Examples

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]]

Generalized functions (User-supplied comparison)

sortBy : (a -> a -> Order) -> List a -> List a

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"]
sortWith : (a -> a -> Order) -> List a -> List a

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 -> LT

This is also the most general sort function, allowing you to define any other: sort == sortWith compare

insertBy : (a -> a -> Order) -> a -> List a -> List a

Insert a value into a list using the given ordering function.

Examples

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 ] ]
maximumBy : (a -> a -> Order) -> List a -> Maybe a

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.

Examples

maximumBy (\x y -> compare (String.length x) (String.length y))
    [ "Hello", "World", "!", "Longest", "bar" ]
    == Just "Longest"
minimumBy : (a -> a -> Order) -> List a -> Maybe a

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.

Examples

minimumBy (\x y -> compare (String.length x) (String.length y))
    [ "Hello", "World", "!", "Longest", "bar" ]
    == Just "!"

Generalized functions (The "generic" operations)

genericLength : List a -> number

An overloaded version of length. In particular, instead of returning an Int, it returns Float type.

Examples

(genericLength [ 1, 2, 3 ] == 3) == True


(genericLength [ 1, 2, 3 ] == 3.0) == True