std/random
Pure pseudo-random generation. A random.Generator<T> is an immutable
recipe for producing a T; run it against a random.Seed with
Generator.step to get back the value paired with the next seed.
Same seed in -> same value out, so every draw is reproducible and testable.
The only impurity is Seed.from_os, which reads OS entropy for a fresh
starting seed.
Import with import std/random.
Exports
Section titled “Exports”enum Error
Section titled “enum Error”enum Error { InvalidIntRange { from: Int, to: Int } InvalidFloatRange { from: Float, to: Float } InvalidWeight { weight: Float } ZeroWeightTotal OsEntropy { reason: String } }
Errors returned when constructing a generator whose invariants can be checked before any random draw happens, or when OS entropy is unavailable.
Error.to_string
Section titled “Error.to_string”fn to_string(e: Error): String
impl Display.to_string
Error.inspect
Section titled “Error.inspect”fn inspect(value: Error): String
impl Debug.inspect
type Seed
Section titled “type Seed”type Seed Int
opaque — construction surface is private to its defining module
Opaque PRNG state (a splitmix64 register). Thread it explicitly through
Generator.step; never mutated. Seed reproducibly with Seed.from_int, or
pull a non-deterministic one with Seed.from_os.
Seed.from_int
Section titled “Seed.from_int”fn from_int(n: Int): Seed
type function on Seed
A reproducible seed from an integer. Same n -> same sequence, forever.
Interactive Tests
seed = Seed.from_int(123)
assert Ok(die) = Generator.int(1, 6)
(roll, _) = Generator.step(die, seed)
assert roll == 2
Seed.from_os
Section titled “Seed.from_os”fn from_os(): Result<Seed, Error>
type function on Seed
A non-deterministic seed from OS entropy. The one impure call on Seed
— the entry point when you want real randomness.
Seed.inspect
Section titled “Seed.inspect”fn inspect(value: Seed): String
impl Debug.inspect
struct Generator
Section titled “struct Generator”struct Generator<T>
opaque — construction surface is private to its defining module
An immutable recipe for producing a T. Build one with a constructor
(Generator.int, …), reshape it with map / flat_map, then run it with
Generator.step. Constructors whose invariants can be invalid return
Result; unwrap them with try or case before composing.
Generator.step
Section titled “Generator.step”fn step<T>(gen: Generator<T>, seed: Seed): (T, Seed)
type function on Generator
Produce a value and the next seed. The pure core of Generator.
die = try Generator.int(1, 6) (n, _) = die |> Generator.step(Seed.from_int(42))
Interactive Tests
gen = Generator.constant("heads")
(value, _) = Generator.step(gen, Seed.from_int(1))
assert value == "heads"
Generator.int
Section titled “Generator.int”fn int(from: Int, to: Int): Result<Generator<Int>, Error>
type function on Generator
Uniform integer in the inclusive range [from, to]. Returns Err when
from > to.
Interactive Tests
assert Ok(die) = Generator.int(1, 6)
(roll, _) = Generator.step(die, Seed.from_int(123))
assert roll >= 1 and roll <= 6
assert Err(Error.InvalidIntRange{from: 6, to: 1}) = Generator.int(6, 1)
Generator.float
Section titled “Generator.float”fn float(from: Float, to: Float): Result<Generator<Float>, Error>
type function on Generator
Uniform float in the half-open range [from, to). Returns Err when
from >= to.
Interactive Tests
assert Ok(gen) = Generator.float(1.5, 2.5)
(x, _) = Generator.step(gen, Seed.from_int(123))
assert x >= 1.5 and x < 2.5
assert Err(Error.InvalidFloatRange{from: 2.5, to: 1.5}) = Generator.float(
2.5,
1.5,
)
Generator.bool
Section titled “Generator.bool”fn bool(): Generator<Bool>
type function on Generator
True or False with equal probability.
Interactive Tests
(value, _) = Generator.step(Generator.bool(), Seed.from_int(123))
assert value == True or value == False
Generator.constant
Section titled “Generator.constant”fn constant<T>(value: T): Generator<T>
type function on Generator
Always produces value (consuming no randomness, seed unchanged).
Interactive Tests
(value, _) = Generator.step(Generator.constant("fixed"), Seed.from_int(123))
assert value == "fixed"
Generator.uniform
Section titled “Generator.uniform”fn uniform<T>(first: T, rest: List<T>): Generator<T>
type function on Generator
Uniform choice among first and rest — non-empty by construction.
Generator.uniform("rock", ["paper", "scissors"])
Interactive Tests
(choice, _) = Generator.uniform("rock", ["paper", "scissors"])
|> Generator.step(Seed.from_int(123))
assert choice == "paper" or choice == "rock" or choice == "scissors"
Generator.weighted
Section titled “Generator.weighted”fn weighted<T>(first: (Float, T), rest: List<(Float, T)>): Result<Generator<T>, Error>
type function on Generator
Weighted choice; each option carries a relative weight. Non-empty. Weights must be non-negative, and at least one weight must be positive; they need not sum to 1.
Interactive Tests
assert Ok(gen) = Generator.weighted((1.0, "always"), [])
(choice, _) = Generator.step(gen, Seed.from_int(123))
assert choice == "always"
assert Err(Error.ZeroWeightTotal) = Generator.weighted((0.0, "never"), [])
Generator.map
Section titled “Generator.map”fn map<T, U>(gen: Generator<T>, f: (T) -> U): Generator<U>
type function on Generator
Transform the produced value.
Interactive Tests
gen = Generator.constant(21) |> Generator.map(|n| n * 2)
(value, _) = Generator.step(gen, Seed.from_int(123))
assert value == 42
Generator.flat_map
Section titled “Generator.flat_map”fn flat_map<T, U>(gen: Generator<T>, f: (T) -> Generator<U>): Generator<U>
type function on Generator
Sequence a dependent generator — the bind operation.
gen = try Generator.int(1, 6) gen |> Generator.flat_map(|n| Generator.list(Generator.bool(), n) )
Interactive Tests
gen =
Generator.constant(3)
|> Generator.flat_map(|n| Generator.constant(n * 10))
(value, _) = Generator.step(gen, Seed.from_int(123))
assert value == 30
Generator.list
Section titled “Generator.list”fn list<T>(gen: Generator<T>, length: Int): Generator<List<T>>
type function on Generator
A list of length independent draws from gen. A non-positive length
produces an empty list.
Interactive Tests
gen = Generator.constant("ha") |> Generator.list(3)
(values, _) = Generator.step(gen, Seed.from_int(123))
assert values == ["ha", "ha", "ha"]
Generator.inspect
Section titled “Generator.inspect”fn inspect<T>(value: Generator<T>): String where T: Debug
impl Debug.inspect