liveBook · Manning

Pseudo-random number generator

As explained in Learn Haskell by Example

A random value generator is a computation that produces random or pseudo-random values, often with controlled variation in size or complexity.

A pseudo-random number generator computes a value from a state, then returns an updated state. Passing that new state into the next call produces a sequence while keeping the computation pure: the same input state gives the same result. section 9.1.2

Listing 9.2 Functions to explicitly work with random state
newtype RandomState = RandomState Int
 deriving (Eq, Show)  #1

randomInt :: RandomState -> (Int, RandomState)
randomInt (RandomState rs) = (newRs, RandomState newRs)  #2
  where
    newRs = (1103515245 * rs + 12345) `mod` (2 ^ 31)  #3

randomIntList :: RandomState -> Int -> [Int]
randomIntList rs n
  | n <= 0 = []                        #4
  | otherwise =
    let (v, rs') = randomInt rs        #4
     in v : randomIntList rs' (n - 1)  #4

This explicit generator threads `RandomState` through each call. `randomInt` applies a linear congruential transformation; `randomIntList` feeds the returned state back recursively to build integer values. section 9.1.2

For ordinary programs, `System.Random` supplies generation functions for multiple types instead of requiring a custom numeric generator. Pure code carries generator state through arguments and results; IO actions can access a global generator. section 9.1.2 section 9.6

Random generators become most useful in property testing when they can create inputs that fit the property:

  • Generate many lists to check that a sorting function returns sorted output, reporting the input when a test fails. section 9.1.5
  • Compose generators rather than writing an unrelated generator for every data type or input condition. section 9.1.5
  • Restrict generated values when a property has preconditions, such as requiring a nonempty alphabet containing the tested character. section 9.3.1
  • Use QuickCheck’s type-driven generators; `Arbitrary` also supports shrinking failures to smaller or simpler values. section 9.6

Testing a rotation property

A property for alphabet rotation expects the rotated character to remain in its alphabet. Unconstrained generation quickly finds that an empty alphabet violates this expectation, revealing that valid test data must satisfy the property’s assumptions. section 9.3.1

For referentially transparent functions, random inputs need no simulated external environment: correctness can be checked by comparing input-derived outputs against a predicate. Generator choice and property interpretation determine whether such a test is valid. section 9.2.1

How Learn Haskell by Example covers it

How deep it goes
Explains explicit state threading with a linear congruential generator, then defers general generation to System.Random and QuickCheck.
Examples
Demonstrates a state-threaded integer list, sorting tests, and an alphabet-rotation property falsified by invalid generated inputs.
What it assumes
Introduces random-state handling from zero while relying on Haskell purity and function input-output behavior.
What you can do after
Apply it via QuickCheck or custom generators to provide randomized, constrained inputs for pure-function properties.
How it connects
Connects pseudo-random generation to property testing, referential transparency, IO, System.Random, QuickCheck, and Arbitrary.

Also explained in

Compare how 10 books explain pseudo-random number generator →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Haskell by Example. The section links point to the parts of the book it draws on.