# List

Standard library for list operations.

Functions in this module operate on type `[A]`

(equivalent to `List<A>`

),
which represents a linked list with `O(1)`

`put()`

and `O(n)`

`at()`

and `delete()`

. Literal lists can be created with
the syntax `[a, b, ...]`

, where `a`

, `b`

, etc. are elements.

To import all names from this module, use:

import List (*)

With no import, you can still access anything with the prefix `List.`

, like `List.at`

.

## Index

Name | Type | Description |
---|---|---|

[A] -> A | Returns the first element in the list | |

[A] -> [A] | Returns a list containing all elements in | |

[A] -> Int | Returns the length of | |

[A] -> Bool | Returns whether | |

([A], [A]) -> [A] | Concatenates | |

[[A]] -> [A] | Concatenates all elements in the list | |

([A], A -> B) -> [B] | Calls | |

([A], Int) -> A | Returns the element at index | |

([A], Int, Int) -> [A] | Returns a sublist of | |

([A], Int, Int) -> [A] | Returns a sublist of | |

([A], Int) -> ([A], [A]) | Returns two lists: the first contains all elements from index | |

([A], Int) -> [A] | Takes | |

([A], Int) -> [A] | Drops | |

([A], A -> Bool) -> [A] | Takes elements from | |

([A], A -> Bool) -> [A] | Drops elements from | |

([A], A -> Bool) -> ([A], [A]) | Takes elements from | |

([A], A -> Bool) -> ([A], [A]) | Returns two new lists: one containing elements for which | |

[A] -> [A] | Reverses the list | |

([A], A -> [B]) -> [B] | Calls | |

([A], F, (F, A) -> F) -> F | Same as | |

([A], F, (F, A) -> (F, B)) -> (F, [B]) | Same as | |

[A ~ Num] -> A ~ Num | Returns the sum of all numbers in | |

[A ~ Ord] -> [A ~ Ord] | Sorts | |

([A], A -> B ~ Ord) -> [A] | Sorts | |

([A], (A, A) -> Bool) -> [A] | Sorts | |

([String], String) -> String | Joins the list of strings | |

[A ~ Ord] -> Option<A ~ Ord> | Returns the maximum element in | |

[A ~ Ord] -> Option<A ~ Ord> | Returns the minimum element in | |

([A], A -> B ~ Ord) -> Option<A> | Returns the element in | |

([A], A -> B ~ Ord) -> Option<A> | Returns the element in | |

(Int, Int) -> [Int] | Returns a list containing the sequence of integers from | |

(A, Int) -> [A] | Creates a new list that has the element | |

([A], [B]) -> [(A, B)] | Returns a list where the | |

[(A, B)] -> ([A], [B]) | Unpacks a list of tuples | |

([A], A -> B) -> Map<B, [A]> | Calls | |

[A] -> [A] | Removes duplicates in | |

([A], A -> B) -> [A] | Removes duplicates in | |

[A] -> [(A, Int)] | Pairs each element in | |

([A], A -> B) -> () | Calls | |

([A], F, (F, A) -> F) -> F | Computes a single value by applying the combining function | |

([A], A -> Bool) -> [A] | Calls | |

([A], A -> Bool) -> Option<A> | Returns the first element in | |

([A], A -> Option<B>) -> [B] | Calls | |

([A], F, (F, A) -> (F, B)) -> (F, [B]) | Computes a new collection and a single value by applying the combining
function | |

([A], A) -> [A] | Puts | |

([A], A) -> [A] | Removes | |

([A], A) -> Bool | Returns true if | |

([A], A -> Bool) -> Bool | Calls | |

([A], A -> Bool) -> Bool | Calls | |

[A] -> Set<A> | Converts | |

[(K, V)] -> Map<K, V> | Converts |

## Functions

head : [A] -> A head(l)

Returns the first element in the list `l`

. Raises `EmptyList`

if `l`

is empty.

This function is part of the `Base`

module, meaning it's a builtin that's in the global namespace, so it doesn't need to be imported.

assert head([1]) == 1 assert head(["hi", "hey", "hello"]) == "hi"

tail : [A] -> [A] tail(l)

Returns a list containing all elements in `l`

except the first. Raises
`EmptyList`

if `l`

is empty.

This function is part of the `Base`

module, meaning it's a builtin that's in the global namespace, so it doesn't need to be imported.

assert tail([1]) == [] assert tail(["hi", "hey", "hello"]) == ["hey", "hello"]

at : ([A], Int) -> A at(l, i)

Returns the element at index `i`

in `l`

. `i`

can be negative, where `-1`

is
the last index, `-2`

is the second-to-last index, etc. If `at`

tries to
access an element at an invalid index, it raises
`BadListIndex`

.

assert at(["cow", "dog", "cat"], 0) == "cow" assert at(["cow", "dog", "cat"], -1) == "cat" assert at([42.3, .428, 13.3], 2) == 13.3 assert at([42.3, .428, 13.3], -3) == 42.3

slice : ([A], Int, Int) -> [A] slice(l, i, len)

Returns a sublist of `l`

starting at index `i`

with length `len`

. `i`

can
be negative, where `-1`

is the last index, `-2`

is the second-to-last index,
etc. If `len <= 0`

, returns `[]`

. If `slice`

tries to access an element at an
invalid index, it raises `BadListIndex`

.

assert slice(["cow", "dog", "cat"], 0, 2) == ["cow", "dog"] assert slice(["cow", "dog", "cat"], -1, 1) == ["cat"] assert slice(["cow", "dog", "cat"], 3, 0) == [] assert slice([42.3, .428, 13.3], -3, 2) == [42.3, .428]

range : ([A], Int, Int) -> [A] range(l, start, end)

Returns a sublist of `l`

starting at index `start`

and ending at index
`end`

, inclusive. `start`

and `end`

can be negative, where `-1`

is the last
index, `-2`

is the second-to-last index, etc. If `start > end`

(after
resolving negative indexes), returns `[]`

. If `range`

tries to access an
element at an invalid index, it raises `BadListIndex`

.

assert range(["cow", "dog", "cat"], 0, 1) == ["cow", "dog"] assert range(["cow", "dog", "cat"], -1, 2) == ["cat"] assert range(["cow", "dog", "cat"], 3, 1) == [] assert range([42.3, .428, 13.3], -3, 1) == [42.3, .428]

split_at : ([A], Int) -> ([A], [A]) split_at(l, i)

Returns two lists: the first contains all elements from index `0`

to `i - 1`

,
and the second contains all elements from index `i`

to the end of the list.
`i`

can be negative, where `-1`

is the last index, `-2`

is the second-to-last
index, etc. If `split_at`

tries to access an element at an invalid index, it
raises `BadListIndex`

.

assert split_at(["cow", "dog", "cat"], 0) == ([], ["cow", "dog", "cat"]) assert split_at(["cow", "dog", "cat"], -1) == (["cow", "dog"], ["cat"]) assert split_at([42.3, .428, 13.3], 2) == ([42.3, .428], [13.3]) assert split_at([42.3, .428, 13.3], -3) == ([], [42.3, .428, 13.3])

take : ([A], Int) -> [A] take(l, n)

Takes `n`

elements from the beginning of `l`

, returning a new list. If `l`

has fewer than `n`

elements, returns `l`

. If `n`

is negative, returns `[]`

.

assert take(["cow", "dog", "cat"], 2) == ["cow", "dog"] assert take(["cow", "dog", "cat"], 10) == ["cow", "dog", "cat"] assert take(["cow", "dog", "cat"], 0) == [] assert take(["cow", "dog", "cat"], -3) == []

drop : ([A], Int) -> [A] drop(l, n)

Drops `n`

elements from the beginning of `l`

, returning a new list. If `l`

has fewer than `n`

elements, returns `[]`

. If `n`

is negative, returns `l`

.

assert drop(["cow", "dog", "cat"], 2) == ["cat"] assert drop(["cow", "dog", "cat"], 10) == [] assert drop(["cow", "dog", "cat"], 0) == ["cow", "dog", "cat"] assert drop(["cow", "dog", "cat"], -3) == ["cow", "dog", "cat"]

take_while : ([A], A -> Bool) -> [A] take_while(l, f)

Takes elements from `l`

while `f`

returns true, returning a new list. `f`

accepts an element and returns true to take it or false to stop.

assert take_while(["cow", "dog", "cat"], |a| a < "d") == ["cow"] assert take_while(["cow", "dog", "cat"], |a| a > "e") == [] assert take_while([42.3, .428, 13.3], |a| a < 50) == [42.3, .428, 13.3] assert take_while([], |_| true) == []

drop_while : ([A], A -> Bool) -> [A] drop_while(l, f)

Drops elements from `l`

while `f`

returns true, returning a new list. `f`

accepts an element and returns true to take it or false to stop.

assert drop_while(["cow", "dog", "cat"], |a| a < "d") == ["dog", "cat"] assert drop_while(["cow", "dog", "cat"], |a| a > "e") == ["cow", "dog", "cat"] assert drop_while([42.3, .428, 13.3], |a| a < 50) == [] assert drop_while([], |_| true) == []

split_while : ([A], A -> Bool) -> ([A], [A]) split_while(l, f)

Takes elements from `l`

while `f`

returns true, and returns two new lists:
the elements that were taken, and all remaining elements.

assert split_while(["cow", "dog", "cat"], |a| a < "d") == (["cow"], ["dog", "cat"]) assert split_while(["cow", "dog", "cat"], |a| a > "e") == ([], ["cow", "dog", "cat"]) assert split_while([42.3, .428, 13.3], |a| a < 50) == ([42.3, .428, 13.3], []) assert split_while([], |_| true) == ([], [])

partition : ([A], A -> Bool) -> ([A], [A]) partition(l, f)

Returns two new lists: one containing elements for which `f`

returns true,
and the other containing elements for which `f`

returns false.

assert partition(["cow", "dog", "cat"], |a| a < "d") == (["cow", "cat"], ["dog"]) assert partition(["cow", "dog", "cat"], |a| a > "e") == ([], ["cow", "dog", "cat"]) assert partition([42.3, .428, 13.3], |a| a < 1) == ([.428], [42.3, 13.3]) assert partition([], |a| true) == ([], [])

reverse : [A] -> [A] reverse(l)

Reverses the list `l`

.

assert reverse(["cow", "dog", "cat"]) == ["cat", "dog", "cow"] assert reverse([42.3, .428, 13.3]) == [13.3, .428, 42.3] assert reverse([]) == []

flat_map : ([A], A -> [B]) -> [B] flat_map(l, f)

Calls `f`

for each element in `l`

, concatenating the resultant lists together
into one list. `f`

accepts an element in `l`

and returns a list.

assert flat_map([42.3, .428, 13.3], |a| [a, a + 0.1]) == [42.3, 42.4, .428, .528, 13.3, 13.4] assert flat_map([42.3, .428, 13.3], |a| [a]) == [42.3, .428, 13.3] assert flat_map(["cow", "dog", "cat"], String.to_chars) == String.to_chars("cowdogcat") assert flat_map([], |a| [a]) == []

foldr : ([A], F, (F, A) -> F) -> F foldr(l, init, f)

Same as `fold`

, expect that it goes through `l`

in the reverse
order, calling `f`

with the last element, then the second-to-last element,
etc.

assert foldr(["cow", "dog", "cat"], "turtle", |accum, a| accum ++ a) == "turtlecatdogcow" assert foldr([42.3, .428, 13.3], 5, |accum, a| -accum + a) == 50.172 assert foldr([], true, |accum, a| accum && a) == true

foldr_map : ([A], F, (F, A) -> (F, B)) -> (F, [B]) foldr_map(l, init, f)

Same as `fold_map`

, expect that it goes through `l`

in the
reverse order, calling `f`

with the last element, then the second-to-last
element, etc. The resulting mapped list is still in the same order as the
original list.

let l = ["cow", "dog", "cat"] assert foldr_map(l, "turtle", |accum, a| (accum ++ "!" ++ a, a ++ "!")) == ("turtle!cat!dog!cow", ["cow!", "dog!", "cat!"]) let l = [42, .4, 13.3] assert foldr_map(l, 5, |accum, a| (-accum + a, accum)) == (49.9, [-7.9, 8.3, 5]) assert foldr_map([], true, |accum, a| (accum && a, accum)) == (true, [])

sum : [A ~ Num] -> A ~ Num sum(l)

Returns the sum of all numbers in `l`

.

assert sum([5, 9, -37]) == -23 assert sum([42.3, .4, 13.3]) == 56.0 assert sum([]) == 0

sort : [A ~ Ord] -> [A ~ Ord] sort(l)

Sorts `l`

in ascending order. `l`

is expected to contain elements that
satisfy the `Ord`

interface, meaning they have
a defined ordering.

assert sort(["cow", "dog", "cat"]) == ["cat", "cow", "dog"] assert sort([42.3, .428, 13.3]) == [.428, 13.3, 42.3] assert sort([]) == []

sort_by : ([A], A -> B ~ Ord) -> [A] sort_by(l)

Sorts `l`

in ascending order based on the return value of `f`

for each
element. The element for which `f`

returns the minimum value is first, and
the element for which `f`

returns the maximum value is last. `f`

accepts an
element as an argument and returns a value that satisfies the
`Ord`

interface, which has a defined ordering.

assert sort_by([42.3, .428, 13.3], |a| -a) == [42.3, 13.3, .428] let f(a) = String.to_chars(a) |> at(2) |> to_int assert sort_by(["cow", "dog", "cat"], f) == ["dog", "cat", "cow"] assert sort_by([], |a| a) == []

sort_cmp : ([A], (A, A) -> Bool) -> [A] sort_cmp(l, f)

Sorts `l`

in ascending order based on the comparator function `f`

. `f`

is
called with two elements `a`

and `b`

, and the comparator should return true
if `a`

must be placed before `b`

in the sorted list.

assert sort_cmp([42.3, .428, 13.3], |a, b| a < b) == [.428, 13.3, 42.3] let key(s) = String.to_chars(s) |> at(2) |> to_int let f(a, b) = key(a) > key(b) assert sort_cmp(["cow", "dog", "cat"], f) == ["cow", "cat", "dog"] assert sort_cmp([], |a, b| a < b) == []

join : ([String], String) -> String join(l, sep)

Joins the list of strings `l`

with the separator `sep`

, returning a string.
`sep`

is placed in-between every two subsequent elements of `l`

.

assert join(["cow", "dog", "cat"], "") == "cowdogcat" assert join(["cow", "dog", "cat"], ", ") == "cow, dog, cat" assert join([], ", ") == ""

max_in : [A ~ Ord] -> Option<A ~ Ord> max_in(l)

Returns the maximum element in `l`

as `Some(max)`

, or
`None`

if `l`

is empty. `l`

is expected to contain elements
that satisfy the `Ord`

interface, meaning they
have a defined ordering.

assert max_in(["cow", "dog", "cat"]) == Some("dog") assert max_in([42.3, .428, 13.3]) == Some(42.3) assert max_in([]) == None

min_in : [A ~ Ord] -> Option<A ~ Ord> min_in(l)

Returns the minimum element in `l`

as `Some(min)`

, or
`None`

if `l`

is empty. `l`

is expected to contain elements
that satisfy the `Ord`

interface, meaning they
have a defined ordering.

assert min_in(["cow", "dog", "cat"]) == Some("cat") assert min_in([42.3, .428, 13.3]) == Some(.428) assert min_in([]) == None

max_by : ([A], A -> B ~ Ord) -> Option<A> max_by(l, f)

Returns the element in `l`

for which `f`

returns the maximum value. `f`

accepts an element as an argument and returns a value that satisfies the
`Ord`

interface, which has a defined ordering.

assert max_by(["cow", "dog", "turtle"], |l| length(l)) == Some("turtle") assert max_by([42.3, .428, 13.3], |l| -l) == Some(.428) assert max_by([], |l| l) == None

min_by : ([A], A -> B ~ Ord) -> Option<A> min_by(l, f)

Returns the element in `l`

for which `f`

returns the minimum value. `f`

accepts an element as an argument and returns a value that satisfies the
`Ord`

interface, which has a defined ordering.

assert min_by(["cow", "dog", "turtle"], |l| length(l)) == Some("cow") assert min_by([42.3, .428, 13.3], |l| -l) == Some(42.3) assert min_by([], |l| l) == None

seq : (Int, Int) -> [Int] seq(start, end)

Returns a list containing the sequence of integers from `start`

to `end`

,
both inclusive. If `start > end`

, returns `[]`

.

assert seq(0, 3) == [0, 1, 2, 3] assert seq(-3, 1) == [-3, -2, -1, 0, 1] assert seq(5, 5) == [5] assert seq(2, 1) == []

repeat : (A, Int) -> [A] repeat(a, n)

Creates a new list that has the element `a`

repeated `n`

times.

assert repeat("hi", 3) == ["hi", "hi", "hi"] assert repeat('h', 1) == ['h'] assert repeat(true, 0) == []

zip : ([A], [B]) -> [(A, B)] zip(l1, l2)

Returns a list where the `i`

-th element is a tuple containing the `i`

-th
element of `l1`

and the `i`

-th element of `l2`

. If `l1`

and `l2`

don't have
the same length, raises `MismatchedLengths`

. See
`unzip()`

for the opposite operation.

assert zip(["cow", "dog", "cat"], [42.3, .428, 13.3]) == [("cow", 42.3), ("dog", .428), ("cat", 13.3)] assert zip([@hi], ['h']) == [(@hi, 'h')] assert zip([], []) == []

unzip : [(A, B)] -> ([A], [B]) unzip(l)

Unpacks a list of tuples `l`

into two separate lists. If the `i`

-th element
of `l`

is a tuple `(a, b)`

, the `i`

-th element of the first result list is
`a`

, and the `i`

-th element of the second result list is `b`

. See
`zip()`

for the opposite operation.

assert unzip([("cow", 42.3), ("dog", .428), ("cat", 13.3)]) == (["cow", "dog", "cat"], [42.3, .428, 13.3]) assert unzip([(@hi, 'h')]) == ([@hi], ['h']) assert unzip([]) == ([], [])

group_by : ([A], A -> B) -> Map<B, [A]> group_by(l, f)

Calls `f`

on each element of `l`

, returning a map from each return value of
`f`

to the list of elements that gave that return value.

assert group_by(["turtle", "dog", "cat"], |a| length(a)) == { 6 => ["turtle"], 3 => ["dog", "cat"] } assert group_by([42.3, .428, 13.3], |a| a > 10) == { true => [42.3, 13.3], false => [.428] } assert group_by([42.3, .428, 13.3], |a| a) == { 42.3 => [42.3], .428 => [.428], 13.3 => [13.3] } assert group_by( ["cow", "dog", "cat"], |a| String.to_chars(a) |> head ) == { 'c' => ["cow", "cat"], 'd' => ["dog"] }

unique : [A] -> [A] unique(l)

Removes duplicates in `l`

, returning a new list. `l`

is not modified.

assert unique(["cow", "dog", "cat"]) == ["cow", "dog", "cat"] assert unique(["cow", "dog", "cow"]) == ["cow", "dog"] assert unique([42.3, .428, 13.3, .428]) == [42.3, .428, 13.3] assert unique([]) == []

unique_by : ([A], A -> B) -> [A] unique_by(l, f)

Removes duplicates in `l`

, returning a new list, where two elements are
duplicates if `f`

returns the same value for them. `l`

is not modified.

assert unique_by([42.3, .428, 13.3], |a| a > 10) == [42.3, .428] assert unique_by([42.3, .428, 13.3], |a| true) == [42.3] assert unique_by( ["cow", "dog", "cat"], |a| String.to_chars(a) |> head ) == ["cow", "dog"] assert unique_by([], |a| a) == []

with_index : [A] -> [(A, Int)] with_index(l)

Pairs each element in `l`

with its index, returning a new list of tuples.

assert with_index(["cow", "dog", "cat"]) == [("cow", 0), ("dog", 1), ("cat", 2)] assert with_index([42.3]) == [(42.3, 0)] assert with_index([]) == []

each : ([A], A -> B) -> () each(l, f)

Calls `f`

on each element of `l`

. This function rarely needs to be used, and
is only necessary when performing a side-effect (e.g. printing, writing to
a file, etc.) for each element in a list. In most cases, what you really want
is a specific operation like `map()`

, `filter()`

, or
`fold()`

.

// prints each element each([1, 2, 3], |e| print("element: " ++ e))

## Implementations

impl Sized for [A]

The following functions are from the `Sized`

interface.

length : [A] -> Int length(sized)

Returns the length of `sized`

. See the full description in the `Sized`

interface.

empty? : [A] -> Bool empty?(sized)

Returns whether `sized`

is empty. See the full description in the `Sized`

interface.

impl Concat for [A]

The following functions are from the `Concat`

interface.

concat : ([A], [A]) -> [A] concat(a, b)

Concatenates `a`

and `b`

together, equivalent to `a ++ b`

. See the full description in the `Concat`

interface.

concat_all : [[A]] -> [A] concat_all(l)

Concatenates all elements in the list `l`

together. See the full description in the `Concat`

interface.

impl Mappable for List

The following functions are from the `Mappable`

interface.

map : ([A], A -> B) -> [B] map(container, f)

Calls `f`

for each element in `container`

, collecting the results into
a new container. See the full description in the `Mappable`

interface.

impl Collection for List

The following functions are from the `Collection`

interface.

fold : ([A], F, (F, A) -> F) -> F fold(collection, init, f)

Computes a single value by applying the combining function `f`

to each
element of the given `collection`

, starting with the initial value `init`

. See the full description in the `Collection`

interface.

filter : ([A], A -> Bool) -> [A] filter(collection, f)

Calls `f`

for each element in `collection`

, returning a new collection
that only contains the elements for which `f`

returns true. See the full description in the `Collection`

interface.

find : ([A], A -> Bool) -> Option<A> find(collection, f)

Returns the first element in `collection`

for which `f`

returns true. See the full description in the `Collection`

interface.

filter_map : ([A], A -> Option<B>) -> [B] filter_map(collection, f)

Calls `f`

for each element in `collection`

, returning a new collection
that contains every `e`

such that `f`

returned `Some(e)`

. See the full description in the `Collection`

interface.

fold_map : ([A], F, (F, A) -> (F, B)) -> (F, [B]) fold_map(collection, init, f)

Computes a new collection and a single value by applying the combining
function `f`

to each element of the given `collection`

, starting with the
initial value `init`

. See the full description in the `Collection`

interface.

put : ([A], A) -> [A] put(collection, elem)

Puts `elem`

into `collection`

, returning a new collection. See the full description in the `Collection`

interface.

delete : ([A], A) -> [A] delete(collection, elem)

Removes `elem`

from `collection`

, returning a new collection. See the full description in the `Collection`

interface.

contains? : ([A], A) -> Bool contains?(collection, elem)

Returns true if `collection`

contains `elem`

. See the full description in the `Collection`

interface.

all? : ([A], A -> Bool) -> Bool all?(collection, f)

Calls `f`

for each element in `collection`

, and returns true if `f`

returns true for **every** element. See the full description in the `Collection`

interface.

any? : ([A], A -> Bool) -> Bool any?(collection, f)

Calls `f`

for each element in `collection`

, and returns true if `f`

returns true for **at least one** element. See the full description in the `Collection`

interface.

impl ToSet for List

The following functions are from the `ToSet`

interface.

to_set : [A] -> Set<A> to_set(a)

Converts `a`

to a set. See the full description in the `ToSet`

interface.

impl ToMap for List

The following functions are from the `ToMap`

interface.

to_map : [(K, V)] -> Map<K, V> to_map(a)

Converts `a`

to a map. See the full description in the `ToMap`

interface.

## Exceptions

exception BadListIndex(Int)

Raised by `at()`

, `split_at()`

, `slice()`

, and
`range()`

when accessing an index out of bounds.

exception MismatchedLengths(Int, Int)

Raised by `zip()`

when the two lists don't have the same lengths.