【发布时间】: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 -> n(身份) -
@Calin:例如,您可以使用
semigroupdAssoc a b c x = uncombine (a <> (b <> c)) x == uncombine ((a <> b) <> c) x作为签名semigroupdAssoc :: (Eq b, Semigroup a) => Combine a b -> Combine a b -> Combine a b -> b -> Bool
标签: haskell