# Collections

Effect ships a large family of pure, value-oriented collection modules. They
play the role that lodash or Ramda do in a plain JavaScript codebase, but with
two important differences: the transforming operations are **immutable** (they
allocate new structures instead of mutating their inputs), and every module
exposes a **dual API** so the same function works both inside a `pipe` and as a
direct call.

```ts
import { Array, pipe } from "effect"

const numbers = [1, 2, 3, 4, 5]

// Pure, immutable transformations — `numbers` is never mutated.
const doubledEvens = pipe(
  numbers,
  Array.filter((n) => n % 2 === 0),
  Array.map((n) => n * 2)
)

console.log(doubledEvens)
// => [4, 8]
console.log(numbers)
// => [1, 2, 3, 4, 5]  (unchanged)
```

This page is a navigational hub. It explains how to pick a collection, how the
dual APIs work, and how value equality factors in. Each module then has its own
page with an exhaustive, example-driven reference.

## Picking a collection

Start from what you are modeling, then reach for the matching module:

| You need…                                          | Use                      | Notes                                                          |
| -------------------------------------------------- | ------------------------ | ------------------------------------------------------------- |
| An ordered list of plain values                    | `Array`                  | Built-in JS arrays plus functional combinators.               |
| A lazy or potentially infinite sequence            | `Iterable`               | Works over any `Symbol.iterator`; transformations are lazy.   |
| Keyed-object / tuple utilities                     | `Record` / `Struct` / `Tuple` | Operate on plain objects and tuples by key/position.     |
| An immutable streaming sequence                    | `Chunk`                  | Efficient append/concat; the backbone of `Stream`.            |
| A persistent map or set keyed by value             | `HashMap` / `HashSet`    | Structural sharing; keys compared by `Equal`.                 |
| A map keyed by string prefixes                     | `Trie`                   | Prefix search and ordered string-key iteration.               |
| In-place mutable buffers                           | `MutableList` / `MutableHashMap` / `MutableHashSet` | For hot loops and local accumulation. |
| A single mutable cell                              | `MutableRef`             | One boxed value you read and overwrite imperatively.          |
| Nodes, edges, and graph algorithms                 | `Graph`                  | Directed/undirected graphs with traversal and path finding.   |

A useful rule of thumb: prefer the immutable modules (`Array`, `Chunk`,
`HashMap`, `HashSet`, `Trie`) for data that flows through your program, and the
`Mutable*` modules only as a local performance optimization where the mutation
cannot escape.

## Dual APIs and pipe

Almost every function in these modules is **dual**: you can call it data-first
(passing the collection as the first argument) or data-last (omitting the
collection so it returns a function ready for `pipe`).

```ts
import { Array, pipe } from "effect"

const xs = [1, 2, 3]

// data-first: the collection comes first
const a = Array.map(xs, (n) => n * 2)
// => [2, 4, 6]

// data-last: returns a unary function, ideal inside pipe
const b = pipe(xs, Array.map((n) => n * 2))
// => [2, 4, 6]
```

Both forms produce the same result. Use data-last inside `pipe` when chaining
several steps, and data-first for one-off calls. See
[Dual APIs](https://effect.plants.sh/code-style/dual-apis/) for the full explanation and how to write
your own dual functions.

Because the modules share global names with the JavaScript built-ins (`Array`,
`Record`, `String`, `Order`, …), the Effect convention is to const first = Array.head([10, 20, 30])
// => Option.some(10)

Option.getOrElse(first, () => 0)
// => 10
```

## Value equality

The collection modules that deduplicate, look up, or compare elements use the
`Equal` protocol rather than JavaScript's `===`. This is what makes a
`HashMap` keyed by a structural value, or `Array.dedupe`, behave the way you
expect for data classes.

```ts
class Id extends Data.Class<{ readonly id: number }> {}

const a = new Id({ id: 1 })
const b = new Id({ id: 1 })

// Data values are compared structurally via the Equal protocol.
const unique = Array.dedupe([a, b])
console.log(unique.length)
// => 1
```

Set-like operations such as `Array.union`, `Array.intersection`, and
`Array.difference` follow the same protocol, with `*With` variants when you
need domain-specific equality. See
[Equal and Hash](https://effect.plants.sh/traits/equal-and-hash/) for how equality and hashing are
derived, and how to make your own types participate.

## In this section

- **`Array`** — functional constructors, transforms, searches, folds,
  grouping, sorting, and set operations over JS arrays and non-empty arrays.

  ```ts
  Array.range(1, 3)
  // => [1, 2, 3]
  ```

- **`Iterable`** — lazy operations over any iterable, including unbounded
  sequences that you bound with `take`.

  ```ts
  Array.from(Iterable.take(Iterable.range(1), 3))
  // => [1, 2, 3]
  ```

- **`Record` / `Struct` / `Tuple`** — keyed-object and tuple utilities for
  mapping, filtering, and reshaping plain objects and tuples.

- **`HashMap` / `HashSet`** — persistent, structurally-shared map and set with
  keys compared by `Equal`.

  ```ts
  const m = HashMap.make(["a", 1], ["b", 2])
  HashMap.get(m, "a")
  // => Option.some(1)
  ```

- **`Trie`** — a prefix tree mapping string keys to values, with prefix search.

- **`MutableList` / `MutableHashMap` / `MutableHashSet`** — in-place mutable
  structures for local, performance-sensitive accumulation.

- **`MutableRef`** — a single mutable cell with helpers like `update` and
  `increment`.

  ```ts
  const ref = MutableRef.make(0)
  MutableRef.increment(ref)
  MutableRef.get(ref)
  // => 1
  ```

- **`Graph`** — immutable directed/undirected graphs with traversal
  (`dfs`, `bfs`, `topo`), analysis, path finding (`dijkstra`, `astar`), and
  diagram export (`toMermaid`).

  ```ts
  const g = Graph.directed<string, string>((mutable) => {
    const a = Graph.addNode(mutable, "A")
    const b = Graph.addNode(mutable, "B")
    Graph.addEdge(mutable, a, b, "A-B")
  })
  ```

Related: the immutable streaming sequence type [`Chunk`](https://effect.plants.sh/data-types/chunk/)
lives in the Data Types section, since it is primarily used as the building
block of `Stream`.