如何在main中使用quickcheck

时间:2011-08-22 15:25:21

标签: haskell quickcheck

我正在编写一个我写的二进制搜索函数的测试。

module Tests where

import Data.List (sort)
import Test.QuickCheck
import BinarySearch (binarySearch)

prop_equals_elem x xs = (binarySearch x $ sort xs) == (x `elem` xs)

args = Args {replay = Nothing, maxSuccess = 200, maxDiscard=200, maxSize=200, chatty = False}

main = do
    quickCheck (prop_equals_elem :: (Ord a) => a -> [a] -> Bool)

在ghci中使用quickCheck可以很好地工作但是当我尝试运行main时会出现错误

Tests.hs:12:5:
    Ambiguous type variable `a0' in the constraints:
      (Arbitrary a0) arising from a use of `quickCheckWith'
          at Tests.hs:12:5-18
      (Show a0) arising from a use of `quickCheckWith'
          at Tests.hs:12:5-18
      (Ord a0) arising from an expression type signature
          at Tests.hs:12:26-72

为什么这不能在main中起作用,而在ghci中起作用?

2 个答案:

答案 0 :(得分:4)

这可能是由extended defaulting rules in GHCi引起的。

测试这样的函数时,需要使用具体的元素类型。由于扩展规则,GHCi会将元素类型默认为(),但在正常编译代码时不会发生这种情况,因此GHC告诉您它无法确定要使用的元素类型。

例如,您可以使用Int代替测试。 ()对于测试此函数毫无用处,因为所有元素都是相同的。

quickCheck (prop_equals_elem :: Int -> [Int] -> Bool)

如果适用于Int,则由于参数化原因,它适用于任何类型。

答案 1 :(得分:3)

运行QuickCheck测试时,QuickCheck需要知道如何生成数据。在这里,您只告诉它您的代码应该使用任意类型的Ord类型类,这对于它开始测试是不够的。因此关于模糊类型类的错误。

如果您只需要一个任意的Ord实例,就像这里显示的那样,Int之类的内容将是您测试的不错选择。这是一个带线性顺序的简单类型。因此,请尝试将您的类型修改为Int中的main,如下所示:

quickCheck (prop_equals_elem :: Int -> [Int] -> Bool)

至于为什么它在GHCi中工作,答案是默认的。 GHCi会尽可能将类型变量默认为(),以避免在您真正不关心值的情况下出现虚假错误。实际上这是一个糟糕的选择:你不会只用()类型测试来测试任何有趣的东西!再次,显式类型签名更好。