简单的QuickCheck测试永远不会完成

时间:2015-05-18 03:31:51

标签: haskell quickcheck

我在QuickCheck周围遇到了一些麻烦。考虑以下简单数据类型及其对应的任意实例。

编辑:评论中要求的以下完整代码。 fixedToFractional会将Micro等固定数字类型转换为Fractional

import Data.Fixed
import System.Random
import Control.Applicative
import Test.QuickCheck

fixedToFractional :: (HasResolution a, Fractional b) => Data.Fixed.Fixed a -> b
fixedToFractional = fromRational . toRational

instance Random Micro where
    randomR (lo, hi) g = randomR (fixedToFractional lo, fixedToFractional hi) g
    random g           = randomR (-999999, 999999) g

data FooType = FooType { foo :: Micro } deriving (Show)

instance Arbitrary FooType where
    arbitrary =
        FooType <$> x
        where
            x = choose (0.0, 1.0)

如果我理解正确,这应该允许生成随机FooType值,foo字段设置为0到1之间的随机值。

接下来,请考虑以下简单测试。

prop_foo_is_gte_zero ft = (foo ft) >= 0.0

当我尝试运行上述测试时,无论是在ghci中还是在使用quickCheckAll的测试文件中,测试都不会完成。 ghc只需几秒钟就可以吃掉一些内存,如果我不杀它,最终会让我的机器脱离交换空间。我可能错过了一些非常基本/愚蠢的东西,但(显然)不知道是什么。有什么想法吗?

编辑:我现在质疑我的Random实例。也许问题存在,而不是我的Arbitrary实例。

1 个答案:

答案 0 :(得分:1)

您的Random

Micro个实例中似乎存在问题

这是一个快速修复它的方法:

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}

import Data.Fixed
import System.Random
import Test.QuickCheck

toDouble :: Micro -> Double
toDouble = realToFrac . toRational

instance Random Micro where
    randomR (lo, hi) g =
      let (a,g') = randomR (toDouble lo, toDouble hi) g
      in (fromRational (toRational a), g')
    random = randomR (-999999, 999999)

data FooType = FooType { foo :: Micro } deriving (Show)

instance Arbitrary FooType where
    arbitrary =
        FooType <$> x
        where
            x = choose (0.0, 1.0)

main :: IO ()
main = quickCheck prop_foo_is_gte_zero
  where prop_foo_is_gte_zero ft = foo ft >= 0.0