简体   繁体   English

如何约束QuickCheck参数,例如仅使用非负的int?

[英]How can I constraint QuickCheck parameters, e.g. only use non-negative ints?

I'm new to Haskell. 我是Haskell的新手。 It's very nice so far, but I'm running into copy-pasting for my QuickCheck properties, and I'd like to fix that. 到目前为止,这是非常好的,但我正在尝试复制粘贴我的QuickCheck属性,我想解决这个问题。

Here's a made-up example: 这是一个简单的例子:

prop_Myfunc :: [Int] -> (Int,Int) -> Bool
prop_Myfunc ints (i,j) = ints !! i == ints !! j

This won't work because QuickCheck generates negative numbers, so I get 这不起作用,因为QuickCheck生成负数,所以我得到

*** Failed! (after 2 tests and 2 shrinks):                               
Exception:
  Prelude.(!!): negative index

I've tried to google for solutions to this, and I've found eg NonNegative and ==>, but I don't understand how they work. 我试图谷歌寻求解决方案,我发现例如NonNegative和==>,但我不明白它们是如何工作的。

How can I restrict the above example so that i and j are never negative? 我怎样才能限制上面的例子,以便i和j永远不会消极? And also, so that neither is too high? 而且,既不是太高了? That is: 0 <= i,j < length ints 即: 0 <= i,j < length ints

First, see this SO answer for an example of how to write a custom Gen ... function and how to use the forAll combinator. 首先,请参阅此SO答案 ,了解如何编写自定义Gen ...函数以及如何使用forAll组合器的forAll

And here is how to write a generator for a non-empty list and two valid non-negative indices into the list: 以下是如何为列表中的非空列表和两个有效的非负索引编写生成器:

import Test.QuickCheck

genArgs :: Gen ( [Int], Int, Int )
genArgs = do
  x <- arbitrary
  xs <- arbitrary
  let n = length xs
  i <- choose (0,n)
  j <- choose (0,n)
  return ( (x:xs), i, j) -- return a non-empty list

test = quickCheck $ forAll genArgs $ \(xs,i,j) -> prop_myfunc xs (i,j)

Constraining wrappers (from Test.QuickCheck.Modifiers , if they aren't reexported implicitly) can be used in this way: 约束包装器(来自Test.QuickCheck.Modifiers ,如果它们不是隐式Test.QuickCheck.Modifiers )可以这样使用:

prop_Myfunc :: [Int] -> (NonNegative Int, NonNegative Int) -> Bool
prop_Myfunc ints (NonNegative i, NonNegative j) = ints !! i == ints !! j

You can treat SomeWrapper a as a with modified distribution. 你可以把SomeWrapper a作为a具有修改的分布。 For example, NonNegative a ensures that a >= 0 . 例如, NonNegative a确保a >= 0 After the wrapper was generated, the value can be get with pattern-matching or explicit accessor ( getNonNegative in this case). 生成包装器后,可以使用模式匹配或显式访问器(在本例中为getNonNegative )获取值。

As for constraining the top margin of your indices, I think it's not possible with wrappers (it's impossible in the Haskkell type system to parameterise a type with the value, the list length in this case). 至于约束索引的上边距,我认为使用包装器是不可能的(在Haskkell类型系统中不可能使用值参数化类型,在这种情况下是列表长度)。 However, with the ==> operator you can add an arbitrary boolean constraint for your test: 但是,使用==>运算符,您可以为测试添加任意布尔约束:

prop_Myfunc ints (NonNegative i, NonNegative j) = i < l && j < l ==> ints !! i == ints !! j where
    l = length ints

It works in other way: when the condition isn't true, it simply discards the current test case. 它以其他方式工作:当条件不成立时,它只是丢弃当前的测试用例。 But be careful: if there are too many thrown cases (the condition is too restrictive), the test becomes much less useful. 但要小心:如果抛出的案例太多(条件限制太多),那么测试就变得不那么有用了。 A „lossless“ behaviour can be often achieved with shrink ing test data, but it's a whole other topic. 通过shrink测试数据通常可以实现“无损”行为,但这是另一个主题。

I was in a similar situation as you and I finally found how to use ==> here: http://www.cse.chalmers.se/~rjmh/QuickCheck/manual.html , in the "Conditional Properties" section. 我遇到了与你类似的情况,我终于找到了如何使用==>这里: http//www.cse.chalmers.se/~rjmh/QuickCheck/manual.html ,在“条件属性”部分。

With your example, you'd have to replace Bool with Property and insert the requirements about your variables before the property test, as follows: 在您的示例中,您必须使用Property替换Bool并在属性测试之前插入有关变量的要求,如下所示:

prop_Myfunc :: [Int] -> (Int,Int) -> Property
prop_Myfunc ints (i,j) = (i >= 0 && j >= 0) ==> ints !! i == ints !! j

(I haven't tested on this particular example, but it worked for me on a similar case.) (我没有对这个特定的例子进行过测试,但是对于类似的情况,它对我有用。)

Note the type of ==> : (==>) :: Testable prop => Bool -> prop -> Property . 注意类型==> :( (==>) :: Testable prop => Bool -> prop -> Property

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM