跳棋和 EqProp

Checkers and EqProp

我正在浏览 Haskell Book and the chapter on applicatives started using the checkers 库进行测试。

这个库引入了EqProp类型类,我不明白它和Eq有什么不同。大多数需要 EqProp 的示例在后台都使用 Eq

为什么人们使用跳棋而不是 QuickCheck?

重点是函数和无限值不具有可判定相等性(Eq),但可以测试为此(EqProp)通过观察(随机)有限片段。

This library introduces the EqProp typeclass, and I don't understand how this differs from Eq.

(==) 来自 Eq 给你一个 BoolEqProp 中的 (=-=) 为您提供快速检查 Property。如果您有 Eq 的实例,您也可以将其设为 EqProp 实例,as witnessed by eq. The interesting instances of EqProp are those that aren't instances of Eq, such as functions (cf. ).

Why do people use checkers over Quickcheck?

Checkers 是一套基于 QuickCheck 的额外工具。因为它的 readme and Hackage description suggest, one of its goals is making it easy to express class laws as Quickcheck properties. For instance, note how the definition of the applicative "test batch",我将在下面引用,看起来很像我们经常写的 Applicative 法则,并且很好 self-documenting.

(请随意跳过 top-level 签名中的簿记约束。另请注意,m (a,b,c) 参数以 simplest-thing-that-could-possibly-work 的方式仅用于类型特化,意图是您通过 undefined :: [(Int,Int,Int)] 来测试 Applicative 的列表实例。)

-- | Properties to check that the 'Applicative' @m@ satisfies the applicative
-- properties
applicative :: forall m a b c.
               ( Applicative m
               , Arbitrary a, CoArbitrary a, Arbitrary b, Arbitrary (m a)
               , Arbitrary (m (b -> c)), Show (m (b -> c))
               , Arbitrary (m (a -> b)), Show (m (a -> b))
               , Show a, Show (m a)
               , EqProp (m a), EqProp (m b), EqProp (m c)
               ) =>
               m (a,b,c) -> TestBatch
applicative = const ( "applicative"
                    , [ ("identity"    , property identityP)
                      , ("composition" , property compositionP)
                      , ("homomorphism", property homomorphismP)
                      , ("interchange" , property interchangeP)
                      , ("functor"     , property functorP)
                      ]
                    )
 where
   identityP     :: m a -> Property
   compositionP  :: m (b -> c) -> m (a -> b) -> m a -> Property
   homomorphismP :: (a -> b) -> a -> Property
   interchangeP  :: m (a -> b) -> a -> Property
   functorP      :: (a -> b) -> m a -> Property

   identityP v        = (pure id <*> v) =-= v
   compositionP u v w = (pure (.) <*> u <*> v <*> w) =-= (u <*> (v <*> w))
   homomorphismP f x  = (pure f <*> pure x) =-= (pure (f x) :: m b)
   interchangeP u y   = (u <*> pure y) =-= (pure ($ y) <*> u)
   functorP f x       = (fmap f x) =-= (pure f <*> x)