The default generator will be called only if a user-defined generator does not. The user definded generator must conform to the following format:
:- func gen_f(type_desc, list(frequency), list({type_desc, list(frequency)}), list(user_gen_type), rnd, rnd) = univ. :- mode gen_f(in, in, in, list_skel_in(user_gen_inst), in, out) = out is det. :- type user_gen_type ---> { type_desc, func(type_desc, list(frequency), list({type_desc, list(frequency)}), list(user_gen_type), rnd, rnd) = univ }. % inst declaration for each user-defined generator :- inst user_gen_inst = bound({ ground, func(in, in, in, list_skel_in(user_gen_inst), in, out) = out is det }). |
func fff(int) = int mode fff(in) = out
:- module use91. :- interface. :- use_module io. :- pred main(io__state, io__state). :- mode main(di, uo) is det. %---------------------------------------------------------------------------% :- implementation. :- import_module int, list, std_util. :- import_module qcheck, rnd. main --> qcheck(qcheck__f(prop1), "user function", 100, [], [], [{type_of(some_function), gen_f}]), qcheck(qcheck__f(prop1), "no user function", 100, [], [], []). :- func gen_f(type_desc, list(frequency), list({type_desc, list(frequency)}), list(user_gen_type), rnd, rnd) = univ. :- mode gen_f(in, in, in, list_skel_in(user_gen_inst), in, out) = out is det. gen_f(_, _, _, _, RS, RS) = Univ :- Univ = univ(some_function). :- func some_function(int) = int. :- mode some_function(in) = out is det. some_function(X) = Y :- Y = 2 * X. :- func prop1(func(int)=int) = property. :- mode prop1(in(func(in)=out is det)) = out is det. prop1(FFF) = FFF(8) `===` (8 * 2). |
Sample output:
Test Description : user function Number of test cases that succeeded : 100 Number of trivial tests : 0 Number of tests cases which failed the pre-condition : 0 Distributions of selected argument(s) : Test description : no user function Falsifiable : '<<predicate>>'
The user defined generator is gen_f/6, which ignores the first 4 arguments, and assigns rnd output equal to the input since gen_f doesn't use it. (All that was trivial, basically gen_f/6 ignores all of the inputs.) And it returns some_function/1 in a univ.
:- pred qcheck(T, string, int, list(list(frequency)), list({type_desc, list(frequency)}), list(user_gen_type), io__state, io__state) <= testable(T). :- mode qcheck(in, in, in, in, in, list_skel_in(user_gen_inst), di, uo) is det. qcheck(qcheck__f(prop1), "user function", 100, [], [], [{type_of(some_function), gen_f}]),qcheck/8 is used in use91.m. The last argument takes in the user-defined generators. The format is
list(user_gen_type)
, since there is only 1 user
defined generator, the list contains 1 element : {type_of(some_function), gen_f}
.
type_of(some_function) | describes what type gen_f generates |
gen_f | is the actual generator |
The invariant function is true only if FFF(8) `===` (8 * 2)
.
The 2nd test shows a random
function will "never" do that, but the 1st test with user defined generator will always
generate the functions Y = 2 * X
:- func gen_f(type_desc, list(frequency), list({type_desc, list(frequency)}), list(user_gen_type), rnd, rnd) = univ. :- mode gen_f(in, in, in, list_skel_in(user_gen_inst), in, out) = out is det.
Argument number |
Type | Description |
---|---|---|
1 | type_desc | The type_of of the current term that the generator
is required to generate. It can be useful if the
generator is able to generate more than one type,
thus the type_desc can be used to determine which
one. |
2 | list(frequency) | Specific frequency for this term; meaningless if the term is not a discriminated union. The user can choose to ignore the setting even if the term is a discriminated union. |
3 | list({type_desc, list(frequency)}) | List of general frequency. |
4 | list(user_gen_type) | List of user-defined generators. |
5 | rnd | Random number supply. |
6 | rnd | Random number return. Let return = supply if not used. |
Look at rand_union/6
to find out how to write code that
extracts/analyses specific frequency and general frequency.
Look at gen/7
to find out how to write code that
extracts/analyses user-defined generators.