of :: a -> Array a
Lifts a single value into a singleton array — the Applicative `pure`/`return`
for Array. Used by `traverse`, `mapM`, and other Applicative/Monad combinators
whenever a plain value needs to be promoted into the Array context.
Combine with `chain` or `ap` to build larger array computations.
of ('Alice')
// => ['Alice']
of (42)
// => [42]
empty :: () -> Array a
Returns a new empty array — the Monoid identity element for Array.
Because `concat (empty ()) (xs)` and `concat (xs) (empty ())` both equal `xs`,
`empty` is the safe neutral starting point for any accumulation.
Use it wherever an "initial value" of type `Array a` is needed.
empty ()
// => []
range :: Integer -> Integer -> Array Integer
Generates the half-open integer interval `[from, to)` — every integer `n`
satisfying `from <= n < to`. The exclusive upper bound matches Python's
`range` convention and guarantees `range (0) (n).length === n`, making it
easy to produce index arrays. Returns `[]` when `from >= to`.
range (0) (5)
// => [0, 1, 2, 3, 4]
range (2) (6)
// => [2, 3, 4, 5]
range (5) (5)
// => []
unfold :: (b -> Maybe [a, b]) -> b -> Array a
The anamorphism (unfold) for Array — builds a list from a seed by repeatedly
applying `f` until it returns `Nothing`. This is the dual of `reduce`:
where `reduce` collapses a list to a value, `unfold` expands a value into a
list. Use it to generate number sequences, lazy pagination results, countdown
timers, or any corecursive structure without writing an explicit loop.
unfold (n => n <= 0 ? M.nothing () : M.just ([n, n - 1])) (4)
// => [4, 3, 2, 1]
unfold (n => n > 5 ? M.nothing () : M.just ([n * n, n + 1])) (1)
// => [1, 4, 9, 16, 25]
chainRec :: ((a -> Step, b -> Step, a) -> Array Step) -> a -> Array b
Stack-safe recursive array expansion via a trampoline. Unlike a naive
recursive `chain`, `chainRec` never grows the JS call stack, making it
safe for deep graph traversals or large tree enumerations. The step
function receives `next` (enqueue a seed for further expansion) and `done`
(emit a result value), and returns an array of steps so one seed can fan
out into many continuations in a single step.
chainRec ((next, done, x) => x <= 0 ? [done (x)] : [next (x - 1), next (x - 1)]) (2)
// => [0, 0, 0, 0]
equals :: (a -> a -> Boolean) -> Array a -> Array a -> Boolean
Element-wise equality using a curried comparator. Two arrays are equal when
they have the same length and every pair of corresponding elements satisfies
the comparator. The comparator can encode any domain equality — case-
insensitive string comparison, numeric tolerance, or structural equality.
equals (a => b => a === b) (['alice', 'bob']) (['alice', 'bob'])
// => true
equals (a => b => a === b) (['alice', 'bob']) (['alice', 'eve'])
// => false
equals (a => b => a === b) ([1, 2]) ([1, 2, 3])
// => false
lte :: (a -> a -> Boolean) -> Array a -> Array a -> Boolean
Lexicographic less-than-or-equal comparison for arrays using a curried
element comparator. Compares element by element left-to-right; the first
differing position determines the result. A strict prefix is always `lte`
its extension. Useful for sorting multi-key records or checking ordering
without constructing a dedicated comparator.
lte (a => b => a <= b) ([1, 2, 3]) ([1, 2, 4])
// => true
lte (a => b => a <= b) ([1, 3]) ([1, 2])
// => false
lte (a => b => a <= b) ([1, 2]) ([1, 2, 0])
// => true
isOutOfBounds :: Integer -> Array a -> Boolean
Returns `true` when `index` is negative or greater than or equal to the
array's length. Use it as a guard before unsafe index access, or pair it
with `lookup`, which already calls it internally to produce a safe `Maybe`.
isOutOfBounds (3) ([1, 2, 3])
// => true
isOutOfBounds (2) ([1, 2, 3])
// => false
isOutOfBounds (-1) ([1, 2, 3])
// => true
size :: Array a -> Integer
Returns the number of elements in the array. A thin curried wrapper around
`arr.length` that can be passed to higher-order combinators such as `map`
or used in point-free style where a plain property access would not compose.
size (['alice', 'bob', 'carol'])
// => 3
size ([])
// => 0
all :: (a -> Boolean) -> Array a -> Boolean
Returns `true` when every element of the array satisfies the predicate.
Short-circuits on the first failing element. Useful for validating inputs
or checking invariants across a whole collection before processing it.
all (x => x > 0) ([1, 5, 12])
// => true
all (x => x > 0) ([1, -3, 5])
// => false
all (x => typeof x === 'string') (['hello', 'world'])
// => true
any :: (a -> Boolean) -> Array a -> Boolean
Returns `true` when at least one element satisfies the predicate.
Short-circuits as soon as a matching element is found. The existential
counterpart to `all`; together they cover universal and existential
quantification over arrays.
any (x => x > 10) ([3, 7, 15])
// => true
any (x => x < 0) ([1, 2, 3])
// => false
none :: (a -> Boolean) -> Array a -> Boolean
Returns `true` when no element satisfies the predicate. Equivalent to
`!any (pred) (arr)` but reads more naturally in validation contexts, e.g.
"none of the prices are negative". Pair with `all` and `any` to express
rich constraints over collections.
none (x => x < 0) ([3, 7, 12])
// => true
none (x => x > 5) ([1, 3, 7])
// => false
elem :: (a -> a -> Boolean) -> a -> Array a -> Boolean
Tests whether `x` is a member of `arr` using a curried equality function.
Passing a custom comparator makes it easy to check membership by a specific
field, e.g. whether a user name exists in a list. Equivalent to
`any (eq (x)) (arr)`.
elem (a => b => a === b) ('bob') (['alice', 'bob', 'carol'])
// => true
elem (a => b => a === b) ('dave') (['alice', 'bob', 'carol'])
// => false
array :: b -> (a -> Array a -> b) -> Array a -> b
The catamorphism for Array — deconstructs an array into two cases: the
empty array returns `empty_`, and a non-empty array calls `nonEmpty` with
the head and tail. This is the safest way to pattern-match on an array's
shape in a functional pipeline, guaranteeing exhaustive handling of both
cases without unchecked index access.
array ('none') (h => _ => h) (['alice', 'bob', 'carol'])
// => 'alice'
array ('none') (h => _ => h) ([])
// => 'none'
array (0) (h => t => h + t.length) ([10, 20, 30])
// => 12
lookup :: Integer -> Array a -> Maybe a
Safe index access that returns `Just` the element at `index`, or `Nothing`
when the index is out of bounds. Eliminates the risk of returning `undefined`
from an out-of-range access and forces callers to handle the missing case
explicitly. Pair with `M.map` or `M.chain` to transform the result in a
pipeline, or `M.withDefault` to supply a fallback.
lookup (1) (['alice', 'bob', 'carol'])
// => just('bob')
lookup (0) ([99.99])
// => just(99.99)
lookup (5) (['alice', 'bob'])
// => nothing()
head :: Array a -> Maybe a
Safe access to the first element, returning `Just a` for a non-empty array
or `Nothing` for an empty one. Avoids the `undefined` pitfall of `arr[0]`
and forces handling the empty case. In a pipeline, chain the result with
`M.map` to transform it, or use `M.withDefault` to supply a fallback value.
head (['alice', 'bob', 'carol'])
// => just('alice')
head ([42])
// => just(42)
head ([])
// => nothing()
last :: Array a -> Maybe a
Safe access to the last element, returning `Just a` for a non-empty array
or `Nothing` for an empty one. The symmetric counterpart to `head`; both
avoid the `undefined` pitfall of unchecked index access on an empty array.
Use `M.withDefault` to provide a fallback in case the array is empty.
last ([10, 20, 30])
// => just(30)
last (['only'])
// => just('only')
last ([])
// => nothing()
tail :: Array a -> Maybe (Array a)
Safe access to all elements after the first, returning `Just (Array a)` for
a non-empty array or `Nothing` for an empty one. Useful for recursive list
processing where the empty case must be handled explicitly. Pair with `head`
to safely destructure the first element and the rest of the list.
tail ([1, 2, 3])
// => just([2, 3])
tail (['only'])
// => just([])
tail ([])
// => nothing()
init :: Array a -> Maybe (Array a)
Safe access to all elements except the last, returning `Just (Array a)` for
a non-empty array or `Nothing` for an empty one. The symmetric counterpart
to `tail`; together they let you walk a list from either end without ever
producing `undefined`. Use in pipelines that need to strip a trailing element.
init ([1, 2, 3])
// => just([1, 2])
init (['only'])
// => just([])
init ([])
// => nothing()
find :: (a -> Boolean) -> Array a -> Maybe a
Returns `Just` the first element satisfying the predicate, or `Nothing` if
no element matches. Safer than native `Array.prototype.find`, which returns
`undefined` on failure. Pair with `M.map` to transform the found value, or
`M.withDefault` to supply a fallback.
find (u => u.role === 'admin') ([{ name: 'alice', role: 'user' }, { name: 'bob', role: 'admin' }])
// => just({ name: 'bob', role: 'admin' })
find (x => x > 100) ([1, 2, 3])
// => nothing()
findMap :: (a -> Maybe b) -> Array a -> Maybe b
Finds the first element for which `f` returns `Just`, and returns that
wrapped value. Combines a search and a transformation in a single pass,
avoiding redundant iterations. More efficient than mapping and then finding
when the transformation itself is the membership test.
findMap (x => x > 0 ? M.just (x * 10) : M.nothing ()) ([-2, -1, 3, 5])
// => just(30)
findMap (x => x > 100 ? M.just (x) : M.nothing ()) ([1, 2, 3])
// => nothing()
reduce :: (b -> a -> b) -> b -> Array a -> b
Left fold over an array with a curried binary accumulator function.
The foundational building block for most aggregation: summing prices,
merging objects into a map, or building strings. Processes elements
left-to-right; pair with `scanl` when you also need the intermediate
accumulators, not just the final result.
reduce (acc => x => acc + x) (0) ([12.5, 7.0, 3.5])
// => 23
reduce (acc => item => ({ ...acc, [item.id]: item.value })) ({}) ([{ id: 'a', value: 1 }, { id: 'b', value: 2 }])
// => { a: 1, b: 2 }
scanl :: (b -> a -> b) -> b -> Array a -> Array b
Left scan — like `reduce` but returns an array containing the initial value
followed by every intermediate accumulator. Use it for running totals,
progress indicators, or undo stacks where the full history of an
accumulation matters. The output length is always `arr.length + 1`.
scanl (acc => x => acc + x) (0) ([10, 20, 30])
// => [0, 10, 30, 60]
scanl (acc => x => acc * x) (1) ([2, 3, 4])
// => [1, 2, 6, 24]
foldMap :: (b -> b -> b) -> b -> (a -> b) -> Array a -> b
Maps each element to a monoidal value and concatenates them using the
supplied `concat` and `empty` (identity). This is the standard Foldable
`foldMap` operation; choosing different monoids (sum, string, array) gives
different aggregation behaviours through a uniform interface.
foldMap (a => b => a + b) (0) (x => x * 2) ([5, 10, 15])
// => 60
foldMap (a => b => a + b) ('') (s => s.toUpperCase ()) (['hello', ' ', 'world'])
// => 'HELLO WORLD'
joinWith :: String -> Array String -> String
Joins an array of strings into a single string, inserting `sep` between
every adjacent pair. A thin curried wrapper around `Array.prototype.join`
that fits naturally into point-free pipelines. Returns an empty string for
an empty array regardless of the separator.
joinWith (', ') (['alice', 'bob', 'carol'])
// => 'alice, bob, carol'
joinWith ('/') (['home', 'user', 'docs'])
// => 'home/user/docs'
joinWith (',') ([])
// => ''
concat :: Array a -> Array a -> Array a
Concatenates two arrays, returning a new array with elements of `a` followed
by elements of `b`. This is the Semigroup/Monoid `append` operation for
Array; pair it with `empty` to get the full Monoid. Useful for building up
arrays incrementally in a pipeline or `reduce`.
concat (['alice', 'bob']) (['carol', 'dave'])
// => ['alice', 'bob', 'carol', 'dave']
concat ([1, 2]) ([])
// => [1, 2]
append :: a -> Array a -> Array a
Appends a single element to the end of an array, returning a new array
without mutating the original. Use in a `reduce` accumulator when building
up a list one element at a time, or as the curried equivalent of
`arr.concat ([x])`.
append ('dave') (['alice', 'bob', 'carol'])
// => ['alice', 'bob', 'carol', 'dave']
append (0) ([1, 2, 3])
// => [1, 2, 3, 0]
prepend :: a -> Array a -> Array a
Prepends a single element to the front of an array, returning a new array
without mutating the original. The symmetric counterpart to `append`; use it
to cons-up lists in head-first order, or as the stack-push operation in a
purely-functional style.
prepend ('alice') (['bob', 'carol'])
// => ['alice', 'bob', 'carol']
prepend (0) ([1, 2, 3])
// => [0, 1, 2, 3]
map :: (a -> b) -> Array a -> Array b
The Functor instance for Array — applies `f` to every element, returning a
new array of the same length. This is the primary way to transform array
contents while preserving structure. Compose with `filter` and `chain` to
build expressive data pipelines over collections of domain objects.
map (u => u.name) ([{ name: 'alice', age: 30 }, { name: 'bob', age: 25 }])
// => ['alice', 'bob']
map (price => price * 1.2) ([9.99, 19.99, 4.99])
// => [11.988, 23.988, 5.988]
filter :: (a -> Boolean) -> Array a -> Array a
Keeps only the elements that satisfy the predicate, preserving order.
The complement `reject` removes matching elements instead. Use `partition`
when you need both the passing and failing subsets in a single pass over
the array.
filter (u => u.active) ([{ name: 'alice', active: true }, { name: 'bob', active: false }])
// => [{ name: 'alice', active: true }]
filter (x => x > 0) ([-3, 1, -1, 2])
// => [1, 2]
reject :: (a -> Boolean) -> Array a -> Array a
Removes every element that satisfies the predicate, keeping the rest.
The exact complement of `filter`: `reject (pred) (arr)` is equivalent to
`filter (x => !pred (x)) (arr)`. Use `partition` when you need both the
passing and failing subsets simultaneously.
reject (u => u.banned) ([{ name: 'alice', banned: false }, { name: 'mallory', banned: true }])
// => [{ name: 'alice', banned: false }]
reject (x => x % 2 === 0) ([1, 2, 3, 4, 5])
// => [1, 3, 5]
partition :: (a -> Boolean) -> Array a -> [Array a, Array a]
Splits an array into a pair `[passing, failing]` based on a predicate in a
single pass. More efficient than calling `filter` and `reject` separately
when both subsets are needed — for example, separating valid orders from
invalid ones before processing each group differently.
partition (x => x > 0) ([-2, 3, -1, 4, 0])
// => [[3, 4], [-2, -1, 0]]
partition (u => u.role === 'admin') ([{ name: 'alice', role: 'admin' }, { name: 'bob', role: 'user' }])
// => [[{ name: 'alice', role: 'admin' }], [{ name: 'bob', role: 'user' }]]
chain :: (a -> Array b) -> Array a -> Array b
Monadic bind (flatMap) for Array — maps `f` over each element and
concatenates the resulting arrays. Solves the 1-to-many expansion problem:
each input produces zero or more outputs. Return `[]` for unwanted elements
to combine filtering and transformation in a single pass. Chain multiple
`chain` calls to compose multi-step expansions.
chain (tag => ['#' + tag, tag.toUpperCase ()]) (['js', 'fp'])
// => ['#js', 'JS', '#fp', 'FP']
chain (x => x > 0 ? [x] : []) ([-1, 2, -3, 4])
// => [2, 4]
flatten :: Array (Array a) -> Array a
Flattens exactly one level of array nesting. Equivalent to `chain (x => x)`
or `Array.prototype.flat (1)`. Use when `map` has produced an
`Array (Array a)` and you want to collapse it. For deeper nesting, apply
`flatten` multiple times or use `chain` recursively.
flatten ([[1, 2], [3], [4, 5]])
// => [1, 2, 3, 4, 5]
flatten ([['alice', 'bob'], [], ['carol']])
// => ['alice', 'bob', 'carol']
ap :: Array (a -> b) -> Array a -> Array b
Applies an array of functions to an array of values, collecting every
(function, value) pair — the Applicative instance for Array. The result is
the Cartesian product with `fns.length * arr.length` elements. Useful for
generating all combinations of options, e.g. every size × colour variant
of a product.
ap ([x => x + 1, x => x * 10]) ([5, 20])
// => [6, 21, 50, 200]
ap ([s => 'small ' + s, s => 'large ' + s]) (['red', 'blue'])
// => ['small red', 'small blue', 'large red', 'large blue']
reverse :: Array a -> Array a
Returns a new array with elements in reversed order without mutating the
original. Safe to use in pipelines where immutability matters, unlike
`Array.prototype.reverse` which sorts in place.
reverse ([1, 2, 3, 4, 5])
// => [5, 4, 3, 2, 1]
reverse (['alice', 'bob', 'carol'])
// => ['carol', 'bob', 'alice']
sort :: (a -> a -> Boolean) -> Array a -> Array a
Stable sort using a curried `lte` (≤) comparator. Elements with equal keys
preserve their original relative order. Pass a plain `a => b => a <= b` for
natural ordering, or use `toComparator` from `ordering.js` to convert an
`Ordering`-returning comparison function.
sort (a => b => a <= b) ([30, 10, 20])
// => [10, 20, 30]
sort (a => b => a >= b) ([30, 10, 20])
// => [30, 20, 10]
sortBy :: (b -> b -> Boolean) -> (a -> b) -> Array a -> Array a
Stable sort on a projected key using a curried `lte` comparator. Avoids
manually extracting the key inside a comparator; supply the key extractor
as `toKey`. Very practical for sorting arrays of objects by a specific
field, e.g. sorting products by price or users by name.
sortBy (a => b => a <= b) (p => p.price) ([{ name: 'widget', price: 9.99 }, { name: 'gadget', price: 4.99 }])
// => [{ name: 'gadget', price: 4.99 }, { name: 'widget', price: 9.99 }]
sortBy (a => b => a <= b) (u => u.name) ([{ name: 'carol' }, { name: 'alice' }, { name: 'bob' }])
// => [{ name: 'alice' }, { name: 'bob' }, { name: 'carol' }]
nub :: (a -> a -> Boolean) -> Array a -> Array a
Deduplicates an array by removing later occurrences of elements already
seen, keeping the first. Uses a curried equality function so it works for
any type: primitives with `===`, objects compared by a specific field, or
custom domain equality. The order of the remaining elements is preserved.
nub (a => b => a === b) (['alice', 'bob', 'alice', 'carol', 'bob'])
// => ['alice', 'bob', 'carol']
nub (a => b => a.id === b.id) ([{ id: 1, v: 'a' }, { id: 2, v: 'b' }, { id: 1, v: 'c' }])
// => [{ id: 1, v: 'a' }, { id: 2, v: 'b' }]
extend :: (Array a -> b) -> Array a -> Array b
Comonad `extend` for Array — applies `f` to every suffix of the array and
collects the results. The suffix starting at index `i` is `arr.slice (i)`.
Useful for sliding-window computations such as running aggregates or local
context extraction, where each position needs access to its own tail.
extend (xs => xs.length) ([10, 20, 30])
// => [3, 2, 1]
extend (head) ([5, 6, 7])
// => [just(5), just(6), just(7)]
take :: Integer -> Array a -> Maybe (Array a)
Returns `Just` the first `n` elements when `0 <= n <= arr.length`, or
`Nothing` when `n` is out of range. Unlike `Array.prototype.slice`, this
forces you to handle the case where the array is shorter than expected.
Use `M.withDefault ([])` to fall back to an empty array silently.
take (2) (['alice', 'bob', 'carol'])
// => just(['alice', 'bob'])
take (0) ([1, 2, 3])
// => just([])
take (5) ([1, 2, 3])
// => nothing()
drop :: Integer -> Array a -> Maybe (Array a)
Returns `Just` the array after discarding the first `n` elements when
`0 <= n <= arr.length`, or `Nothing` if `n` is out of range. Use this
instead of unchecked slicing when the caller cannot guarantee the array is
long enough. Pair with `take` for safe prefix/suffix splitting.
drop (2) (['alice', 'bob', 'carol'])
// => just(['carol'])
drop (0) ([1, 2, 3])
// => just([1, 2, 3])
drop (5) ([1, 2, 3])
// => nothing()
takeLast :: Integer -> Array a -> Maybe (Array a)
Returns `Just` the last `n` elements when `0 <= n <= arr.length`, or
`Nothing` when `n` is out of range. The symmetric counterpart to `take`;
useful for extracting a trailing window such as the most recent N log
entries from a history array.
takeLast (2) ([10, 20, 30, 40])
// => just([30, 40])
takeLast (0) ([1, 2, 3])
// => just([])
takeLast (5) ([1, 2, 3])
// => nothing()
dropLast :: Integer -> Array a -> Maybe (Array a)
Returns `Just` the array with the last `n` elements removed when
`0 <= n <= arr.length`, or `Nothing` if `n` is out of range. The symmetric
counterpart to `drop`; use it to strip a trailing sentinel or page marker
from a fetched list before further processing.
dropLast (2) ([10, 20, 30, 40])
// => just([10, 20])
dropLast (0) ([1, 2, 3])
// => just([1, 2, 3])
dropLast (5) ([1, 2, 3])
// => nothing()
replicate :: Integer -> a -> Array a
Creates an array of exactly `n` copies of `x`. Useful for initialising a
fixed-size buffer, producing a default value array, or generating test data
without writing an explicit loop. Returns `[]` when `n` is zero or negative.
replicate (3) ('*')
// => ['*', '*', '*']
replicate (4) (0)
// => [0, 0, 0, 0]
replicate (0) ('x')
// => []
span :: (a -> Boolean) -> Array a -> [Array a, Array a]
Splits an array into `[prefix, rest]` where `prefix` is the longest leading
run of elements satisfying the predicate, and `rest` is everything from the
first failing element onward. Use `break_` for the complementary split
(splits at the first passing element), or `splitAt` for an index-based
variant. Both parts together always reconstruct the original array.
span (x => x < 5) ([1, 3, 5, 7])
// => [[1, 3], [5, 7]]
span (x => x < 0) ([1, 2, 3])
// => [[], [1, 2, 3]]
span (x => x > 0) ([1, 2, 3])
// => [[1, 2, 3], []]
break_ :: (a -> Boolean) -> Array a -> [Array a, Array a]
Splits an array at the first element satisfying the predicate, returning
`[prefix, rest]`. Equivalent to `span (complement (pred))`; the prefix runs
until the first element that passes the test. Use `span` when you want to
split on the first failure, and `break_` when you want to split on the first
success.
break_ (x => x > 3) ([1, 2, 4, 5])
// => [[1, 2], [4, 5]]
break_ (x => x > 0) ([1, 2, 3])
// => [[], [1, 2, 3]]
break_ (x => x < 0) ([1, 2, 3])
// => [[1, 2, 3], []]
splitAt :: Integer -> Array a -> [Array a, Array a]
Splits the array at index `n`, returning `[arr.slice (0, n), arr.slice (n)]`.
When `n <= 0` the prefix is `[]`; when `n >= arr.length` the suffix is `[]`.
Unlike `take` and `drop`, `splitAt` never returns `Nothing` — it clamps
silently. Use for fixed-offset partitioning such as header/body separation.
splitAt (2) (['a', 'b', 'c', 'd'])
// => [['a', 'b'], ['c', 'd']]
splitAt (0) ([1, 2, 3])
// => [[], [1, 2, 3]]
splitAt (5) ([1, 2, 3])
// => [[1, 2, 3], []]
until :: (a -> Boolean) -> (a -> a) -> a -> a
Iterates `f` starting from `x`, returning the first value that satisfies
`pred`. Models a while-loop in purely-functional style and is useful for
numeric convergence, binary search seed generation, or repeated
transformation until a stable state. Diverges if `pred` never becomes true.
until (x => x > 100) (x => x * 2) (1)
// => 128
until (x => x <= 1) (x => Math.floor (x / 2)) (100)
// => 0
takeWhile :: (a -> Boolean) -> Array a -> Array a
Returns the longest leading prefix of elements satisfying the predicate.
Unlike `take`, the cutoff is determined by data content rather than a fixed
count. Use `span` when you also need the remainder, or `dropWhile` for the
complement. Returns `[]` if the first element already fails the predicate.
takeWhile (x => x < 5) ([1, 3, 5, 7, 2])
// => [1, 3]
takeWhile (x => x > 0) ([4, 2, -1, 3])
// => [4, 2]
takeWhile (x => x < 0) ([1, 2, 3])
// => []
dropWhile :: (a -> Boolean) -> Array a -> Array a
Drops the longest leading prefix of elements satisfying the predicate and
returns the remainder. The complement of `takeWhile`; together they form
`span`. Useful for skipping over a run of sentinels or headers at the start
of a list before processing the meaningful payload.
dropWhile (x => x < 5) ([1, 3, 5, 7, 2])
// => [5, 7, 2]
dropWhile (x => x > 0) ([4, 2, -1, 3])
// => [-1, 3]
dropWhile (x => x > 0) ([1, 2, 3])
// => []
intercalate :: Array a -> Array (Array a) -> Array a
Inserts a separator array between each sub-array and flattens one level,
producing a single combined array. The array-level analogue of `joinWith`.
Useful for interleaving delimiters between runs of elements, e.g. inserting
divider items between groups. Returns `[]` for an empty outer array.
intercalate ([0]) ([[1, 2], [3, 4], [5]])
// => [1, 2, 0, 3, 4, 0, 5]
intercalate ([',']) ([['a', 'b'], ['c']])
// => ['a', 'b', ',', 'c']
groupBy :: (a -> a -> Boolean) -> Array a -> Array (Array a)
Groups adjacent elements into sub-arrays using a curried equality predicate.
Only consecutive equal elements are grouped; sort the array first if you
want all occurrences of a value merged. Useful for run-length encoding,
collapsing duplicate log entries, or splitting a sorted list into equal
runs before aggregating each group.
groupBy (a => b => a === b) ([1, 1, 2, 2, 2, 3])
// => [[1, 1], [2, 2, 2], [3]]
groupBy (a => b => a.dept === b.dept) ([{ name: 'alice', dept: 'eng' }, { name: 'bob', dept: 'eng' }, { name: 'carol', dept: 'hr' }])
// => [[{ name: 'alice', dept: 'eng' }, { name: 'bob', dept: 'eng' }], [{ name: 'carol', dept: 'hr' }]]
zip :: Array a -> Array b -> Array [a, b]
Pairs elements from two arrays position-by-position, truncating to the
shorter length. Excess elements of the longer array are discarded. Use
`zipWith` to apply a combining function instead of producing raw pairs, or
pass the result to `reduce` to build a lookup map.
zip (['alice', 'bob', 'carol']) ([10, 20])
// => [['alice', 10], ['bob', 20]]
zip ([1, 2, 3]) ([4, 5, 6])
// => [[1, 4], [2, 5], [3, 6]]
zipWith :: (a -> b -> c) -> Array a -> Array b -> Array c
Combines corresponding elements from two arrays using `f`, truncating to
the shorter length. A generalisation of `zip`: where `zip` always produces
pairs, `zipWith` can produce any value, making it useful for vector
arithmetic, parallel transformation, or merging related datasets by position.
zipWith (name => score => ({ name, score })) (['alice', 'bob']) ([95, 87])
// => [{ name: 'alice', score: 95 }, { name: 'bob', score: 87 }]
zipWith (a => b => a + b) ([1, 2, 3]) ([10, 20])
// => [11, 22]
traverse :: (b -> f b) -> (f (a->b) -> f a -> f b) -> ((a->b) -> f a -> f b) -> (a -> f b) -> Array a -> f (Array b)
Applicative traversal — maps an effectful function `f` over an array and
sequences the effects, collecting all results into a single wrapped array.
With Maybe this gives "all-or-nothing" semantics: if any element produces
`Nothing`, the entire traversal short-circuits to `Nothing`. Unlike `map`,
`traverse` propagates and combines the effects of each step. Pass the target
Applicative's `of`, `ap`, and `map` explicitly so this works with any
Applicative (Maybe, Either, Array, Promise, etc.).
apOf :: b -> f b (pure / of)
apAp :: f (a -> b) -> f a -> f b (ap, curried)
apMap :: (a -> b) -> f a -> f b (map, curried)
const apOf = x => M.just (x)
const apAp = ff => fa => M.chain (f => M.map (f) (fa)) (ff)
const apMap = f => fa => M.map (f) (fa)
traverse (apOf) (apAp) (apMap) (x => x > 0 ? M.just (x) : M.nothing ()) ([1, 2, 3])
// => just([1, 2, 3])
traverse (apOf) (apAp) (apMap) (x => x > 0 ? M.just (x) : M.nothing ()) ([1, -1, 3])
// => nothing()
mapM :: (m b -> (b -> m c) -> m c) -> (Array b -> m (Array b)) -> (a -> m b) -> Array a -> m (Array b)
Maps a monadic function over an array and sequences the effects, collecting
results — the monadic `mapM` from Haskell. Requires the monad's `chain` and
`of` to be passed explicitly so it is monad-agnostic. Use it instead of
`traverse` when you have a monad rather than a general Applicative. If any
step returns a failing monad (e.g. `Nothing`, `Left`), the whole computation
short-circuits.
mapM (chain) (of) (f) (xs)
≡ sequence through xs applying f to each element
mapM (M.chain) (xs => M.just (xs)) (x => x > 0 ? M.just (x) : M.nothing ()) ([5, 10, 15])
// => just([5, 10, 15])
mapM (M.chain) (xs => M.just (xs)) (x => x > 0 ? M.just (x) : M.nothing ()) ([5, -1, 15])
// => nothing()
forM :: (m b -> (b -> m c) -> m c) -> (Array b -> m (Array b)) -> Array a -> (a -> m b) -> m (Array b)
Like `mapM` but with the array and function arguments swapped — useful when
the array is known upfront and you want to express "for each element of xs,
do this effectful thing". The name mirrors Haskell's `forM`. Internally
delegates to `mapM (chain) (of_) (f) (arr)`.
forM (chain) (of) (xs) (f) ≡ mapM (chain) (of) (f) (xs)
forM (M.chain) (xs => M.just (xs)) ([1, 2, 3]) (x => x > 0 ? M.just (x * 2) : M.nothing ())
// => just([2, 4, 6])
forM (M.chain) (xs => M.just (xs)) ([1, -2, 3]) (x => x > 0 ? M.just (x) : M.nothing ())
// => nothing()