Module Core_kernel.Quickcheck.Observer

An 'a Quickcheck.Observer.t represents a hash function on 'a. Observers are used to construct distributions of random functions; see Quickcheck.Generator.fn.

Like generators, observers have a ~size argument that is threaded through to bound the depth of recursion in potentially infinite cases. For finite values, size can be ignored.

For hashable types, one can construct an observer using of_hash. For other types, use the built-in observers and observer combinators below, or use create directly.

type -'a t
type +'a gen
val create : ('a ‑> size:Core_kernel__.Import.int ‑> Core_kernel__.Import.Hash.state ‑> Core_kernel__.Import.Hash.state) ‑> 'a t
val observe : 'a t ‑> 'a ‑> size:Core_kernel__.Import.int ‑> Core_kernel__.Import.Hash.state ‑> Core_kernel__.Import.Hash.state
val of_hash : (module Quickcheck_intf.Deriving_hash with type t = 'a) ‑> 'a t

of_hash creates an observer for any hashable type.

val bool : Core_kernel__.Import.bool t
val char : Core_kernel__.Import.char t
val doubleton : ('a ‑> Core_kernel__.Import.bool) ‑> 'a t

doubleton f maps values to two "buckets" (as described in t above), depending on whether they satisfy f.

val enum : Core_kernel__.Import.int ‑> f:('a ‑> Core_kernel__.Import.int) ‑> 'a t

enum n ~f maps values to n buckets, where f produces the index for a bucket from 0 to n-1 for each value.

val of_list : 'a Core_kernel__.Import.list ‑> equal:('a ‑> 'a ‑> Core_kernel__.Import.bool) ‑> 'a t

of_list list ~equal maps values in list to separate buckets, and compares observed values to the elements of list using equal.

val fixed_point : ('a t ‑> 'a t) ‑> 'a t

Fixed point observer for recursive types. For example:

        let sexp_obs =
          fixed_point (fun sexp_t ->
            unmap (variant2 string (list sexp_t))
              ~f:(function
                | Sexp.Atom atom -> `A atom
                | Sexp.List list -> `B list))
val recursive : ('a t ‑> 'a t) ‑> 'a t
val variant2 : 'a t ‑> 'b t ‑> [ `A of 'a | `B of 'b ] t
val variant3 : 'a t ‑> 'b t ‑> 'c t ‑> [ `A of 'a | `B of 'b | `C of 'c ] t
val variant4 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> [ `A of 'a | `B of 'b | `C of 'c | `D of 'd ] t
val variant5 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> 'e t ‑> [ `A of 'a | `B of 'b | `C of 'c | `D of 'd | `E of 'e ] t
val variant6 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> 'e t ‑> 'f t ‑> [ `A of 'a | `B of 'b | `C of 'c | `D of 'd | `E of 'e | `F of 'f ] t
val of_predicate : 'a t ‑> 'a t ‑> f:('a ‑> Core_kernel__.Import.bool) ‑> 'a t

of_predicate t1 t2 ~f combines t1 and t2, where t1 observes values that satisfy f and t2 observes values that do not satisfy f.

val comparison : compare:('a ‑> 'a ‑> Core_kernel__.Import.int) ‑> eq:'a ‑> lt:'a t ‑> gt:'a t ‑> 'a t

comparison ~compare ~eq ~lt ~gt combines observers lt and gt, where lt observes values less than eq according to compare, and gt observes values greater than eq according to compare.

val singleton : Core_kernel__.Import.unit ‑> _ t

maps all values to a single bucket.

val unmap : 'a t ‑> f:('b ‑> 'a) ‑> 'b t

unmap t ~f applies f to values before observing them using t.

val tuple2 : 'a t ‑> 'b t ‑> ('a * 'b) t
val tuple3 : 'a t ‑> 'b t ‑> 'c t ‑> ('a * 'b * 'c) t
val tuple4 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> ('a * 'b * 'c * 'd) t
val tuple5 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> 'e t ‑> ('a * 'b * 'c * 'd * 'e) t
val tuple6 : 'a t ‑> 'b t ‑> 'c t ‑> 'd t ‑> 'e t ‑> 'f t ‑> ('a * 'b * 'c * 'd * 'e * 'f) t
val fn : 'a gen ‑> 'b t ‑> ('a ‑> 'b) t

Observer for function type. fn gen t observes a function by generating random inputs from gen, applying the function, and observing the output using t.

val of_fun : (Core_kernel__.Import.unit ‑> 'a t) ‑> 'a t

of_fun f produces an observer that lazily applies f.

It is recommended that f should not do a lot of expensive work and should not be memoized. Instead, spread out the work of generating an observer over many of_fun calls combined with, e.g., variant or tuple. This allows lazily generated observers to be garbage collected after each test and the relevant portions cheaply recomputed in subsequent tests, rather than accumulating without bound over time.