我正在使用QuickCheck
在我的代码上运行任意测试用例。但是,在我的代码的一部分中,我有类型同义词:
type Vector = [Double]
我还有一些函数接受一些Vector
作为输入。但是,所有这些函数都要求Vector
具有相同的长度。
有没有办法约束QuickCheck
,以便它只生成长度 n 的列表?
答案 0 :(得分:3)
一个简单的解决方案是没有任意实例,而是做
之类的事情import Test.QuickCheck
import Control.Monad
prop_vec :: Int -> Gen [Double]
prop_vec = flip replicateM arbitrary . abs
prop_addComm :: Int -> Gen Bool
prop_addComm i = do
v <- prop_vec i
u <- prop_vec i
return $ u + v = v + u --assuming you'd added a Num instance for your vectors
从来没有一个类型类,所以你得到的帮助失败较少,但它更容易鞭打。
答案 1 :(得分:2)
您可以使用==>
表示法设置约束。
一个例子是:
prop_test xs = minimum xs == (head $ sort xs)
失败了:
*** Failed! Exception: 'Prelude.minimum: empty list' (after 1 test):
[]
现在有一个约束:
prop_test xs = not (null xs) ==> minimum xs == (head $ sort xs)
它有效:
*Main> quickCheck prop_test
+++ OK, passed 100 tests.
在你的情况下:
prop_test xs ys = length xs == length ys ==> undefined -- whatever you want
答案 2 :(得分:2)
另一个明显的解决方案是生成元组列表并解压缩它们。例如,在ghci中:
> let allSameLength (xs:xss) = all (==length xs) (map length xss)
> quickCheck (\xys -> let (xs, ys) = unzip xys in allSameLength [xs, ys])
+++ OK, passed 100 tests.
> :{
| quickCheck (\wxyzs -> let
| (wxs, yzs) = unzip wxyzs
| (ws, xs) = unzip wxs
| (ys, zs) = unzip yzs
| in allSameLength [ws, xs, ys, zs])
| :}
+++ OK, passed 100 tests.
答案 3 :(得分:1)
这是一种可能性。我们将为可以构建与大小相关的随机值的类型定义一个新类。然后你可以创建一个类型级别的列表或树或其他,并为这些一次性声明一个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.