quickCheck 命题逻辑生成器
quickCheck propositional logic 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)),
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
将无济于事,因为它不会生成结尾 'tree'。所以它似乎是需要的,但应该以某种方式进行调整。
但我不擅长 Haskell,而且我在 debugging/reading 文档方面遇到困难。
将vector
应用于non-zero参数:
subforms = resize (n `div` 2) (vector (1 + (n `div` 2)))
或使用listOf1 arbitrary
代替vector
subforms = resize (n `div` 2) (listOf1 arbitrary)
来自 follow-up 评论:
even need the generated amount to be at least >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 `(:)`
我同意 dfeuer 的观点,空的析取和连词是有意义的,并且在逻辑上分别表示假和真。但是,如果您不想使用此类术语,那么我认为您通过快速检查尝试修复问题是在错误地看待问题。相反,通过对这些构造函数使用 NonEmpty Form
而不是 [Form]
来将其修复为您的数据类型。那么,不仅 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
将无济于事,因为它不会生成结尾 'tree'。所以它似乎是需要的,但应该以某种方式进行调整。
但我不擅长 Haskell,而且我在 debugging/reading 文档方面遇到困难。
将vector
应用于non-zero参数:
subforms = resize (n `div` 2) (vector (1 + (n `div` 2)))
或使用listOf1 arbitrary
代替vector
subforms = resize (n `div` 2) (listOf1 arbitrary)
来自 follow-up 评论:
even need the generated amount to be at least >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 `(:)`
我同意 dfeuer 的观点,空的析取和连词是有意义的,并且在逻辑上分别表示假和真。但是,如果您不想使用此类术语,那么我认为您通过快速检查尝试修复问题是在错误地看待问题。相反,通过对这些构造函数使用 NonEmpty Form
而不是 [Form]
来将其修复为您的数据类型。那么,不仅 quickcheck 无法生成这些无效表单,其他人也无法生成这些无效表单。