【问题标题】:Generate triple (Network.HTTP.ResponseCode) using an instance of Arbitrary使用任意实例生成三元组 (Network.HTTP.ResponseCode)
【发布时间】:2012-04-27 14:42:50
【问题描述】:

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

所以我写了这样的东西:

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

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

其次,我的任意函数类型错误,这很明显。但是后来我真的不知道如何编写一个返回三元组的函数,其中随机 Int 范围为 1-6。

如果有人可以在这里帮助我,我将不胜感激。

谢谢。

【问题讨论】:

    标签: haskell quickcheck


    【解决方案1】:

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

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

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

    您可以尝试使用 Test.QuickCheck.Gen.suchThat,但我假设在这种情况下它不会很好地工作。如果可以,我建议使用新类型包装器:

    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)) 对这三个元素进行后处理。

    【讨论】:

    • 很好的答案。我唯一要补充的是,如果您无论如何都要创建一个新类型,并且由于ResponseCode 显然只有六个可能的值,您不妨定义类似data ResponseCode = Success | Partial | Failure | FileNotFound | NotAuthorized | I'mALittleTeapot 之类的东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-11
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    相关资源
    最近更新 更多