使用Arbitrary实例生成三元组(Network.HTTP.ResponseCode)

时间:2012-04-27 05:58:18

标签: haskell quickcheck

我有一个从Network.HTTP获取ResponseCode的函数。为了使用QuickCheck进行测试,我想为ResponseCode编写一个Arbitrary实例。 (如果您不知道,ResponseCode只是该库中的三个整数:类型ResponseCode =(Int,Int,Int))。

所以我写了这样的话:

instance Arbitrary ResponseCode where
    arbitrary = triple ( elements [1..6] )
       where triple f = (f, f, f)

首先,GHC抱怨说我使用类型的方式不是标准的haskell所以我必须使用一些编译器标志(这不是我想要的,因为我觉得必须有一个简单的解决方案没有标志的简单问题)。

其次,我的任意函数都有错误的类型,这很明显。但后来我真的没弄明白如何编写一个函数来返回一个三元组,其中包含1-6的随机Ints。

如果有人能帮助我,我将不胜感激。

谢谢。

1 个答案:

答案 0 :(得分:5)

首先,已经有这两个实例:

instance Arbitrary Int
instance (Arbitrary a, Arbitrary b, Arbitrary c) =>
         Arbitrary (a, b, c)

这意味着(Int,Int,Int)已经是任意的实例。这意味着类型同义词ResponseCode已经是一个实例。您无法定义和使用第二个实例。

您可以尝试使用Test.QuickCheck.Gen.such但我假设它在这种情况下不能正常工作。如果可以,我建议使用newtype包装器:

import Test.QuickCheck
import Network.HTTP.Base
import Control.Applicative
import System.Random

newtype Arb'ResponseCode = Arb'ResponseCode { arb'ResponseCode :: ResponseCode }
  deriving (Show)

instance Arbitrary Arb'ResponseCode where
  arbitrary = do
      responseCode <- (,,) <$> f <*> f <*> f
      return (Arb'ResponseCode responseCode)
    where f = elements [1..6]

-- To use this you can call
-- (fmap arb'ResponseCode arbitrary)
-- instead of just (arbitrary)

或许可以使用内置(Int,Int,Int)实例并使用(succ。(mod 6))对这三个元素进行后处理。