Haskell 快速检查命题逻辑发生器

Haskell 快速检查命题逻辑发生器,haskell,generator,quickcheck,Haskell,Generator,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)),

我有一个快速检查命题逻辑生成器:

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
成员的选项

我的想法是,这个问题来自调整大小(divn2)。当
n
为偶数时,这将最终命中
0
,而不会进一步生成并因此创建空成员。删除
调整大小
不会有帮助,因为它不会生成结束“树”。因此,这似乎是必要的,但应该以某种方式加以调整


但我不擅长Haskell,调试/阅读文档时遇到困难。

vector
应用于非零参数:

subforms = resize (n `div` 2) (vector (1 + (n `div` 2)))
或者使用而不是
向量

subforms = resize (n `div` 2) (listOf1 arbitrary)

根据后续评论:

甚至需要生成的量至少大于2


向量
应用于长度>=2:

subforms = resize (n `div` 2) (vector (2 + (n `div` 2)))
或者在前面显式附加两个元素(使用
listOf
允许长度也发生变化):


我同意dfeuer的观点,空的析取和连接是有意义的,逻辑上分别表示假和真。但是如果你不喜欢这样的条款,那么我认为你在快速检查中试图解决这个问题是错误的。相反,通过对这些构造函数使用而不是
[Form]
来在数据类型中修复它。那么,不仅quickcheck无法生成这些无效表单,其他人也无法生成这些表单。

这是一个很好的方法,至少更好。我犯了一个恼人的错误,(刚刚意识到)我甚至需要生成的量至少为
>2
,因为一个元素的连词仍然无效。好的,让我调整我的答案来处理这个问题。我同意dfeuer的观点,尽管这些限制似乎是人为的。这一定是我对这个领域普遍缺乏了解。我正在使用提供的函数。对该函数的快速检查会导致非穷举模式。公平地说,这是正确的,而且这些数据可能是正确生成的。但是这个测试中的函数是提供给我的,所以我“假设”他们做的是正确的。我正在询问他们空的Cnj和Dsj的有用性,以及他们代码中可能出现的错误。但我现在至少得到了我所要求的,我所得到的真实性将被进一步研究。但谢谢你的快速回答。是什么让这些无效?空的析取是false/bottom,而空的连词是true/top。事实上,这些是用你的类型表达那些重要主张的唯一方式@德弗尔我对这些公式很不熟悉⊤ 及⊥. 它们在
形式中缺失,这听起来绝对正确。我想你也可以将true表示为
Prop 0`Equiv`Prop 0
,将false表示为
Prop 0`Equiv`Neg(Prop 0)
,但它们既不像
Cnj[]
Dsj[]
那样紧凑,也不像(IMO)那样清晰。
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 `(:)`