4

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

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 中起作用?

4

2 回答 2

5

这可能是由GHCi 中扩展的默认规则引起的。

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

例如,您可以将Int其用于测试。()对测试这个功能毫无用处,因为所有元素都是一样的。

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

如果它适用于Int,由于参数性,它应该适用于任何类型。

于 2011-08-22T15:33:07.473 回答
3

当您运行 QuickCheck 测试时,QuickCheck 需要知道如何生成数据。在这里,您只告诉它您的代码应该与Ord类型类的任意类型一起使用,这还不足以开始测试。因此,关于模棱两可的类型类的错误。

如果您只需要一个任意Ord实例,如此处所示,那么类似的东西Int将是您测试的不错选择。它是一种具有线性顺序的简单类型。因此,请尝试将您的类型固定为Intin main,如:

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

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

于 2011-08-22T15:37:02.473 回答