1% define arbitrary/2 and friends
    2
    3:- use_module(library(apply), [maplist/2]).    4
    5:- if(\+ predicate_property(maplist(_,  _, _),_)).    6
    7:- use_module(library(apply_macros), [maplist/3]).    8
    9:- endif.   10
   11:- use_module(library(random), [random_between/3, random_member/2, random/1]).   12:- if(\+predicate_property(random_between(_, _, _), _)).   13
   14:- use_module(library(random), [random/3]).   15
   16random_between(Lo, Hi, X) :-
   17        random(Lo, Hi, X).
   18
   19:- endif.   20
   21:- if(\+predicate_property(random_member(_, _), _)).   22
   23random_member(X, Xs) :-
   24        length(Xs, N),
   25        random_between(1, N, I),
   26        nth(I, Xs, X).
   27
   28:- endif.
 arbitrary_type(?Type) is multi
True if Type supports arbitrary/2.
   33arbitrary_type(Type) :-
   34    clause(arbitrary(Type, _), _).
   35
   36% TODO does this code make any sense?
   37:- multifile error:has_type/2.   38error:has_type(arbitrary_type, Type) :-
   39    nonvar(Type),
   40    \+ \+ quickcheck:arbitrary_type(Type).
   41
   42arbitrary(any, X) :-
   43    setof( Type
   44         , ( arbitrary_type(Type)
   45           , ground(Type)  % exclude parameterized types
   46           , Type \== any  % don't recurse
   47           )
   48         , Types
   49         ),
   50    random_member(Type, Types),
   51    arbitrary(Type, X).
   52
   53arbitrary(boolean, X) :-
   54    random_member(X, [true, false]).
   55
   56arbitrary(list, X) :-
   57    arbitrary(list(any), X).
   58
   59arbitrary(list(T), X) :-
   60    random_between(1,30,Length),
   61    length(X, Length),
   62    maplist(arbitrary(T), X).
   63
   64arbitrary(oneof(L), X) :-
   65    random_member(X, L).
   66
   67arbitrary(between(L,U), X) :-
   68    ((integer(L), integer(U)) ->
   69     random_between(L,U,X)
   70    ;
   71     random(L, U, X)
   72    ).
   73
   74arbitrary(code, X) :-
   75    random_between(0x20, 0x7e, X).  % printable ASCII
   76
   77arbitrary(codes, X) :-
   78    arbitrary(list(code), X).
   79
   80arbitrary(atom, X) :-
   81    arbitrary(codes, Codes),
   82    atom_codes(X, Codes).
   83
   84arbitrary(float, X) :-
   85    arbitrary(integer, I),
   86    random(F), 
   87    X is I * F.
   88
   89arbitrary(integer, X) :-
   90    random_between(-30000, 30000, X).
   91
   92arbitrary(string, X) :-
   93    arbitrary(codes, Codes),
   94    string_codes(X, Codes).
   95
   96arbitrary(atomic, X) :-
   97    random_member(Type, [atom,float,integer,string]),
   98    arbitrary(Type, X).
   99
  100arbitrary(chars, X) :-
  101    arbitrary(atom, Atom),
  102    atom_chars(Atom, X).
  103
  104arbitrary(text, X) :-
  105    random_member(Type, [atom, string, chars, codes]),
  106    arbitrary(Type, X).
  107
  108arbitrary(number, X) :-
  109    random_member(Type, [integer, float]),
  110    arbitrary(Type, X).
  111
  112arbitrary(natural, X) :-
  113    arbitrary(nonneg, X).
  114
  115arbitrary(nonneg, X) :-
  116    random_between(0, 30000, X).
  117
  118arbitrary(positive_integer, X) :-
  119    random_between(1, 30000, X).
  120
  121arbitrary(negative_integer, X) :-
  122    random_between(-30000, -1, X).
  123
  124arbitrary(rational, X) :-
  125    arbitrary(integer, Numerator),
  126    arbitrary(integer, Denominator),
  127    X is Numerator rdiv Denominator.
  128
  129arbitrary(encoding, X) :-
  130    setof(E, error:current_encoding(E), Encodings),
  131    random_member(X, Encodings)