我有一个简单的类型定义:
data Cell = Cell {
x :: Int,
y :: Int
} deriving (Show)
我不能Cell
用作 quickcheck 属性的输入,大概是因为 quickcheck 不知道如何生成 Cell 值。
我的理解是我需要使 Cell 成为类型类的实例Arbitrary
。
例如,如果我希望使用 x 和 y 的随机正值生成 Cell,我该怎么做?
我有一个简单的类型定义:
data Cell = Cell {
x :: Int,
y :: Int
} deriving (Show)
我不能Cell
用作 quickcheck 属性的输入,大概是因为 quickcheck 不知道如何生成 Cell 值。
我的理解是我需要使 Cell 成为类型类的实例Arbitrary
。
例如,如果我希望使用 x 和 y 的随机正值生成 Cell,我该怎么做?
为您的数据类型编写一个实例Arbitrary
很容易。你只需要实现这个arbitrary
函数,它应该返回一个Gen Cell
. 最简单的方法是利用现有Arbitrary
实例并注意这Gen
是一个 monad,所以我们可以使用do
-notation:
instance Arbitrary Cell where
arbitrary = do
Positive x <- arbitrary
Positive y <- arbitrary
return $ Cell x y
或者,生成器通常可以使用以下运算符优雅地编写Control.Applicative
:
instance Arbitrary Cell where
arbitrary = Cell <$> pos <*> pos
where pos = getPositive <$> arbitrary -- getPositive requires QC >= 2.5
在这里,我还使用了Positive
来自Test.QuickCheck.Modifiers的修饰符来确保我们只生成正整数。
Arbitrary
您可以使用 TemplateHaskell生成一个执行相同操作的实例并派生包:
import Data.DeriveTH
derive makeArbitrary ''Cell