Haskell 为什么列表的这个可遍历实例不正确?
下面的代码未通过可遍历的checkers测试。我希望你能解释它为什么会失败,而不仅仅是如何修复它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
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 Byfoldr 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