QuickCheck:测试有限集中的每个元素

时间:2014-08-18 04:38:32

标签: haskell quickcheck

我正在寻找一种方法来测试一组确定性值总是的函数(而不是列表中随机选择的值)。例如,我想要一种检查

的方法
f :: (Num a) => a -> Bool
f x = (x - 2) == (x-3+1)

完全适用于Int的1,3和5,没有明确写出

testGroup "f tests" $ map (testProperty . property) [f (1::Int), f (3::Int), f (5::Int)]

相反,我希望Int周围有一些包装器类型,这样当我在此类型上调用f时,它会每次使用值1,3和5测试f

这样做的动机是this answer来测试多态函数。

我想出了一个使用我自己的Arbitrary [Some c]实例的解决方案:

data Some c where
  Some :: (Show a, Arbitrary a, c a) => a -> Some c

instance Arbitrary [Dict c] => Arbitrary [Some c] where
  arbitrary = do
    dicts  :: [Dict c] <- arbitrary
    sequence $ map (\(Dict (Proxy::Proxy a)) -> liftM Some (arbitrary :: Gen a)) dicts


data Dict c where
  Dict :: (Show a, Arbitrary a, c a)
        => Proxy a -> Dict c

class ClassToTest a
  -- where ...    

instance Arbitrary [Dict ClassToTest] where
  arbitrary = return $ [Dict (Proxy::Proxy TYPE1),
                        Dict (Proxy::Proxy TYPE2)]

testAll :: forall a . (Arbitrary [a]) => (a -> Bool) -> Gen Bool
testAll f = do
  xs' <- arbitrary :: Gen [a]
  return $ and $ map f xs'

然后我可以写一个函数

myTest :: (ClassToTest a) => a -> Bool
myTest x = error ""

theTest :: Test
theTest = testProperty "mytest" $ testAll myTest

会生成随机值TYPE1并运行myTest,然后生成TYPE2的随机值并再次运行myTest。这个想法是TYPE *的列表非常大,所以我宁愿不依赖于随机选择来确保列表中的所有内容都被测试。我的方法问题当然是QuickCheck已经有(Arbitrary a) => Arbitrary [a]的通用实例,所以这段代码需要-XOverlappingInstances。有更好的方式吗?

0 个答案:

没有答案