I have a function with the following type signature
rndListIndex :: Double -> Double -> Double -> Double
rndListIndex maxIdx r1 r2 = …
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 choose
but 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.
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:
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
I would suggest defining your own type that wraps Double
and give it an Arbitrary
instance that only generates numbers between 0 and 1. Something like:
import Test.QuickCheck
newtype UnitInterval = Unit Double deriving Show
instance Arbitrary UnitInterval where
arbitrary = fmap Unit (choose (0, 1))
shrink (Unit x) = [ Unit y | y <- shrink x, 0 <= y && y <= 1 ]
For generating idx
, you can use QuickCheck's Positive
modifier, as @bennoffs suggested (you will have to import Test.QuickCheck.Modifiers
). This is similar to the UnitInterval
type I defined above, but generates positive numbers instead of numbers between 0 and 1. Your property will then look like:
prop_alwaysLessThanMaxIdx (Positive idx) (Unit r1) (Unit r2) =
rndListIndex idx r1 r2 <= idx
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.