以下代码无法通过checkers测试遍历。我很欣赏它失败的原因,而不仅仅是如何修复它。
import Test.QuickCheck
import Test.QuickCheck.Checkers
import Test.QuickCheck.Classes
data List a =
Nil
| Cons a (List a)
deriving (Show, Eq, Ord)
instance Functor List where
fmap _ Nil = Nil
fmap f (Cons x xs) = (Cons (f x) (fmap f xs))
instance Foldable List where
foldr f z (Cons x xs) = f x z
foldr _ z Nil = z
instance Traversable List where
traverse f Nil = pure Nil
-- traverse f (Cons x Nil) = Cons <$> f x <*> pure Nil
traverse f (Cons x xs) = Cons <$> f x <*> (traverse f xs)
instance Arbitrary a => Arbitrary (List a) where
arbitrary = sized go
where go 0 = pure Nil
go n = do
xs <- go (n - 1)
x <- arbitrary
return (Cons x xs)
type TI = List
instance Eq a => EqProp (List a) where (=-=) = eq
main = do
let trigger = undefined :: TI (Int, Int, [Int])
-- quickBatch (functor trigger)
quickBatch (traversable trigger)
您在此处看到它通过了fmap
法律,但未通过foldMap
法律:
λ> main
traversable:
fmap: +++ OK, passed 500 tests.
foldMap: *** Failed! Falsifiable (after 6 tests):
<function>
Cons 4 (Cons (-2) (Cons (-5) (Cons 5 (Cons 2 Nil))))
答案 0 :(得分:6)
instance Foldable List where
foldr f z (Cons x xs) = f x z
foldr _ z Nil = z
您的可折叠实例不会遍历列表的尾部。
checkers
通过一起测试Traversable
和Functor
来测试您的Foldable
个实例:它从{的实现foldMap
和fmap
中获取{ {1}}并确保它们与您定义的Traversable
和foldMap
产生相同的结果。