是否可以在QuickCheck中生成任意函数 [英] Is it possible to generate arbitrary functions in 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)
我的问题是:
- 是否由于没有
Show
的实例而无法返回未完全应用的任意函数? - 我可以为
Show(Int-> Int)
编写实例以使#1
成为可能吗? - 在我正在测试对所有(给定类型的)函数都正确的身份的情况下,QuickCheck是否可以生成给定类型签名的任意函数.上面,我手动指定了3个测试函数,我想以某种方式使其自动化,理想情况下是这样的
f<-任意:: Gen(Int-> Int)
- is it simply not possible to return arbitrary functions that aren't fully applied due to not having an instance for
Show
? - Can I write an instance for
Show (Int -> Int)
to make# 1
possible? - 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
更多信息
-
QuickCheck实现:https://hackage.haskell.org/package/QuickCheck-2.11.3/docs/Test-QuickCheck-Function.html
科恩·克拉森(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屋!