【问题标题】:QuickCheck Semigroup over a function函数上的 QuickCheck 半群
【发布时间】:2021-10-26 06:01:58
【问题描述】:

我有这种方法来测试半群的关联性

semigroupdAssoc :: (Eq m, Semigroup m) => m -> m -> m -> Bool
semigroupdAssoc a b c = a <> (b <> c) == (a <> b) <> c

给定以下类型

newtype Combine a b =
    Combine { unCombine :: a -> b }

我的 Semigroup 实施我

instance Semigroup b => Semigroup (Combine a b) where
    (<>) (Combine u) (Combine u') = Combine (u <> u')

我对如何编写快速测试感到困惑,

假设我要测试字符串,

type CombineAssoc = Combine String String -> Combine String String -> Combine String String -> Bool

测试将是

    quickCheck (semigroupdAssoc :: CombineAssoc)

我知道我必须为Combine 编写一个Arbitrary 实现,但我不知道怎么做。

想出了解决办法,但我不明白。

Arbitrary for Combine 的实现如下所示:

instance (CoArbitrary a, Arbitrary b) => Arbitrary  (Combine a b) where
    arbitrary = do
        Combine <$> arbitrary

还需要实现 Show(不是很好)

instance Show (Combine a b) where
    show (Combine _) = "unCombine"

更新此数据类型的关联函数

combineSemigroupAssoc :: (Eq b, Semigroup b) => a -> Combine a b -> Combine a b -> Combine a b -> Bool
combineSemigroupAssoc x a b c = unCombine (a <> (b <> c)) x == unCombine ((a <> b) <> c) x

实现需要测试的属性

genString :: Gen String
genString = arbitrary

prop_combineSemigroupAssoc :: Property
prop_combineSemigroupAssoc = forAll genString (combineSemigroupAssoc :: CombineAssoc)

最后运行 quickCheck

    quickCheck prop_combineSemigroupAssoc

认为我仍然需要帮助

  • 您能否解释一下 Arbitrary 实现现在是如何工作的(CoArbitrary 的文档对我来说不是很清楚)?
  • 有没有更好的方法来实现 Show for Combine,比如查看实际的调用参数?

【问题讨论】:

  • 你不能那样做,因为你在Combine对象中有一个函数,你不能检查两个函数是否相等(这是赖斯定理的结果)。
  • 所以我必须将函数应用于某些参数并尝试一下?我知道我的 semigroup 实现有效,因为我可以在 ghci 中对其进行测试
  • @WillemVanOnsem QuickCheck 一直用于检查(有点)两个函数是否相等——不是通过实际证明它们相等,而是通过不证明它们不相等。
  • 我可以为 String 的简单 uncombine 函数做 Gen -> String, \n -&gt; n(身份)
  • @Calin:例如,您可以使用semigroupdAssoc a b c x = uncombine (a &lt;&gt; (b &lt;&gt; c)) x == uncombine ((a &lt;&gt; b) &lt;&gt; c) x 作为签名semigroupdAssoc :: (Eq b, Semigroup a) =&gt; Combine a b -&gt; Combine a b -&gt; Combine a b -&gt; b -&gt; Bool

标签: haskell


【解决方案1】:

我建议使用Fun 来编写您的属性:

type SS = Fun String String -- just to shorten things a bit

prop_CombineAssoc :: SS -> SS -> SS -> String -> Bool
prop_CombineAssoc f_ g_ h_ s =
    unCombine (f <> (g <> h)) s == unCombine ((f <> g) <> h) s
    where
    [f, g, h] = map (Combine . applyFun) [f_, g_, h_]

上面的属性通过了,但是为了好玩,下面是失败的样子。为了得到这个输出,我把(f &lt;&gt; (g &lt;&gt; h)) 改成了f

> quickCheck prop_CombineAssoc
*** Failed! Falsified (after 3 tests and 16 shrinks):    
{_->""}
{_->""}
{_->"a"}
""

如您所见,FunShow 实例比像 Combine 的实例那样简单地返回常量 String 提供更多信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2019-11-10
    相关资源
    最近更新 更多