5

以下代码未通过检查器测试以进行可遍历。我会很感激解释它为什么失败,而不仅仅是如何修复它。

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))))
4

1 回答 1

6
instance Foldable List where
  foldr f z (Cons x xs) = f x z
  foldr _ z Nil = z

您的 Foldable 实例不会遍历列表的尾部。


checkers通过测试和一起测试您的Traversable实例:它派生自您的实现,并确保它们产生与您定义的结果相同的结果。FunctorFoldablefoldMapfmapTraversablefoldMapfmap

于 2016-03-21T11:15:12.900 回答