An 'a t
a generates values of type 'a
with a specific probability distribution.
Generators are constructed as functions that produce a value from a splittable
pseudorandom number generator (see Splittable_random
), with a ~size
argument
threaded through to bound the size of the result value and the depth of recursion.
There is no prescribed semantics for size
other than that it must be non-negative.
Non-recursive generators are free to ignore it, and recursive generators need only
make sure it decreases in recursive calls and that recursion bottoms out at 0.
val create : (size:Core_kernel__.Import.int ‑> Splittable_random.State.t ‑> 'a) ‑> 'a t
val generate : 'a t ‑> size:Core_kernel__.Import.int ‑> Splittable_random.State.t ‑> 'a
Generators form a monad. t1 >>= fun x -> t2
replaces each value x
in t1
with
the values in t2
; each value's probability is the product of its probability in
t1
and t2
.
This can be used to form distributions of related values. For instance, the
following expression creates a distribution of pairs x,y
where x <= y
:
Int.gen
>>= fun x ->
Int.gen_incl x Int.max_value
>>| fun y ->
x, y
include Core_kernel__.Import.Monad.S with type a t := a t
include Base__.Monad_intf.S_without_syntax with type a t := a t
include Base__.Monad_intf.Infix with type a t := a t
module Monad_infix : Base__.Monad_intf.Infix with type a t := a t
include Core_kernel__.Import.Applicative.S with type a t := a t
val return : 'a ‑> 'a t
module Applicative_infix : sig ... end
val with_size : 'a t ‑> size:Core_kernel__.Import.int ‑> 'a t
with_size t ~size = create (fun ~size:_ random -> generate t ~size random)
val bool : Core_kernel__.Import.bool t
val char : Core_kernel__.Import.char t
val char_digit : Core_kernel__.Import.char t
val char_lowercase : Core_kernel__.Import.char t
val char_uppercase : Core_kernel__.Import.char t
val char_alpha : Core_kernel__.Import.char t
val char_alphanum : Core_kernel__.Import.char t
val char_print : Core_kernel__.Import.char t
val char_whitespace : Core_kernel__.Import.char t
val singleton : 'a ‑> 'a t
val doubleton : 'a ‑> 'a ‑> 'a t
val of_list : 'a Core_kernel__.Import.list ‑> 'a t
Produce any of the given values, weighted equally.
of_list [ v1 ; ... ; vN ] = union [ singleton v1 ; ... ; singleton vN ]
val union : 'a t Core_kernel__.Import.list ‑> 'a t
Combine arbitary generators, weighted equally.
union [ g1 ; ... ; gN ] = weighted_union [ (1.0, g1) ; ... ; (1.0, gN) ]
val of_sequence : p:Core_kernel__.Import.float ‑> 'a Sequence.t ‑> 'a t
Generator for the values from a potentially infinite sequence. Chooses each value
with probability p
, or continues with probability 1-p
. Must satisfy 0. < p &&
p <= 1.
.
val geometric : p:Core_kernel__.Import.float ‑> Core_kernel__.Import.int ‑> Core_kernel__.Import.int t
geometric ~p init
produces a geometric distribution (think "radioactive decay")
that produces init
with probability p
, and otherwise recursively chooses from
geometric ~p (init+1)
. Must satisfy 0. < p && p <= 1.
.
val small_non_negative_int : Core_kernel__.Import.int t
small_non_negative_int
produces a non-negative int of a tractable size, e.g.
allocating a value of this size should not run out of memory.
val small_positive_int : Core_kernel__.Import.int t
small_positive_int
produces a positive int of a tractable size, e.g. allocating a
value of this size should not run out of memory.
val compare_fn : 'a obs ‑> ('a ‑> 'a ‑> Core_kernel__.Import.int) t
Generator for comparison functions; result is guaranteed to be a partial order.
val equal_fn : 'a obs ‑> ('a ‑> 'a ‑> Core_kernel__.Import.bool) t
Generator for equality functions; result is guaranteed to be an equivalence relation.
val filter_map : 'a t ‑> f:('a ‑> 'b Core_kernel__.Import.option) ‑> 'b t
filter_map t ~f
produces y
for every x
in t
such that f x = Some y
.
filter t ~f
produces every x
in t
such that f x = true
.
val filter : 'a t ‑> f:('a ‑> Core_kernel__.Import.bool) ‑> 'a t
val recursive_union : 'a t Core_kernel__.Import.list ‑> f:('a t ‑> 'a t Core_kernel__.Import.list) ‑> 'a t
Generator for recursive data type with multiple clauses. At size 0, chooses only among the non-recursive cases; at sizes greater than 0, chooses among non-recursive and recursive cases, calling the recursive cases with decremented size.
type tree = Leaf | Node of tree * int * tree;;
recursive_union [return Leaf] ~f:(fun self ->
[let%map left = self
and int = Int.gen
and right = self
in Node (left, int, right)])
val weighted_recursive_union : (Core_kernel__.Import.float * 'a t) Core_kernel__.Import.list ‑> f:('a t ‑> (Core_kernel__.Import.float * 'a t) Core_kernel__.Import.list) ‑> 'a t
Like recursive_union
, with the addition of non-uniform weights for each clause.
Fixed-point generator. Use size
to bound the size of the value and the depth of
the recursion. There is no prescribed semantics for size
except that it must be
non-negative. For example, the following produces a naive generator for natural
numbers:
fixed_point (fun self ->
match%bind size with
| 0 -> singleton 0
| n -> with_size self ~size:(n-1) >>| Int.succ)
val weighted_union : (Core_kernel__.Import.float * 'a t) Core_kernel__.Import.list ‑> 'a t
weighted_union alist
produces a generator that combines the distributions of each
t
in alist
with the associated weights, which must be finite positive floating
point values.
val of_fun : (Core_kernel__.Import.unit ‑> 'a t) ‑> 'a t
of_fun f
produces a generator that lazily applies f
.
It is recommended that f
not be memoized. Instead, spread out the work of
generating a whole distribution over many of_fun
calls combined with
weighted_union
. This allows lazily generated generators to be garbage collected
after each test and the relevant portions cheaply recomputed in subsequent tests,
rather than accumulating without bound over time.
val list : 'a t ‑> 'a Core_kernel__.Import.list t
Generators for lists, choosing each element independently from the given element
generator. list
and list_non_empty
distribute size
among the list length and
the sizes of each element. list_non_empty
never generates the empty list.
list_with_length
generates lists of the given length, and distributes size
among
the sizes of the elements.
val list_non_empty : 'a t ‑> 'a Core_kernel__.Import.list t
val list_with_length : Core_kernel__.Import.int ‑> 'a t ‑> 'a Core_kernel__.Import.list t