39

我有一个简单的类型定义:

data Cell = Cell {
    x       :: Int,
    y       :: Int
  } deriving (Show)

我不能Cell用作 quickcheck 属性的输入,大概是因为 quickcheck 不知道如何生成 Cell 值。

我的理解是我需要使 Cell 成为类型类的实例Arbitrary

例如,如果我希望使用 x 和 y 的随机正值生成 Cell,我该怎么做?

4

2 回答 2

49

为您的数据类型编写一个实例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的修饰符来确保我们只生成正整数。

要编写更复杂的生成器,请查看Test.QuickCheck.Gen中的各种生成器。

于 2013-05-08T12:13:36.053 回答
16

Arbitrary您可以使用 TemplateHaskell生成一个执行相同操作的实例并派生包:

import Data.DeriveTH

derive makeArbitrary ''Cell
于 2013-05-09T03:26:46.830 回答