-- 3 (find k"th element of a list)
element_at xs x = xs !! x
prop_3a xs x = (x < length xs && x >= 0) ==> element_at xs (x::Int) == (xs !! x::Int)
When prop_3a is ran through QuickCheck, it gives up, because it won't generate long enough lists.
How can I write a generator that will generate lists with length longer than the random integer?
QuickCheck is a software library, specifically a combinator library, originally written in the programming language Haskell, designed to assist in software testing by generating test cases for test suites – an approach known as property testing.
If you want to use QuickCheck in a command such as stack ghci or stack ghc , you can add it as a --package option e.g. to run a REPL to play around with QuickCheck you can use stack ghci --package QuickCheck and then write import Test. QuickCheck .
Haskell is a statically-typed functional programming language: Haskell type declarations are identified and checked during compilation, guaranteeing that program semantics are known by the designers before execution or possibly even before the implementation.
hammar's answer is perfectly adequate for the problem. But for the sake of answering the precise question asked, I couldn't help but investigate a bit. Let's use forAll
.
prop_bang x = x >= 0 ==> forAll (listLongerThan x) $ \xs ->
element_at xs x == xs !! x
So now we need a function, listLongerThan :: Int -> Gen [Int]
. It takes a length, x, and produces a generator which will produce lists of length greater than x
.
listLongerThan :: Int -> Gen [Int]
listLongerThan x = replicateM (x+1) arbitrary
It's rather straightforward: we simply take advantage of the Monad instance of Gen
. If you run quickCheck prop_bang
, you'll notice it starts taking quite a long time, because it begins testing absurdly long lists. Let's limit the length of the list, to make it go a bit faster. Also, right now listLongerThan
only generates a list that is exactly x+1
long; let's mix that up a bit, again utilizing the Monad instance of Gen.
prop_bang =
forAll smallNumber $ \x ->
forAll (listLongerThan x) $ \xs ->
element_at xs x == xs !! x
smallNumber :: Gen Int
smallNumber = fmap ((`mod` 100) . abs) arbitrary
listLongerThan :: Int -> Gen [Int]
listLongerThan x = do
y <- fmap (+1) smallNumber -- y > 0
replicateM (x+y) arbitrary
You can use sample smallNumber
or sample (listLongerThan 3)
in ghci to make sure it is generating the correct stuff.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With