是否可以在QuickCheck中生成任意函数 [英] Is it possible to generate arbitrary functions in QuickCheck

查看:56
本文介绍了是否可以在QuickCheck中生成任意函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为身份编写QuickCheck测试

I was trying to write a QuickCheck test for the identity

f $ y = f y

我最初的计划是编写一个返回函数&的任意生成器.具有签名 Gen(Int-> Int,Int)

My initial plan was to write an arbitrary generator that returns functions & Integer, having the signature Gen (Int -> Int, Int)

并在 prop_DollerDoesNothing 中测试带有/不带有 $ 的功能应用程序是否会得到相同的结果.

and in the prop_DollerDoesNothing test that function application with / without the $ gives the same result.

这是我的代码:

  prop_DollarDoesNothing :: Property
  prop_DollarDoesNothing =
    forAll arbitraryFuncInt (\(f, y) -> (f $ y) == (f y))

  arbitraryFuncInt :: Gen (Int -> Int, Int)
  arbitraryFuncInt = do
    f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
    y <- arbitrary :: Gen Int
    return (f, y)

它生成了以下有用的错误消息:

And it generated the following helpful error message:

    * No instance for (Show (Int -> Int))
        arising from a use of `forAll'
        (maybe you haven't applied a function to enough arguments?)
    * In the expression:
        forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))
      In an equation for `prop_DollarDoesNothing':
          prop_DollarDoesNothing
            = forAll arbitraryFuncInt (\ (f, y) -> (f $ y) == (f y))

因此,我修复了错误,并通过应用任意函数并从 arbitraryFuncInt

So, I fixed the error and got the test working by applying the arbitrary function and returning a pair of ints from arbitraryFuncInt

  prop_DollarDoesNothing :: Property
  prop_DollarDoesNothing =
    forAll arbitraryFuncInt (\(x, y) -> x == y)

  arbitraryFuncInt :: Gen (Int, Int)
  arbitraryFuncInt = do
    f <- elements [(\x -> x*2), (\x -> x+3), (\x -> x-2)]
    y <- arbitrary :: Gen Int
    return (f $ y, f y)

我的问题是:

  1. 是否由于没有 Show 的实例而无法返回未完全应用的任意函数?
  2. 我可以为 Show(Int-> Int)编写实例以使#1 成为可能吗?
  3. 在我正在测试对所有(给定类型的)函数都正确的身份的情况下,QuickCheck是否可以生成给定类型签名的任意函数.上面,我手动指定了3个测试函数,我想以某种方式使其自动化,理想情况下是这样的 f<-任意:: Gen(Int-> Int)
  1. is it simply not possible to return arbitrary functions that aren't fully applied due to not having an instance for Show?
  2. Can I write an instance for Show (Int -> Int) to make # 1 possible?
  3. Can QuickCheck generate arbitrary functions given a type signature, for cases where I'm testing identities that are true for all functions (of a given type). Above, I specify the 3 test functions by hand, I'd like to automate that somehow, ideally something like this f <- arbitrary :: Gen (Int -> Int)

推荐答案

QuickCheck支持使用 Fun 类型生成,缩小和显示功能. CoArbitrary 可以生成函数.然后将其转换为一个(可能是无限的)类似于trie的结构,可以对其进行检查并缩小为一个有限值(因为测试失败仅取决于有限的多个输入),然后可以将其作为反例.

QuickCheck has support to generate, shrink and show functions, using the Fun type. CoArbitrary enables generation of functions. It is then converted to a (possibly infinite) trie-like structure, that can be inspected and shrunk to a finite value (because a test failure only depends on finitely many inputs), which can then be shown as a counterexample.

具体来说,您可以使用我描述的机制将属性编写为带有 Fun 参数的函数,该参数是(->)的包装.使用 Fn 模式对其进行解构以获取函数.

Concretely, you can write properties as function that take a Fun argument, which is a wrapper around (->) using the mechanism I described. Deconstruct it with the Fn pattern to get a function.

prop_dollarDoesNothing :: Property
prop_dollarDoesNothing = property $ \(Fn (f :: Int -> Int)) x ->
  (f $ x) === f x

更多信息

科恩·克拉森(Koen Claessen)撰写的论文收缩和显示功能",似乎很赚钱,但他的演讲在线:"rel =" nofollow noreferrer> https://www.youtube.com/watch?v=CH8UQJiv9Q4

The paper "Shrinking and showing functions" by Koen Claessen, which appears to be paywalled, but his talk is online: https://www.youtube.com/watch?v=CH8UQJiv9Q4

这篇关于是否可以在QuickCheck中生成任意函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆