haskell - 是否可以在 QuickCheck 中生成任意函数
问题描述
我试图为身份编写一个 QuickCheck 测试
f $ y = f y
我最初的计划是编写一个返回函数和整数的任意生成器,具有签名Gen (Int -> Int, Int)
并且在prop_DollerDoesNothing
测试中,带有/不带有 的功能应用程序$
给出了相同的结果。
这是我的代码:
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)
它生成了以下有用的错误消息:
* 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
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 <- arbitrary :: Gen (Int -> Int)
解决方案
QuickCheck 支持使用类型生成、缩小和显示函数Fun
。CoArbitrary
可以生成函数。然后将其转换为(可能是无限的)类似 trie 的结构,可以对其进行检查并缩小为有限值(因为测试失败仅取决于有限多个输入),然后可以将其显示为反例。
具体来说,您可以将属性编写为带有参数的函数,这是使用我描述的机制Fun
的包装器。(->)
用模式解构它Fn
以获得一个函数。
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 的论文“Shrinking and show functions”似乎是付费墙,但他的演讲是在线的:https ://www.youtube.com/watch?v=CH8UQJiv9Q4
推荐阅读
- python-3.x - ModuleNotFoundError:没有名为“帐户”的模块
- python - 将 matplotlib savefig .png 传输到 dest 文件夹
- python - 如何在数据框中仅选择索引列?
- html - 仅使用溢出-y 滚动 DIV
- php - 如何在 PHP 中的一个元素中编写多个不同的 xml 命名空间
- python - 想用 selenium 在页面上刮一张桌子
- caching - 具有大约 100,000 个条目的重复字典访问的最佳缓存策略
- javascript - Vuejs多个复选框不适用于v-model
- mongodb - mongodb 查询 updateMany :更新集合中所有文档的嵌入式文档列表中的字段
- rust - 转换 Vec
> 到 &[&[u8]]