2015-07-29 4 views
5

Я два генератора, gen_n & gen_arr:QuickCheck: Как объединить два генератора?

gen_n :: Gen Int 
gen_n = suchThat arbitrary (\i -> i >= 0 && i <= 10) 

gen_elem :: Gen Int 
gen_elem = suchThat arbitrary (\i -> i >= 0 && i <= 100) 

gen_arr :: Gen [Int] 
gen_arr = listOf gen_elem 

Как совместить эти два в Gen (Int, [Int])?

combine_two_gens :: Gen a -> Gen b -> Gen (a, b) 

ответ

7

(я) Вы можете использовать обычный функториальный/монадическое состав, чтобы объединить их:

gen_comb :: Gen (Int, [Int]) 
gen_comb = (,) <$> gen_elem <*> gen_arr 

(Control.Applicative.liftA2 и Control.Monad.liftM2 также хорошо, конечно)

(б) не использовать suchThat, чтобы просто ограничить диапазон. Это может быть ужасно неэффективным, поскольку он просто генерирует случайные экземпляры до тех пор, пока условие не будет выполнено, отбросив остальное. Вместо этого, вы можете использовать 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: Как отмечено ниже Зета, мы можем сделать еще лучше в этом случае, используя choose (0,100) (choose :: Random a => (a, a) -> Gen a) вместо elements [0..100]. См. here или here для получения полного списка комбинаторов генераторов.


*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 против elements:

*Main> sample (suchThat arbitrary (\i -> i >= 10000 && i <= 10005)) 
^CInterrupted. 
*Main> sample (elements [10000..10005]) 
10003 
10002 
10000 
10000 
... 

suchThat генератор не выводить ничего.

+2

Рассмотрим 'select (0,100)' вместо 'elements [0..100]'. Хотя 'elements' отлично, если ваш диапазон не является непрерывным, или если ваш тип не имеет экземпляра' Random', 'select' обычно более эффективен, если ваши значения находятся в закрытом диапазоне. – Zeta

Смежные вопросы