为什么类型类Functor只有成员fmap?我经常发现对数据类型进行折叠很有用。比如,层次结构的数据类型,如树形结构。
请注意,map是fold的一种特殊情况,即后者更基本。我想我可以接受它现在的状态,但也许有一个原因?
请注意,map是fold的一种特殊情况,即后者更基本。我想我可以接受它现在的状态,但也许有一个原因?
因为Functor
是一种非常通用的对象,不是所有Functor
都支持折叠操作。例如,有一个实例1
instance Functor (a ->) where
-- > fmap :: (b -> c) -> (a -> b) -> (a -> c)
fmap f g = g . f
然而,尽管对于所有的 a
,(a ->)
都是一个 Functor
,但对于无限的 a
,没有一个合理的 fold
定义。(顺便说一句,通常情况下 'fold' 是一个catamorphism,这意味着对于每个 functor,它都有一个不同的类型。 Foldable
类型类为类似序列的类型定义了它。)
考虑一下 Integer -> Integer
的 foldr
定义会是什么样子;最外层的应用会是什么?
它的值会是什么?
foldr (\ _ n -> 1 + n) 0 (\ n -> n + 1)
如果没有更多关于参数类型的结构信息,fold
的合理定义是不存在的。
1 由于某种原因,(a ->)
不是合法的 Haskell 语法。但我仍将使用它作为 (->) a
更易读的版本,因为我认为这对新手来说更容易理解。
map
只是针对列表(或者其他一些东西)而言的 fold
的特例,而不是普遍适用的。谢谢。 - akonsufold
比其他类型(尤其是任意树)更加强大。从形式上来说(忽略惰性),列表函子是自由幺半函子,它是从幺半到集合的遗忘函子的左伴随;然后,一般的 fold
函数是列表函子和遗忘函子之间的同态集伴随的一个方向。因此,列表上的每个幺半同态(包括 map
)都可以通过某个 fold
实例给出。 - Jonathan CastFoldable
:这是一个类型类,提供各种形式的fold
(折叠)。
对于可以“在改变时折叠”的东西,也有Traversable
,可与列表的mapAccumL
函数相比较。map
是mapAccumL
的特殊情况(毫不奇怪,考虑到名称),因此Traversable
的定义要求该事物也是Functor
和Foldable
。fold
是基于map
定义的*,那么我们就可以为每个Functor
定义fold
,因为我们可以利用现有的map
免费获得fold
。 - Lynn
IO
上的fold
,它是一个Functor
但不是Foldable
? - Zetafmap
如何是fold
的特殊情况?我无法想象你如何能够用其中一个实现另一个,这就是我所谓的“更基本”的概念。 - Dietrich Eppfmap
是一个打字错误。我指的是map
。 - akonsu