(i) You can use a normal functional / monadic composition to combine them:
gen_comb :: Gen (Int, [Int]) gen_comb = (,) <$> gen_elem <*> gen_arr
( Control.Applicative.liftA2 and Control.Monad.liftM2 are great too)
(ii) do not use suchThat to simply limit the range. This can be terribly inefficient as it simply generates random instances until the condition is met, discarding the rest. Instead, you can use elements :: [a] -> Gen a :
gen_elem' :: Gen Int gen_elem' = elements [0..100] gen_arr' :: Gen [Int] gen_arr' = listOf gen_elem' gen_comb' :: Gen (Int, [Int]) gen_comb' = (,) <$> elements [0..100] <*> listOf (elements [0..100])
Update: As Zeta already mentioned, in this case we can do even better by using choose (0,100) ( choose :: Random a => (a, a) -> Gen a ) instead of elements [0..100] . See here or here for a complete list of generator combinators.
*Main> sample gen_arr' [78] [2,27] [12,39] [92,22,40,6,18,19,25,13,95,99] ... *Main> sample gen_comb' (9,[23,3]) (11,[67,38,11,79]) (5,[96,69,68,81,75,14,59,68]) ...
suchThat vs. elements :
*Main> sample (suchThat arbitrary (\i -> i >= 10000 && i <= 10005)) ^CInterrupted. *Main> sample (elements [10000..10005]) 10003 10002 10000 10000 ...
The generator suchThat did not suchThat anything.