How do I do this? I want something with the structure sevenList :: Gen [Integer]
that generates a list and that is guaranteed to always include at least one 7.
I know that if I wanted to generate a list of size n, I could do something like this:
listOfLength n gen = sequence [ gen | i <- [1..n] ]
But this is not sufficient because if I for example generate a list of length 10 and a 7 is not generated I have to continue, but at the moment it wont.
You can decide to generate two lists, and then construct a list where we append the lists with a seven sandwiched between them.
For instance:
genSevenList :: Gen [Integer]
genSevenList = do
la <- arbitrary
lb <- arbitrary
return $ la ++ 7 : lb
The first two statements thus generate two arbitrary [Integer]
lists, and then we return $ la ++ 7 : lb
. We thus prepend lb
with 7
, and append this to la
.
You can also generate one arbitrary list, split it at a random index and then join these parts together as described above. For instance:
genSevenList :: Gen [Integer]
genSevenList = do
l <- arbitrary
k <- choose (0,length l)
let (la,lb) = splitAt k l
return $ la ++ 7 : lb
Although both are capable of generating all possible lists, like @leftroundabout says, it is more likely that the second implementation will come up with shorter lists, since the odds that both aribtrary
calls will generate a short list (or an empty list) is not that large.