Eager, persistent, singly-linked lists.

All operations are recursive over cons cells; mutation is not possible. Helpers come in five flavours: queries, access, construction, transformations, and search. Everything is polymorphic in the element type T.

Examples

cure
use Std.List

let xs = [1, 2, 3, 4, 5]
length(xs)                                # => 5
map(xs, fn(x) -> x * x)                   # => [1, 4, 9, 16, 25]
filter(xs, fn(x) -> x % 2 == 0)           # => [2, 4]
cure
use Std.List

# Sum of squares of positive integers up to 10
let r = (1..11)                           # [1..10]
          |> filter(fn(x) -> x > 0)
          |> map(fn(x) -> x * x)
          |> sum
# r => 385
cure
use Std.List

match uncons([1, 2, 3])
  Some(p) -> Std.Io.print_int(p.1)         # prints 1
  None()  -> Std.Io.println("empty")

Types

  • type List = Nil | Cons

    Group tag consumed by Cure.Stdlib.Preload. The canonical cons-list family. Seeded programmatically into every module (so []/[h | t] literal sugar resolves without use), and declared here with the builtin decorator; builtin_list_drift_test.exs pins the two equal.

Functions

  • # fn all(list: List(t), pred: Function(t, Bool)) -> Bool

    true when every element satisfies pred (vacuously true for []).

  • # fn any(list: List(t), pred: Function(t, Bool)) -> Bool

    true when at least one element satisfies pred.

  • # fn append(a: List(t), b: List(t)) -> List(t)

    Concatenate two lists. Linear in length(a).

  • # fn at(list: List(t), idx: Int) -> Option(t)

    0-based lookup as an Option: Some(element) when 0 <= idx < length, None() otherwise (past either end, on [], or a negative index). The total, honest counterpart to nth/3 — no default to invent. Structural recursion; a negative index falls off the end and yields None().

  • # fn concat(lists: List(List(t))) -> List(t)

    Concatenate a list of lists into a single flat list.

  • # fn cons(elem: t, list: List(t)) -> List(t)

    Prepend elem onto list (the Cure-level spelling of [elem | list]).

  • # fn contains(list: List(t), elem: t) -> Bool

    true when elem appears in list (structural equality). The requires Equatable(t) constraint threads the dictionary that dispatches the h == elem comparison at the element type.

  • # fn count(list: List(t), pred: Function(t, Bool)) -> Int

    Count of elements satisfying pred.

  • # fn drop(list: List(t), n: Int) -> List(t)

    Drop the first n elements; returns list unchanged when n <= 0.

  • # fn filter(list: List(t), pred: Function(t, Bool)) -> List(t)

    Keep elements of list for which pred(elem) returns true.

  • # fn find(list: List(t), pred: Function(t, Bool), default: t) -> t

    First element satisfying pred; returns default when nothing matches.

  • # fn flat_map(list: List(t), f: Function(t, List(u))) -> List(u)

    Map f over list and flatten one level of nesting.

  • # fn foldl(list: List(t), acc: u, f: Function(t, Function(u, u))) -> u

    Left fold. f is curried: f(elem)(acc) -> acc. Reduces list starting from the head.

  • # fn foldr(list: List(t), acc: u, f: Function(t, Function(u, u))) -> u

    Right fold. f is curried: f(elem)(acc) -> acc. Builds up the result from the tail toward the head; not tail-recursive, so expect O(length) stack on very long lists.

  • # fn head(list: List(t), default: t) -> t

    First element of list; returns default when empty.

  • # fn is_empty(list: List(t)) -> Bool

    true when list has no elements.

  • # fn last(list: List(t), default: t) -> t

    Last element of list; returns default when empty.

  • # fn length(list: List(t)) -> Int extern

    Length of list as an Int. Delegates to :erlang.length/1.

  • # fn map(list: List(t), f: Function(t, u)) -> List(u)

    Map f over every element of list.

  • # fn nth(list: List(t), idx: Int, default: t) -> t

    0-based random access. Returns default when idx is out of range.

  • # fn product(list: List(Int)) -> Int

    Product of an Int list, left-folded.

  • # fn reverse(list: List(t)) -> List(t)

    Reverse list; tail-recursive via a private accumulator.

  • # fn set_at(list: List(t), idx: Int, value: t) -> List(t)

    Replace the element at idx with value when 0 <= idx < length; return list unchanged otherwise (past either end, on [], or a negative index). Total; structural recursion. This is the putter half of the ix affine.

  • # fn split_first(list: List(t), default: t) -> Tuple(t, List(t))

    Like uncons/1, but substitutes default for the head when empty, so the result is always a %[head, tail] pair.

  • # fn sum(list: List(Int)) -> Int

    Sum of an Int list, left-folded.

  • # fn tail(list: List(t)) -> List(t)

    All-but-the-first elements of list; empty list yields [].

  • # fn take(list: List(t), n: Int) -> List(t)

    First n elements; [] when n <= 0.

  • # fn uncons(list: List(t)) -> Option(Tuple(t, List(t)))

    Split list into Some(%[head, tail]), or None() when empty.

  • # fn zip_with(a: List(t), b: List(u), f: Function(t, Function(u, v))) -> List(v)

    Combine two lists element-wise using f. Stops at the shorter list. f is curried: f(a)(b) -> c.