ifigueroap / racket-quickcheck

Quickcheck Clone implemented in Racket
Other
32 stars 16 forks source link

Documentation: clarify role of first argument to trans function in the arbitrary struct #28

Open 97jaz opened 7 years ago

97jaz commented 7 years ago

The documentation for the arbitrary struct says:

Represents a source of randomly generated values, except where the values are filtered by the function trans to produce a narrower set of new values.

And trans has the contract:

(-> any/c generator? generator?)

But nothing indicates how the first argument to that function is used to narrow the set.

97jaz commented 7 years ago

From reading the source and the original paper on Quickcheck, I'm getting a better sense of what's going on, but it makes me think that variant should have been provided.

97jaz commented 7 years ago

To give some background, I'm trying to produce arbitrary dates. I got this to work -- I hope correctly -- by doing this:

(require rackunit
         quickcheck
         (only-in quickcheck/generator
                  variant
                  lift->generator)
         datetime/date)

(define (choose-date lower upper)
  (define lo (date->jdn lower))
  (define hi (date->jdn upper))

  (lift->generator
   jdn->date
   (choose-integer lo hi)))

(define arbitrary-date
  (arbitrary
   (sized
    (λ (n)
      (choose-date (jdn->date (- n))
                   (jdn->date n))))
   (λ (n gen)
     (variant (if (>= n 0)
                  (* 2 n)
                  (+ (* 2 (- n)) 1))
              gen))))

This solution has a couple of deficiencies: it requires two undocumented procedures from quickcheck, and it reproduces the variant-choosing logic from the implementation of arbitrary-integer (which, I think, is to ensure that the first argument to variant is nonnegative).

Have I overlooked a better way of accomplishing this?