【问题标题】:Haskell QuickCheck generate random data for function with many input variablesHaskell QuickCheck 为具有许多输入变量的函数生成随机数据
【发布时间】:2013-08-27 04:57:51
【问题描述】:

我有一个具有以下类型签名的函数

rndListIndex :: Double -> Double -> Double -> Double
rndListIndex maxIdx r1 r2 = …
  • 第一个输入应该是一个来自非负严格正整数的值
  • 第二个和第三个输入必须在闭区间 [0.0,1.0] 内,否则函数没有意义

函数具有

的性质
prop_alwaysLessThanMaxIdx idx r1 r2 = (rndListIndex idx r1 r2 <= idx)

如何分别为maxIdxr1,r2 生成随机数据;我知道函数choose,但不知道如何将它与多个输入变量一起使用。

目前我已经用固定的idx 测试了属性,这不是应该测试的方式。

【问题讨论】:

  • 第一个值可以是0吗?
  • 现在我认为不应该 - 我将编辑问题。

标签: haskell quickcheck


【解决方案1】:

您必须使用 QuickCheck 中的 forAll 函数。它有以下类型:

forAll :: (Show a, Testable prop) 
       => Gen a           -- ^ The generator to use for generating values
       -> (a -> prop)     -- ^ A function which returns a testable property
       -> Property                  

forAll 接受两个参数:

  • 生成器描述了如何生成值。生成器的示例有choosearbitraryoneof、...
  • 该函数测试给定输入的属性。它必须返回一个作为Testable 实例的值,例如另一个PropertyBool 或函数。

带有选择和元素生成器的嵌套 forAll 示例:

-- This generates a Property p for all x's in the closed interval [1,3]
-- The property p in turn generates a property q for all y ∈ [4,5]
-- The property q is True if x < y.
prop_choose = forAll (choose (1,3)) $ \x ->
              forAll (elements [4,5]) $ \y -> x < y

对于您的测试属性,您可以使用 forAll 和 choose 作为第二个和第三个参数。 对于第一个参数,QuickCheck 中有 Positive a 类型,可用于生成 a 类型的任意正值(当 a 为 Num 时,它有一个 Arbitrary 实例):

prop_alwayLessThanMaxIdx :: Positive Integer -> Property
prop_alwaysLessThanMaxIdx (Positive idx) = 
  forAll (choose (0,1)) $ \r1 ->
  forAll (choose (0,1)) $ \r2 ->
   (rndListIndex idx r1 r2) < idx

【讨论】:

    【解决方案2】:

    我建议定义您自己的类型来包装 Double 并给它一个 Arbitrary 实例,它只生成 0 到 1 之间的数字。类似于:

    import Test.QuickCheck
    newtype UnitInterval = Unit Double deriving Show
    
    instance Arbitrary UnitInterval where
      arbitrary = fmap Unit (choose (0, 1))
      shrink (Unit x) = [ Unit y | y <- shrink x, 0 <= y && y <= 1 ]
    

    要生成idx,您可以使用QuickCheck 的Positive 修饰符,正如@bennoffs 建议的那样(您必须导入Test.QuickCheck.Modifiers)。这类似于我上面定义的 UnitInterval 类型,但生成正数而不是 0 和 1 之间的数字。您的属性将如下所示:

    prop_alwaysLessThanMaxIdx (Positive idx) (Unit r1) (Unit r2) =
      rndListIndex idx r1 r2 <= idx
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-21
      • 2015-01-15
      • 1970-01-01
      • 2020-05-10
      • 2014-01-06
      • 1970-01-01
      • 2021-01-07
      相关资源
      最近更新 更多