0

QuickCheck用来在我的代码上运行任意测试用例。但是,在我的代码的一部分中,我有类型同义词:

type Vector = [Double]

我还有一些函数可以接受多个Vectors 作为输入。但是,所有这些函数都要求Vectors 的长度相同。

有没有办法限制QuickCheck它只生成长度为n的列表?

4

4 回答 4

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

从来没有一个类型类,所以你得到的失败帮助更少,但它更容易启动。

于 2013-11-04T04:25:55.060 回答
3

==>您可以使用符号设置约束。

一个例子是:

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
于 2013-11-04T04:28:30.550 回答
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.
于 2013-11-04T04:37:00.783 回答
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.
于 2013-11-04T04:24:35.130 回答