简单的 QuickCheck 测试永远无法完成
Simple QuickCheck Test Never Completes
我在思考 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
在几秒钟内吃掉几 GB 的 RAM,如果我不杀掉它,最终 运行 我的机器将无法交换 space。我可能错过了一些令人难以置信的东西 fundamental/stupid,但(显然)不知道是什么。有什么想法吗?
编辑:我现在质疑我的 Random
实例。也许问题就在那里,而不是我的 Arbitrary
实例。
Micro
的 Random
实例似乎有问题
这里有一个快速的修复方法:
{-# 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
我在思考 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
在几秒钟内吃掉几 GB 的 RAM,如果我不杀掉它,最终 运行 我的机器将无法交换 space。我可能错过了一些令人难以置信的东西 fundamental/stupid,但(显然)不知道是什么。有什么想法吗?
编辑:我现在质疑我的 Random
实例。也许问题就在那里,而不是我的 Arbitrary
实例。
Micro
Random
实例似乎有问题
这里有一个快速的修复方法:
{-# 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