QuickCheck: определение произвольного экземпляра с точки зрения других арбитров

Я использую QuickCheck 1, и у меня есть следующие типы данных:

data A = ...
instance Arbitrary A where ...
data B = ...
instance Arbitrary B where ...
data C = C A B

Теперь я хотел бы определить экземпляр Arbitrary для C, чтобы значения C генерировались с использованием существующих генераторов для A и B. Я закончил это:

instance Arbitrary C where
  arbitrary = elements [(C a b) |
                        a <- generate 20 (System.Random.mkStdGen 0) arbitrary,
                        b <- generate 20 (System.Random.mkStdGen 0) arbitrary]

Является ли это явное генерирование фиксированного числа значений для A и B необходимым, или есть лучший способ объединения существующего Arbitraries в новый?

Ответ 1

Я бы сделал это вот так:

instance Arbitrary C
  where arbitrary = do a <- arbitrary
                       b <- arbitrary
                       return (C a b)

Хотя sclv-идея использования liftM2 из Control.Monad, вероятно, лучше:

instance Arbitrary C
  where arbitrary = liftM2 C arbitrary arbitrary