我遇到了两个例子:
data List a =
Nil
| Cons a (List a)
deriving (Eq, Show)
instance Eq a => EqProp (List a) where
(=-=) = eq
newtype ZipList' a =
ZipList' (List a)
deriving (Eq, Show)
instance Eq a => EqProp (ZipList' a) where
xs =-= ys = xs' `eq` ys'
where xs' = let (ZipList' l) = xs
in take' 3000 l
ys' = let (ZipList' l) = ys
in take' 3000 l
take' :: Int -> List a -> List a
take' n (Cons a as) = Cons a (take' (n - 1) as)
(还有Functor
和Applicative
实例正在测试中):
main :: IO ()
main =
hspec $ do
describe "List" $ do
it "Functor" $
property (quickBatch $ functor (undefined :: List (Int, Float, String)))
it "Applicative" $
property
(quickBatch $ applicative (undefined :: List (Int, Float, String)))
describe "ZipList'" $ do
it "Functor" $
property
(quickBatch $ functor (undefined :: ZipList' (Int, Float, String)))
it "Applicative" $
property
(quickBatch $ applicative (undefined :: ZipList' (Int, Float, String)))
据我了解,我们采用3000个值,因为否则测试将永远追逐无限列表。但是在第一个示例中,也有一个无限的列表,不是吗?那么为什么EqProp
在这种情况下琐碎呢?
您的属性测试库(我知道quickCheck,但不知道quickBatch)应该在生成值时(而不是在比较值时)管理数据大小。在相等性检查中限制大小是一个坏主意,因为这意味着
既然已经有和的实例,[]
并且ZipList
是一个,newtype
我们可以像这样免费获得实例。
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
deriving instance Eq a => EqProp (ZipList' a)