我在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
实例。
答案 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