Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell QuickCheck generate random data for function with many input variables

I have a function with the following type signature

rndListIndex :: Double -> Double -> Double -> Double
rndListIndex maxIdx r1 r2 = …
  • the first input should be a value coming from a non-negative strictly positive integer
  • the second and third input are required to be within the closed interval [0.0,1.0] otherwise the function makes no sense

the function has the property of

prop_alwaysLessThanMaxIdx idx r1 r2 = (rndListIndex idx r1 r2 <= idx)

how do I generate random data for maxIdx and r1,r2 separately; I know of the function choosebut do not know how to use it with more than one input variable.

For now I have tested the Property with fixed idx, which is not the way it should be tested.

like image 678
epsilonhalbe Avatar asked Aug 23 '13 17:08

epsilonhalbe


People also ask

How is test data generated In QuickCheck?

In QuickCheck, test data is produced by test generators whose types are of the form Gen a. Gen a is a generator for values of type a. A type can define a default test data generator by defining an instance of the class Arbitrary:

How to get the counterexample as a Haskell value?

If you want to get the counterexample as a Haskell value, rather than just printing it, try the quickcheck-with-counterexamples package. Args specifies arguments to the QuickCheck driver

How do I run more tests with QuickCheck?

To run more tests you can use the withMaxSuccess combinator: >>> quickCheck (withMaxSuccess 10000 prop_reverse) +++ OK, passed 10000 tests. To use QuickCheck on your own data types you will need to write Arbitrary instances for those types.

What is the purpose of the return[] statement in Haskell?

For the curious, the return [] is a Template Haskell splice that makes GHC insert the empty list of declarations at that point in the program; GHC typechecks everything before the return [] before it starts on the rest of the module, which means that the later call to quickCheckAll can see everything that was defined before the return [].


1 Answers

You have to use the forAll function from QuickCheck. It has the following type:

forAll :: (Show a, Testable prop) 
       => Gen a           -- ^ The generator to use for generating values
       -> (a -> prop)     -- ^ A function which returns a testable property
       -> Property                  

forAll takes two arguments:

  • The generator describes how to generate values. Examples of generators are choose, arbitrary, oneof, ...
  • The function tests the property for the given input. It must return a value that is an instance of Testable, for example another Property, Bool or a function.

Example of a nested forAll with the choose and elements generators:

-- This generates a Property p for all x's in the closed interval [1,3]
-- The property p in turn generates a property q for all y ∈ [4,5]
-- The property q is True if x < y.
prop_choose = forAll (choose (1,3)) $ \x ->
              forAll (elements [4,5]) $ \y -> x < y

For your test property, you can use forAll with choose for the second and third argument. For the first argument, there is the Positive a type in QuickCheck which can be used to generate arbitrary positive values of type a (It has an Arbitrary instance when a is a Num):

prop_alwayLessThanMaxIdx :: Positive Integer -> Property
prop_alwaysLessThanMaxIdx (Positive idx) = 
  forAll (choose (0,1)) $ \r1 ->
  forAll (choose (0,1)) $ \r2 ->
   (rndListIndex idx r1 r2) < idx
like image 176
bennofs Avatar answered Sep 21 '22 23:09

bennofs