(std test gen)

Reference

Overview

Generators of test values that draw through a recorder, so that a failing case shrinks by replaying fewer and smaller draws.

(import (std prelude))
(import (std test gen))

(type (: Suit (Union Hearts Spades Clubs Diamonds)))
(type (: Card (Record (: rank int) (: suit Suit))))

(: gen-card (Gen Card))
(def gen-card
  (gen-let ((rank (gen-int-range 1 13))
            (suit (gen-element (list Hearts Spades Clubs Diamonds))))
    (Card (rank rank) (suit suit))))

(impl (Arbitrary Card) (defun (arbitrary) gen-card))

(gen-sample gen-card)                ; one card
(gen-samples (gen-list gen-int) 5)   ; five lists, small ones first

A (Gen T) makes values of type T. Property tests in (std test prop) use generators, but this module does not import (std test). A program can use the generators without the test runner, for example to make fixtures.

The recorder. A generator does not read a RandomSource itself. It asks a Choices for numbers with draw. A Choices has one of two modes:

draw records the number after it puts it into its bound, not the raw random number. So a recorded vector replays to the same value, and a changed vector replays to a value that is still in range.

Smaller draws give simpler values. (std test prop) shrinks a failing case: it makes the recorded vector smaller and replays it. This gives a simpler value only when each generator obeys this rule: 0 is the simplest choice at every draw, and a larger draw gives a value farther from the simplest. Because a used-up vector answers 0, a shorter vector also gives a simpler value. Thus no generator needs a shrinker of its own. Every generator in this module obeys the rule:

A generator made from these with gen-map, gen-bind, gen-let and the other combinators obeys the rule too.

A generator of your own. Build it from the generators above when you can: it then obeys the rule without more work. A generator made with make-gen that calls draw itself must obey the rule on its own:

A generator that breaks the rule still works: its values are as random as before. Only its failing cases shrink less well.

Sizes. A Choices has a size, which choices-size gives. Numbers, lists and recursive values grow with it. A property’s first runs have small sizes and its last runs large ones, so small cases are tried first. gen-sized reads the size, and gen-resize changes it.

Edge values. The number and text generators give values that often find bugs: int-max, -1, NaN when asked for, surrogate pairs, combining characters. An edge of an integer is recorded as the draws that the full-range way to the same value would record. So shrinking can change the draw that chose the edge, keep the value, and then make the value smaller.

Discarded runs. A generator can give up: gen-such-that after 100 tries, and any generator after 10000 draws. It then calls discard!, which marks the Choices and raises an exception. (std test prop) does not count a discarded run.

Gen is not a Monad. The callback of the bind of a Monad can be a bjoroutine, but a generator runs inside an ordinary function. Use gen-let to draw values in order, or gen-bind.

Defaults by type. The trait Arbitrary gives a generator for a type. (for-all ((: xs (List int))) ...) uses it. An instance is only a generator, because shrinking needs nothing more.

See also: Gen, draw, gen-let, Arbitrary, gen-sample

Reference

Types

Functions

Values

Macros

Types

Choices

record ↑ Types

Where a generator gets its numbers: from a random source, recorded, or from a recorded vector, replayed.

A Choices records every number that it answers, in both modes. After a replay, the record is the part of the vector that the replay used, followed by the zeros it answered after the vector was used up. A Choices also holds the size of the run, and whether the run was discarded.

A Choices is for one run of a generator. Make a new one for each run.

See also: recording-choices, replaying-choices, draw, choices-draws

Gen

record ↑ Types

A generator of values of type %a.

%a
The type of the values.

A generator is a function from a Choices to a value. Make one from the generators and combinators of this module, or with make-gen.

See also: make-gen, gen-run, gen-let, Arbitrary

Arbitrary

trait ↑ Types

The generator that a type has when a property names no generator.

%a
The type that the generator makes.
(impl (Arbitrary Card) (defun (arbitrary) gen-card))

;; In (std test prop): (: xs (List Card)) uses it.
(for-all ((: xs (List Card)))
  (check (= (list-length (list-sort xs)) (list-length xs))))

This module has instances for bool, int, long, ulong, bigint, double (without NaN and the infinities), char, string, void, Option, Result, tuples of two and three, List, Vec, Map, HashSet, OrderedMap and OrderedSet. An instance for a container needs instances for the types in it.

An instance is only a generator. It has no shrinker, because shrinking replays smaller draws. A generator in an instance must obey the rule that smaller draws give simpler values.

See also: arbitrary, Gen

Functions

recording-choices

function ↑ Functions

(: recording-choices (-> RandomSource int Choices))
(recording-choices rng size)

A Choices that draws from a random source and records each number.

rng
The source to draw from.
size
The size of the run. Numbers, lists and recursive values grow with it.
returns
A new Choices, with nothing recorded.
(def c (recording-choices (make-random/seed64 3UL) 60))
(def v (gen-run (gen-list gen-int) c))
(choices-draws c)   ; the draws that replay to v

See also: replaying-choices, choices-draws

replaying-choices

function ↑ Functions

(: replaying-choices (-> (Vec ulong) int Choices))
(replaying-choices draws size)

A Choices that answers the numbers of a vector in order, and 0 after the vector is used up.

draws
The numbers to answer, usually from choices-draws.
size
The size of the run. Give the size of the recording, or a replay can give a different value.
returns
A new Choices, with nothing recorded.
(gen-run g (replaying-choices (choices-draws c) 60))   ; the value again
(gen-run g (replaying-choices (vec-empty) 60))         ; the simplest value of g

A number of the vector is put into the bound of its draw. So a vector that was changed, for example by shrinking, still gives a value in range.

See also: recording-choices, choices-draws

draw

function ↑ Functions

(: draw (-> Choices ulong ulong))
(draw c bound)

A number from 0, included, to bound, not included. Every generator is made from this.

c
The choices to draw from.
bound
The bound. 0 means every ulong.
returns
A number in [0, bound). A replay answers the next number of its vector, put into the bound, or 0 when the vector is used up.
raises ArgumentException
When the run drew 10000 numbers before. The run is then discarded: see discard!.
;; A die. A draw of 0 gives 1, the simplest value.
(def gen-die (make-gen (fun (c) (+ 1 (cast System.Int32 (draw c 6UL))))))

The number is recorded after it is put into the bound. Map 0 to the simplest value, and larger numbers to values farther from it, so that shrinking makes values simpler.

A recording puts a random number into the bound with a remainder, so a bound that is not a power of 2 makes small numbers slightly more likely.

See also: choices-size, discard!

choices-size

function ↑ Functions

(: choices-size (-> Choices int))
(choices-size c)

The size of the run.

c
The choices.
returns
The size given when the choices were made, or the size that gen-resize set.

See also: gen-sized, gen-resize

choices-draws

function ↑ Functions

(: choices-draws (-> Choices (Vec ulong)))
(choices-draws c)

Every number that the choices answered, in order.

c
The choices.
returns
The record. Replayed with replaying-choices, at the same size, it gives the same value.

After a replay, the record is the part of the vector that was used, and a 0 for each draw after the vector was used up.

See also: replaying-choices

choices-discarded?

function ↑ Functions

(: choices-discarded? (-> Choices bool))
(choices-discarded? c)

Whether the run was discarded.

c
The choices.
returns
#t after discard!.

A discarded run ends with an exception. The code that ran the generator examines this flag, not the exception, to tell a discard from a failure.

See also: discard!

discard!

function ↑ Functions

(: discard! (-> Choices string %a))
(discard! c why)

Marks the run as discarded and leaves it with an exception.

c
The choices of the run.
why
Why the run is discarded. It is the message of the exception, after discarded: .
returns
Nothing: it always raises. The result type fits any position.
raises ArgumentException
Always.

Use it in a generator that can not make a good value from its draws. (std test prop) does not count a discarded run, and fails a property when more than 10 times its runs are discarded.

See also: choices-discarded?, gen-such-that

make-gen

function ↑ Functions

(: make-gen (-> (-> Choices %a) (Gen %a)))
(make-gen f)

A generator from a function that draws from a Choices.

f
The function. It gets the choices of the run, and answers a value.
returns
The generator.
(: gen-even (Gen int))
(def gen-even
  (make-gen (fun (c) (* 2 (cast System.Int32 (draw c 1000UL))))))

The function must get all its numbers from the choices, through draw or other generators. It must map a draw of 0 to the simplest value, or shrinking does not make its values simpler.

See also: draw, gen-run

gen-run

function ↑ Functions

(: gen-run (-> (Gen %a) Choices %a))
(gen-run g c)

Runs a generator with the choices of a run.

g
The generator.
c
The choices.
returns
The value that g makes from the draws of c.
(gen-run gen-int (replaying-choices (vec-empty) 50))   ; 0

See also: make-gen, gen-sample

gen-sample

function ↑ Functions

(: gen-sample (-> (Gen %a) (#:size int) (#:rng RandomSource) %a))
(gen-sample g #:size 30 #:rng (make-random))

One value of a generator.

g
The generator.
#:size
The size of the run.
#:rng
The source to draw from. A new source each call when not given.
returns
A value that g makes.
(gen-sample (gen-list gen-int))
(gen-sample gen-string #:size 5 #:rng (make-random/seed64 1UL))

See also: gen-samples

gen-samples

function ↑ Functions

(: gen-samples (-> (Gen %a) int (#:size int) (#:rng RandomSource) (List %a)))
(gen-samples g n #:size 100 #:rng (make-random))

Values of a generator, at sizes that grow as the runs of a property do.

g
The generator.
n
How many values.
#:size
The size of the last value.
#:rng
The source to draw from. A new source each call when not given.
returns
n values. The first is made at size 1 and the last at size, with sizes evenly between.
(gen-samples (gen-list gen-int) 20 #:rng (make-random/seed64 1UL))

Each value draws from its own source, split from rng. The same seed gives the same values.

See also: gen-sample

gen-pure

function ↑ Functions

(: gen-pure (-> %a (Gen %a)))
(gen-pure x)

A generator that always makes x and draws nothing.

x
The value.
returns
The generator.

See also: gen-element

gen-map

function ↑ Functions

(: gen-map (-> (-> %a %b) (Gen %a) (Gen %b)))
(gen-map f g)

A generator whose values are those of another, with a function applied.

f
The function.
g
The generator.
returns
A generator of the results of f.
(def gen-even (gen-map (fun (n) (* 2 n)) gen-int))

gen-map applies a function to values. The generator of a prelude Map is gen-map-of.

See also: gen-bind, gen-let

gen-bind

function ↑ Functions

(: gen-bind (-> (Gen %a) (-> %a (Gen %b)) (Gen %b)))
(gen-bind g f)

A generator that draws a value, and then draws from the generator that a function makes from it.

g
The first generator.
f
A function from the first value to the next generator. It must be an ordinary function, not a bjoroutine.
returns
The generator.
;; A list and an index into it.
(gen-bind (gen-such-that (fun (xs) (not (list-empty? xs))) (gen-list gen-int))
          (fun (xs) (gen-map (fun (i) (Tuple xs i))
                             (gen-int-range 0 (- (list-length xs) 1)))))

Both generators draw from the same choices, so shrinking makes both values simpler. gen-let writes the same thing with names.

See also: gen-let, gen-map

gen-such-that

function ↑ Functions

(: gen-such-that (-> (-> %a bool) (Gen %a) (Gen %a)))
(gen-such-that pred g)

A generator of the values of g for which pred holds.

pred
The condition.
g
The generator.
returns
A generator that runs g until pred holds.
(gen-such-that even? gen-int)

After 100 values for which pred does not hold, the run is discarded. A condition that few values satisfy tests little, so a property whose runs are discarded too often fails. Prefer a generator that makes good values directly, for example (gen-map (fun (n) (* 2 n)) gen-int) instead of (gen-such-that even? gen-int).

See also: discard!

gen-one-of

function ↑ Functions

(: gen-one-of (-> (List (Gen %a)) (Gen %a)))
(gen-one-of gens)

A generator that makes a value with one of the generators, each equally likely.

gens
The generators. The first is the simplest: a draw of 0 chooses it.
returns
The generator.
raises ArgumentException
When gens is empty.
(gen-one-of (list (gen-pure 0) (gen-int-range 1 9) gen-int))

See also: gen-frequency, gen-element

gen-frequency

function ↑ Functions

(: gen-frequency (-> (List (Tuple int (Gen %a))) (Gen %a)))
(gen-frequency choices)

A generator that makes a value with one of the generators, chosen by weight.

choices
Pairs of a weight and a generator. A generator is chosen with a probability of its weight divided by the sum of the weights. The first is the simplest.
returns
The generator.
raises ArgumentException
When the sum of the weights is not above 0.
(gen-frequency (list (Tuple 1 (gen-pure None))
                     (Tuple 3 (gen-map Some gen-int))))

A generator with a weight of 0 is never chosen. Give no weight less than 0.

See also: gen-one-of

gen-element

function ↑ Functions

(: gen-element (-> (List %a) (Gen %a)))
(gen-element xs)

A generator that makes one of the values, each equally likely.

xs
The values. The first is the simplest: a draw of 0 chooses it.
returns
The generator.
raises ArgumentException
When xs is empty.
(gen-element (list Hearts Spades Clubs Diamonds))

See also: gen-one-of, gen-shuffle

gen-sized

function ↑ Functions

(: gen-sized (-> (-> int (Gen %a)) (Gen %a)))
(gen-sized f)

A generator that a function makes from the size of the run.

f
A function from the size to a generator.
returns
The generator.
;; A list of exactly size elements.
(gen-sized (fun (n) (gen-list-of-length n gen-int)))

See also: choices-size, gen-resize

gen-resize

function ↑ Functions

(: gen-resize (-> int (Gen %a) (Gen %a)))
(gen-resize n g)

A generator that runs g at another size.

n
The size for g.
g
The generator.
returns
The generator. After g, the size is again what it was.
(gen-resize 5 (gen-list gen-int))   ; short lists at every size

See also: gen-sized

gen-recursive

function ↑ Functions

(: gen-recursive (-> (Gen %a) (-> (Gen %a) (Gen %a)) (Gen %a)))
(gen-recursive base step)

A generator of a recursive type, which halves the size at each level so that its values end.

base
The generator of the base case, such as a leaf.
step
A function from a generator of the smaller parts to a generator of one level.
returns
The generator.
(type (: Tree (Union Leaf (: Node Tree int Tree))))

(: gen-tree (Gen Tree))
(def gen-tree
  (gen-recursive (gen-pure Leaf)
                 (fun (self) (gen-let ((l self) (x gen-int) (r self))
                               (Node l x r)))))

At size 0 or less, it makes the base case. At a larger size, a draw chooses: a draw of 0 makes the base case, and the others call step with this generator at half the size. Thus a case shrinks toward the base case. The base case comes at one draw in four, and always when the size reaches 0.

See also: gen-sized

gen-int-range

function ↑ Functions

(: gen-int-range (-> int int (Gen int)))
(gen-int-range lo hi)

An int from lo to hi, both included, each equally likely.

lo
The smallest value.
hi
The largest value. Not less than lo.
returns
The generator.
raises ArgumentException
When lo is above hi.
(gen-int-range 1 6)   ; a die

The simplest value is the one nearest 0: lo when the range is above 0, hi when it is below 0, and 0 when the range contains 0. A range that contains 0 draws the sign first, then the distance from 0. So a value shrinks toward 0.

See also: gen-int, gen-long-range

gen-long-range

function ↑ Functions

(: gen-long-range (-> long long (Gen long)))
(gen-long-range lo hi)

A long from lo to hi, both included, each equally likely.

lo
The smallest value.
hi
The largest value. Not less than lo.
returns
The generator.
raises ArgumentException
When lo is above hi.

The simplest value is the one nearest 0, as for gen-int-range. The range can be all the longs.

See also: gen-long, gen-int-range

gen-double

function ↑ Functions

(: gen-double (-> (#:special bool) (Gen double)))
(gen-double #:special #f)

A double that grows with the size, with edge values now and then. 0.0 is the simplest.

#:special
#t to add NaN, positive infinity and negative infinity to the edges.
returns
The generator.
(gen-double)
(gen-double #:special #t)   ; also NaN and the infinities

9 times in 10, a whole part from -size² to size², with a fraction of 53 bits added away from 0. 1 time in 10, an edge: 0.0, 1.0, -1.0, the largest and the smallest doubles, the smallest double above 0, and -0.0. NaN and the infinities find bugs, but many properties do not hold for them, so they come only with #:special #t.

See also: gen-int

gen-string-of

function ↑ Functions

(: gen-string-of (-> (Gen char) (Gen string)))
(gen-string-of g)

A string of the characters of a generator, whose length grows with the size.

g
The generator of the characters.
returns
The generator. The empty string is the simplest.
(gen-string-of (gen-element (string->list "ACGT")))   ; DNA

See also: gen-string, gen-list

gen-option

function ↑ Functions

(: gen-option (-> (Gen %a) (Gen (Option %a))))
(gen-option g)

None, or Some value of g. None is the simplest.

g
The generator of the value.
returns
The generator. It makes None 1 time in 4.

See also: gen-result

gen-result

function ↑ Functions

(: gen-result (-> (Gen %e) (Gen %a) (Gen (Result %e %a))))
(gen-result ge ga)

Ok with a value of ga, or Err with a value of ge, equally likely. Ok is the simplest.

ge
The generator of the error.
ga
The generator of the value.
returns
The generator.

See also: gen-option

gen-tuple2

function ↑ Functions

(: gen-tuple2 (-> (Gen %a) (Gen %b) (Gen (Tuple %a %b))))
(gen-tuple2 ga gb)

A pair of values, the first drawn first.

ga
The generator of the first value.
gb
The generator of the second value.
returns
The generator.

See also: gen-tuple3, gen-tuple4, gen-let

gen-tuple3

function ↑ Functions

(: gen-tuple3 (-> (Gen %a) (Gen %b) (Gen %c) (Gen (Tuple %a %b %c))))
(gen-tuple3 ga gb gc)

A tuple of three values, drawn in order.

ga
The generator of the first value.
gb
The generator of the second value.
gc
The generator of the third value.
returns
The generator.

See also: gen-tuple2, gen-tuple4

gen-tuple4

function ↑ Functions

(: gen-tuple4 (-> (Gen %a) (Gen %b) (Gen %c) (Gen %d) (Gen (Tuple %a %b %c %d))))
(gen-tuple4 ga gb gc gd)

A tuple of four values, drawn in order.

ga
The generator of the first value.
gb
The generator of the second value.
gc
The generator of the third value.
gd
The generator of the fourth value.
returns
The generator.

Arbitrary has no instance for tuples of four. Name this generator in the binding.

See also: gen-tuple2, gen-tuple3

gen-list

function ↑ Functions

(: gen-list (-> (Gen %a) (Gen (List %a))))
(gen-list g)

A list of values of g, whose length grows with the size. The empty list is the simplest.

g
The generator of the elements.
returns
The generator.
(gen-list gen-int)
(gen-list (gen-int-range 0 20))

Before each element, a draw tells whether there is one more element, and 0 tells that there is not. So shrinking makes a list shorter when it deletes draws, and ends it when it sets such a draw to 0.

The length is 1 + size / 5 on average: 1 at size 0, and 21 at size 100. A list has at most 1000 elements, at any size.

See also: gen-list-of-length, gen-vec, gen-array

gen-list-of-length

function ↑ Functions

(: gen-list-of-length (-> int (Gen %a) (Gen (List %a))))
(gen-list-of-length n g)

A list of exactly n values of g.

n
The length.
g
The generator of the elements.
returns
The generator.

The length does not shrink. Use gen-list when the length is part of what to test.

See also: gen-list

gen-vec

function ↑ Functions

(: gen-vec (-> (Gen %a) (Gen (Vec %a))))
(gen-vec g)

A vec of values of g, as gen-list makes.

g
The generator of the elements.
returns
The generator. The empty vec is the simplest.

See also: gen-list, gen-array

gen-array

function ↑ Functions

(: gen-array (-> (Gen %a) (Gen (Array %a))))
(gen-array g)

A new array of values of g, as gen-list makes.

g
The generator of the elements.
returns
The generator. The empty array is the simplest. Each value is a new array.

See also: gen-list, gen-vec

gen-shuffle

function ↑ Functions

(: gen-shuffle (-> (List %a) (Gen (List %a))))
(gen-shuffle xs)

A permutation of the values. The order of xs is the simplest.

xs
The values.
returns
The generator.

Fisher-Yates from the front: element i changes places with an element at i or after it, and a draw of 0 keeps it at i. So a case shrinks toward the order of xs.

See also: gen-element

gen-map-of

function ↑ Functions

(: gen-map-of (-> (Gen %k) (Gen %v) (Gen (Map %k %v))))
(gen-map-of gk gv)

A prelude Map, made from a gen-list of keys and values.

gk
The generator of the keys.
gv
The generator of the values.
returns
The generator. The empty map is the simplest.

The map shrinks as its list of entries does. When the list has a key more than once, the last value wins. So the map can have fewer entries than the list.

See also: gen-orderedmap, gen-list

gen-hashset

function ↑ Functions

(: gen-hashset (-> (Gen %a) (Gen (HashSet %a))))
(gen-hashset g)

A HashSet, made from a gen-list of its elements.

g
The generator of the elements.
returns
The generator. The empty set is the simplest.

See also: gen-orderedset, gen-list

gen-orderedmap

function ↑ Functions

(: gen-orderedmap (-> (Gen %k) (Gen %v) (Gen (OrderedMap %k %v))))
(gen-orderedmap gk gv)

An OrderedMap, made from a gen-list of keys and values.

gk
The generator of the keys.
gv
The generator of the values.
returns
The generator. The empty map is the simplest.

When the list has a key more than once, the last value wins.

See also: gen-map-of, gen-list

gen-orderedset

function ↑ Functions

(: gen-orderedset (-> (Gen %a) (Gen (OrderedSet %a))))
(gen-orderedset g)

An OrderedSet, made from a gen-list of its elements.

g
The generator of the elements.
returns
The generator. The empty set is the simplest.

See also: gen-hashset, gen-list

arbitrary

function ↑ Functions

(: arbitrary (-> (Gen %a)))

The generator of a type. The type of the result chooses the instance.

returns
The generator of the instance for that type.
(def (: g (Gen (List int))) (arbitrary))
(def (: cards (List Card)) (gen-samples (arbitrary) 10))

It takes no arguments. Write the type where the result goes, for example with (def (: name Type) ...).

See also: Arbitrary

Values

gen-bool

value ↑ Values

(: gen-bool (Gen bool))

#t or #f, equally likely. #f is the simplest.

See also: gen-element

gen-int

value ↑ Values

(: gen-int (Gen int))

An int that grows with the size, with edge values now and then. 0 is the simplest.

A first draw chooses the kind of value:

An edge is recorded as the draws for “any int” that give it. So shrinking changes the kind of an edge to “any int”, keeps the value, and can then make the value smaller.

See also: gen-int-range, gen-long

gen-long

value ↑ Values

(: gen-long (Gen long))

A long that grows with the size, with edge values now and then. 0 is the simplest.

As gen-int, but over the longs. The edges are 0, 1, -1, long-max, long-min, int-max, int-min and 2³².

See also: gen-long-range, gen-int

gen-ulong

value ↑ Values

(: gen-ulong (Gen ulong))

A ulong that grows with the size, with edge values now and then. 0 is the simplest.

8 times in 10, a value from 0 to size². 1 time in 10, any ulong. 1 time in 10, an edge: 0, 1, the largest ulong, 2⁶³ or 2³². An edge is recorded as the draws for “any ulong” that give it, as for gen-int.

See also: gen-long

gen-bigint

value ↑ Values

(: gen-bigint (Gen bigint))

A bigint: usually a long, and sometimes a value beyond the range of a long. 0 is the simplest.

3 times in 4, a value of gen-long. 1 time in 4, that value multiplied by a number from 0 to 2⁶⁴, so most such values are beyond the range of a long.

See also: gen-long

gen-char

value ↑ Values

(: gen-char (Gen char))

Any Unicode scalar value, mostly printable ASCII, with characters that find bugs now and then. #\a is the simplest.

A first draw chooses the kind of character:

See also: gen-ascii-char, gen-string

gen-ascii-char

value ↑ Values

(: gen-ascii-char (Gen char))

A printable ASCII character, from space to ~. #\a is the simplest.

The 95 characters are put in an order that starts at #\a: the letters come before the digits and the punctuation. A case shrinks toward a letter, which is easy to read.

See also: gen-char, gen-ascii-string

gen-string

value ↑ Values

(: gen-string (Gen string))

A string of gen-char characters, whose length grows with the size. The empty string is the simplest.

The length is as for gen-list. Because of gen-char, it sometimes has surrogate pairs, combining characters and other characters that find bugs.

See also: gen-ascii-string, gen-string-of, gen-char

gen-ascii-string

value ↑ Values

(: gen-ascii-string (Gen string))

A string of printable ASCII characters, whose length grows with the size. The empty string is the simplest.

See also: gen-string, gen-ascii-char

gen-unit

value ↑ Values

(: gen-unit (Gen void))

Always unit. It draws nothing.

See also: gen-pure

Macros

gen-let

macro ↑ Macros

(gen-let ((name gen) ...) body ...)

A generator that draws each binding in order, as let* binds, and makes the value of the body.

name
The name of the value.
gen
The generator of the value. It can use the names of the bindings before it.
body ...
The forms that make the value from the names. At least one form.
(: gen-card (Gen Card))
(def gen-card
  (gen-let ((rank (gen-int-range 1 13))
            (suit (gen-element (list Hearts Spades Clubs Diamonds))))
    (Card (rank rank) (suit suit))))

;; A later generator uses an earlier value.
(gen-let ((n (gen-int-range 0 10))
          (xs (gen-list-of-length n gen-int)))
  (Tuple n xs))

Gen is not a Monad, so (do ...) does not make generators. gen-let is the way to draw values in order. All the bindings draw from the same choices.

See also: gen-bind, gen-map