# Random

`Random` is a pseudo-random number generator exposed through Effect's context.
Instead of reaching for `Math.random()` directly, you read randomness from the
current `Random` service. That single indirection is what makes random programs
**reproducible**: in a test or a local simulation you can seed the generator and
get the exact same sequence every time.

`Random` is a [`Context.Reference`](https://effect.plants.sh/services-and-layers/references/), which means it is
**always available** — there is no layer to provide. A default `Math.random`-backed
implementation is installed for you, and you can override it (per-effect with
[`withSeed`](#withseed), or globally with a custom generator) wherever you need
determinism.

```ts
import { Effect, Random } from "effect"

const program = Effect.gen(function*() {
  const randomFloat = yield* Random.next          // 0 <= x < 1
  const randomInt = yield* Random.nextInt          // any safe integer
  const diceRoll = yield* Random.nextIntBetween(1, 6)

  return { randomFloat, randomInt, diceRoll }
})
```
**Not for secrets:** The default `Random` implementation is built on `Math.random` and is **not**
cryptographically secure. Never use it for tokens, session identifiers, password
salts, or any security-sensitive value. For unpredictable, secure randomness use
the `Crypto` module instead. `Random` optimizes for reproducibility; `Crypto`
optimizes for unpredictability.

All of the generators below return an `Effect` with **no error channel**
(`Effect.Effect<A>`) — drawing a random value cannot fail.

## Generating values

The core generators cover floats, integers, booleans, and bounded ranges. Read
them with `yield*` inside `Effect.gen`:

```ts
import { Effect, Random } from "effect"

const program = Effect.gen(function*() {
  // A double in [0, 1) — the analogue of Math.random()
  const f = yield* Random.next

  // A coin flip
  const flip = yield* Random.nextBoolean

  // A safe integer anywhere in the full safe-integer range
  const big = yield* Random.nextInt

  // A float in a custom range [0, 10)
  const temp = yield* Random.nextBetween(0, 10)

  // An integer in a range — inclusive by default, so this is a d6
  const dice = yield* Random.nextIntBetween(1, 6)

  // Exclude the upper bound: a uniform index into a 6-element array
  const index = yield* Random.nextIntBetween(0, 6, { halfOpen: true })

  return { f, flip, big, temp, dice, index }
})
```
**Note:** `nextIntBetween` rounds its bounds before drawing: the lower bound is rounded up
with `Math.ceil` and the upper bound is rounded down with `Math.floor`. With the
default (inclusive) behavior, `nextIntBetween(1, 6)` can return any of `1, 2, 3,
4, 5, 6`. Pass `{ halfOpen: true }` to make the upper bound exclusive — ideal for
picking an array index.

## Shuffling collections

`shuffle` randomly reorders any iterable and returns a new `Array` (the input is
not mutated). It uses a Fisher–Yates shuffle driven by the active `Random`
service:

```ts
import { Effect, Random } from "effect"

const program = Effect.gen(function*() {
  const deck = yield* Random.shuffle([1, 2, 3, 4, 5])
  console.log(deck) // => e.g. [3, 1, 5, 2, 4]

  // Works on any iterable, e.g. a Set
  const picks = yield* Random.shuffle(new Set(["a", "b", "c"]))
  console.log(picks) // => e.g. ["b", "c", "a"]
})
```

## Determinism and testing

Because randomness flows through the service, you can replace it with a seeded
generator using [`withSeed`](#withseed). The **same seed always produces the same
sequence**, so a flaky "it depends on randomness" test becomes a deterministic
one:

```ts
import { Effect, Random } from "effect"

const program = Effect.gen(function*() {
  const a = yield* Random.next
  const b = yield* Random.next
  return [a, b] as const
})

// Same seed => identical output, run after run
const seeded1 = program.pipe(Random.withSeed("test-seed"))
const seeded2 = program.pipe(Random.withSeed("test-seed"))

// Both promises resolve to the same pair of numbers
Effect.runPromise(seeded1)
Effect.runPromise(seeded2)
```

This is exactly the mechanism that underpins reproducible, property-based-style
tests: seed the program, exercise it, and if it fails you can replay the *same*
random sequence to debug it. See the [testing guide](https://effect.plants.sh/testing/) for how to
structure deterministic tests around services like this.
**Tip:** A seed makes the sequence **predictable**, not **secure**. Use an unpredictable
seed (or the `Crypto` module) when uniqueness or unpredictability actually
matters; reserve fixed seeds for tests and simulations.

## API reference

### `next`

Generates a random double in `[0, 1)` (inclusive of 0, exclusive of 1) — the
direct analogue of `Math.random()`.

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  const x = yield* Random.next
  // => 0.5488135039273248 (0 <= x < 1)
})
```

### `nextBoolean`

Generates a random boolean — `true` roughly half the time. (Internally it draws a
double and returns whether it is greater than `0.5`.)

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  const b = yield* Random.nextBoolean
  // => true | false
})
```

### `nextInt`

Generates a random safe integer across the entire range from
`Number.MIN_SAFE_INTEGER` to `Number.MAX_SAFE_INTEGER` (inclusive). Use
[`nextIntBetween`](#nextintbetween) when you want a bounded integer.

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  const n = yield* Random.nextInt
  // => -3920481039402011 (some safe integer)
})
```

### `nextBetween`

`(min: number, max: number) => Effect<number>` — generates a random **float** in
`[min, max)` (inclusive of `min`, exclusive of `max`).

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  const x = yield* Random.nextBetween(10, 20)
  // => 14.73... (10 <= x < 20)
})
```

### `nextIntBetween`

`(min: number, max: number, options?: { halfOpen?: boolean }) => Effect<number>` —
generates a random **integer** in a rounded range. The lower bound is rounded up
(`Math.ceil`), the upper bound rounded down (`Math.floor`). Inclusive of both
bounds by default; pass `{ halfOpen: true }` to exclude the upper bound.

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  // Inclusive: result is one of 1, 2, 3, 4, 5, 6
  const dice = yield* Random.nextIntBetween(1, 6)
  // => 4

  // Half-open: result is one of 0, 1, 2, 3, 4, 5 (good for array indices)
  const idx = yield* Random.nextIntBetween(0, 6, { halfOpen: true })
  // => 5
})
```

### `shuffle`

`<A>(elements: Iterable<A>) => Effect<Array<A>>` — returns a new array with the
elements of any iterable in random order, leaving the input untouched.

```ts
import { Effect, Random } from "effect"

Effect.gen(function*() {
  const shuffled = yield* Random.shuffle(["a", "b", "c", "d"])
  // => ["c", "a", "d", "b"]
})
```

### `withSeed`

```ts
// data-last (for .pipe)
withSeed(seed: string | number): <A, E, R>(self: Effect<A, E, R>) => Effect<A, E, R>
// data-first
withSeed<A, E, R>(self: Effect<A, E, R>, seed: string | number): Effect<A, E, R>
```

Runs an effect with a deterministic generator seeded by the given `string` or
`number`. Internally it provides a seeded ISAAC-based generator in place of the
default `Random` service for the duration of `self`. The same seed always yields
the same sequence. It is `dual`, so it works both in `.pipe(...)` and as a direct
call.

```ts
import { Effect, Random } from "effect"

const draw = Random.next

// data-last, via pipe
const a = draw.pipe(Random.withSeed(42))

// data-first, direct call
const b = Random.withSeed(draw, 42)

// a and b resolve to the same number
Effect.runPromise(a) // => 0.123...
Effect.runPromise(b) // => 0.123... (identical)
```

### `Random` (the reference)

```ts
const Random: Context.Reference<{
  nextIntUnsafe(): number
  nextDoubleUnsafe(): number
}>
```

The service itself. It is a [`Context.Reference`](https://effect.plants.sh/services-and-layers/references/) holding a
minimal generator interface: `nextDoubleUnsafe()` returns a double in `[0, 1)` and
`nextIntUnsafe()` returns a safe integer. Every function above is derived from
these two methods. The `Unsafe` suffix means they are plain, synchronous,
non-`Effect` functions — prefer the wrapped generators (`Random.next`,
`Random.nextInt`, …) in application code.

You normally interact with it through [`withSeed`](#withseed), but you can also
provide a fully custom generator — for example a fixed sequence in a test, or a
secure source in production:

```ts
import { Effect, Random } from "effect"

// A custom generator that always returns the same values — handy for asserting
// on code paths that branch on randomness.
const fixed = {
  nextDoubleUnsafe: () => 0.5,
  nextIntUnsafe: () => 7
}

const program = Effect.gen(function*() {
  const d = yield* Random.next      // => 0.5
  const n = yield* Random.nextInt   // => 7
  const r = yield* Random.nextIntBetween(1, 100) // derived from 0.5 => 51
  return { d, n, r }
})

// Override the reference for this effect
const deterministic = program.pipe(
  Effect.provideService(Random, fixed)
)

Effect.runPromise(deterministic) // => { d: 0.5, n: 7, r: 51 }
```
**Secure randomness:** The `Random` module is deliberately reproducible and is not suitable for
security-sensitive values. When you need cryptographically secure, unpredictable
bytes or numbers, reach for the `Crypto` module instead — you can also plug a
secure generator into the `Random` reference using `Effect.provideService` as
shown above.