为什么Functor类型类不包含fold方法?

时间:2015-07-30 13:28:48

标签: haskell

为什么类型类Functor只有成员fmap?我经常发现执行折叠数据类型很有用。比如说,分层的,就像一棵树。

请注意,mapfold的特例,即后者更为基础。我想我可以采取它的方式,但也许有一个原因?

2 个答案:

答案 0 :(得分:12)

因为Functor是一种非常普遍的对象;并非所有Functor支持折叠。例如,有一个实例 1

instance Functor (a ->) where
     -- > fmap :: (b -> c) -> (a -> b) -> (a -> c)
     fmap f g = g . f

但是,虽然(a ->)对于所有Functor来说都是a,但对于无限a,并没有合理的fold定义。 (顺便说一句,'折叠通常是catamorphism,这意味着它对每个仿函数都有不同的类型。Foldable类型类为序列类型定义它。)

考虑foldr的{​​{1}}定义是什么样的;最外层的应用程序是什么?

的价值是什么?
Integer -> Integer

是? foldr (\ _ n -> 1 + n) 0 (\ n -> n + 1) 没有合理的定义,在参数类型上没有更多的结构。

由于某种原因,

1 fold并非合法的Haskell。但我仍然会使用它作为(a ->)的更易阅读的版本,因为我觉得新手更容易理解。

答案 1 :(得分:6)

您正在寻找的抽象是Foldable:这是一个类型类,提供fold的各种形式。

对于可以“更改时折叠”的内容,还有Traversable,与列表的mapAccumL功能相当。

fmap实际上并不是fold的特殊情况,正如@DietrichEpp所指出的那样,请看possible non-Functor instances of Foldable

mapmapAccumL的一个特例(给出名称并不奇怪),因此Traversable的定义要求该事物也是FunctorFoldable