Skuld.Effects.Random (skuld v0.2.3)

View Source

Random effect - generate random values.

Provides three handler modes:

  • Production (with_handler/1): Uses Erlang's :rand module for cryptographically suitable random values.

  • Seeded (with_seed_handler/2): Uses a deterministic seed for reproducible random sequences - ideal for testing.

  • Fixed (with_fixed_handler/2): Returns values from a fixed sequence, cycling when exhausted - useful for specific test scenarios.

Production Usage

use Skuld.Syntax
alias Skuld.Comp
alias Skuld.Effects.Random

comp do
  f <- Random.random()
  i <- Random.random_int(1, 100)
  elem <- Random.random_element([:a, :b, :c])
  {f, i, elem}
end
|> Random.with_handler()
|> Comp.run!()
#=> {0.7234..., 42, :b}

Seeded Usage (Deterministic)

# Same seed produces same sequence - reproducible tests
comp do
  a <- Random.random()
  b <- Random.random()
  {a, b}
end
|> Random.with_seed_handler(seed: {1, 2, 3})
|> Comp.run!()
#=> {0.123..., 0.456...}  # always the same

Fixed Usage (Test Scenarios)

# Return specific values for testing edge cases
comp do
  a <- Random.random()
  b <- Random.random()
  c <- Random.random()
  {a, b, c}
end
|> Random.with_fixed_handler(values: [0.0, 0.5, 1.0])
|> Comp.run!()
#=> {0.0, 0.5, 1.0}

Handler Submodules

  • Random.Seed - Deterministic seeded random handler
  • Random.Fixed - Fixed value handler for testing

Summary

Functions

Install Random handler via catch clause syntax.

Generate a random float between 0.0 (inclusive) and 1.0 (exclusive).

Pick a random element from a non-empty list.

Generate a random integer in the range min..max (inclusive).

Shuffle a list randomly.

Install a handler that returns values from a fixed sequence.

Install a random handler using Erlang's :rand module.

Install a deterministic random handler with a fixed seed.

Functions

__handle__(comp, arg2)

Install Random handler via catch clause syntax.

Config selects handler type:

catch
  Random -> nil                            # production handler
  Random -> {:seed, seed: {1, 2, 3}}       # seeded handler
  Random -> {:fixed, values: [0.5, 0.7]}   # fixed values handler

random()

@spec random() :: Skuld.Comp.Types.computation()

Generate a random float between 0.0 (inclusive) and 1.0 (exclusive).

Example

comp do
  f <- Random.random()
  f
end
|> Random.with_handler()
|> Comp.run!()
#=> 0.7234...

random_element(list)

@spec random_element([a, ...]) :: Skuld.Comp.Types.computation() when a: term()

Pick a random element from a non-empty list.

Example

comp do
  elem <- Random.random_element([:rock, :paper, :scissors])
  elem
end
|> Random.with_handler()
|> Comp.run!()
#=> :scissors

random_int(min, max)

@spec random_int(integer(), integer()) :: Skuld.Comp.Types.computation()

Generate a random integer in the range min..max (inclusive).

Example

comp do
  i <- Random.random_int(1, 6)
  i
end
|> Random.with_handler()
|> Comp.run!()
#=> 4

shuffle(list)

@spec shuffle([a]) :: Skuld.Comp.Types.computation() when a: term()

Shuffle a list randomly.

Example

comp do
  shuffled <- Random.shuffle([1, 2, 3, 4, 5])
  shuffled
end
|> Random.with_handler()
|> Comp.run!()
#=> [3, 1, 5, 2, 4]

with_fixed_handler(comp, opts \\ [])

@spec with_fixed_handler(
  Skuld.Comp.Types.computation(),
  keyword()
) :: Skuld.Comp.Types.computation()

Install a handler that returns values from a fixed sequence.

Delegates to Random.Fixed.with_handler/2.

Options

  • :values - A list of values to return. For random() these should be floats 0.0-1.0. For random_int/2 and random_element/1, the handler uses these as indices (mod list length).

Example

comp do
  a <- Random.random()
  b <- Random.random()
  c <- Random.random()
  {a, b, c}
end
|> Random.with_fixed_handler(values: [0.1, 0.5, 0.9])
|> Comp.run!()
#=> {0.1, 0.5, 0.9}

with_handler(comp)

Install a random handler using Erlang's :rand module.

Uses the default random algorithm seeded from system entropy. Not deterministic across runs.

Example

comp do
  f <- Random.random()
  f
end
|> Random.with_handler()
|> Comp.run!()

with_seed_handler(comp, opts \\ [])

Install a deterministic random handler with a fixed seed.

Delegates to Random.Seed.with_handler/2.

Options

  • :seed - A seed tuple {s1, s2, s3} for the random generator. Default: {1, 2, 3}.
  • :algorithm - The random algorithm to use. Default: :exsss.

Example

comp do
  a <- Random.random()
  b <- Random.random_int(1, 10)
  {a, b}
end
|> Random.with_seed_handler(seed: {42, 42, 42})
|> Comp.run!()
#=> {0.123..., 7}  # always the same with this seed