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.