Вот одна из возможностей. Мы определим новый класс для типов, которые могут создавать случайные значения, зависящие от размера. Затем вы можете создать список или дерево на уровне типов или что-то еще и объявить один экземпляр Arbitrary
для них раз и навсегда.
import Control.Monad
import Test.QuickCheck
class SizedArbitrary a where
sizedArbitrary :: Int -> Gen a
instance Arbitrary a => SizedArbitrary [a] where
sizedArbitrary n = replicateM n arbitrary
data Branch a b = a :+ b deriving (Eq, Ord, Show, Read)
instance (SizedArbitrary a, SizedArbitrary b) => SizedArbitrary (Branch a b) where
sizedArbitrary n = liftM2 (:+) (sizedArbitrary n) (sizedArbitrary n)
instance (SizedArbitrary a, SizedArbitrary b) => Arbitrary (Branch a b) where
arbitrary = arbitrarySizedIntegral >>= sizedArbitrary . abs
Затем мы можем загрузить его в ghci и проверить, работает ли он:
*Main> let allSameLength (xs:xss) = all (==length xs) (map length xss)
*Main> quickCheck (\(xs :+ ys) -> allSameLength [xs, ys])
+++ OK, passed 100 tests.
*Main> quickCheck (\(ws :+ xs :+ ys :+ zs) -> allSameLength [ws, xs, ys, zs])
+++ OK, passed 100 tests.
person
Daniel Wagner
schedule
04.11.2013