haskell - quickCheck 命题逻辑生成器
问题描述
所以我有这个 quickCheck 命题逻辑生成器:
instance Arbitrary Form where
arbitrary = genForm
genForm = sized genForm'
genForm' 0 = fmap Prop (choose (1,15))
genForm' n | n > 15 = genForm' (n `div` 2)
genForm' n | n > 0 =
oneof [fmap Prop (choose (1,15)),
fmap Neg subform,
fmap Cnj subforms,
fmap Dsj subforms,
liftM2 Impl subform subform,
liftM2 Equiv subform subform]
where subform = genForm' (n `div` 2)
subforms = resize (n `div` 2) (vector (n `div` 2))
数据类型定义如下:
type Name = Int
data Form = Prop Name
| Neg Form
| Cnj [Form]
| Dsj [Form]
| Impl Form Form
| Equiv Form Form
deriving (Eq,Ord)
问题是这个生成器将以以下形式生成:(+[]
什么都没有的析取)。我不希望我的运算符没有嵌套Prop
成员,因为它会生成无效的命题公式。我想确保Prop
最后没有成员没有选择。
我的想法是这个问题来自resize (div n 2)
. 什么时候n
甚至这最终会命中0
并且不会进一步生成,从而创建一个空成员。删除resize
将无济于事,因为它不会生成结尾的“树”。所以它似乎是必要的,但应该以某种方式进行调整。
但是我在 Haskell 方面并不出色,而且我在调试/阅读文档时遇到了困难。
解决方案
应用于vector
非零参数:
subforms = resize (n `div` 2) (vector (1 + (n `div` 2)))
或使用listOf1 arbitrary
代替vector
subforms = resize (n `div` 2) (listOf1 arbitrary)
来自后续评论:
甚至需要生成量至少>2
应用于vector
长度 >= 2:
subforms = resize (n `div` 2) (vector (2 + (n `div` 2)))
或者在前面显式附加两个元素(listOf
用于允许长度也不同):
subforms = resize (n `div` 2) (listOf2 arbitrary)
where
listOf2 :: Gen a -> Gen [a]
listOf2 gen = liftA2 (:) gen (liftA2 (:) gen (listOf gen))
-- 1. (listOf gen) to generate a list
-- 2. Call gen twice to generate two more elements
-- 3. Append everything together with `(:)`
推荐阅读
- apache-camel - Camel:处理文件、拆分和聚合
- c - 为什么我的缓冲区存储在堆栈中的两个位置?
- java - 我们可以修改或自定义 Java 对象的数据结构(例如树、链表等)吗?
- angular - 在 pipe() 中引用 ViewChild
- apache-kafka - KafkaStreams 在拓扑中添加超过 1 个处理器不起作用
- java - 访问 Java hashmap 以获取子类
- kotlin - 如何使用简短形式覆盖属性设置器?
- javascript - 使 SVG 完全填满整个页面
- java - 如何禁用 Selenium 中的保存密码弹出窗口?
- android - 在 Google Play 和 App Store 上上传类似的应用