假设我正在为 Data.Set 编写测试。我想检查从集合中删除元素是否有效,所以我可能会写出以下代码:
假设
我曾想过写下以下代码:
这个方法可行,但有点繁琐;还有更好的选择吗?(如果没有,我会修改问题并将此作为答案。)实际的
prop_deleteA it x = member x it ==> not (member x (delete x it))
假设
it
具有合适的 Arbitrary
实例。然而,这取决于 quickcheck 生成的 x
值是否存在于集合中,这一点通常不能保证。如果能让 x
依赖于 it
,以确保 x
已经是 it
的成员,则效果会更好。我该怎么做呢?我曾想过写下以下代码:
prop_deleteB it f = let x = f it
in not (member x (delete x it))
在it技术相关中,f :: Set a -> a
可以通过coarbitrary进行适当定义。然而,coarbitrary只允许我们定义 f :: Set a -> b
,这不是我们想要的。到目前为止,我最好的想法是定义一个新类型。
data SetAndElement a = SetAndElement (Set a) a
这使我们能够编写一个合适的Arbitrary
实例。
instance (Ord a, Arbitrary a) => Arbitrary (SetAndElement a) where
arbitrary = do it <- suchThat arbitrary (not . Set.null)
x <- elements (elems it)
return (SetAndElement it x)
允许将prop_delete
写为
prop_deleteC (SetAndElement it x) = not (member x (delete x it))
这个方法可行,但有点繁琐;还有更好的选择吗?(如果没有,我会修改问题并将此作为答案。)实际的
Data.Set
实现(containers 包)通过检查 (delete x) . (insert x) == id
来测试删除操作,如果 x
不是给定集合的成员。
forAll
,但没有充分理解它。我的努力大多都朝着coarbitrary
的解决方案错误地引导了。 - sircolinton