Haskell 为什么列表的这个可遍历实例不正确?

Haskell 为什么列表的这个可遍历实例不正确?,haskell,traversable,Haskell,Traversable,下面的代码未通过可遍历的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 = N

下面的代码未通过可遍历的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)
您的可折叠实例不会遍历列表的尾部



checkers
通过同时测试
Functor
Foldable
来测试您的
Traversable
实例:它从您的
Traversable
实现中派生
foldMap
fmap
,并确保它们产生的结果与您的
foldMap
fmap
相同已定义。

但如何编写可折叠实例?它需要一个
b
而不是
列表b
,所以我不能写像
foldr f z(Cons x xs)=Cons(f x z)(foldr f z xs)
@TheUnfunCat By
foldr f z xs
这样的东西,你得到了一个
b
,再加上
x
,现在你有了两个
a
b
,如果有一个函数从它们中产生一个新的
b
。?Const是我能想到的唯一一个。。。类中可能有一些用于Applicative或whatevz,但我被难住了。@TheUnfunCat尝试再次查看foldr的类型签名:
(a->b->b->t a->b
好的,明白了:
foldr f z(Cons x xs)=f x(foldr f z xs)
,但不明白它为什么工作。只需遵循bitemyapps的建议,
不必立即为自己不懂的内容而烦恼。继续走
λ> 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))))
instance Foldable List where
  foldr f z (Cons x xs) = f x z
  foldr _ z Nil = z