可折叠vs可穿越

时间:2016-03-08 02:18:26

标签: haskell functor applicative foldable traversable

在深入研究Applicative时,我来到了Traversable。虽然我已经知道LYHGG中的Foldable,但我还没有见过前者,所以我开始阅读Haskell wiki about Traversable

在阅读时,我理解为什么Foldable.foldTraversable.sequenceA平行且Foldable.foldMapTraversable.traverse平行。

我还看到每个Traversable也是FoldableFunctorsequenceAtraversal都有默认实现彼此的条款:

traverse f = sequenceA . fmap f
sequenceA = traverse id

所以,正如我在LYHGG中看到foldMapFoldable的最小完整定义,我认为,它与traverse平行,所以fold(与sequenceA平行的,也是一个最小的完整定义(它不是......)Foldable不是像Functor那样的Traversable,所以我们不能应用这个:

foldMap f = fold . fmap f
fold = foldMap id -- this is ok

为什么不是每FoldableFunctorFoldable实际上不是Functor的实例是什么?

1 个答案:

答案 0 :(得分:9)

正如dfeuer所说,SetFoldable的一个很好的例子,它不是Functor

考虑Set.map的类型:

map :: Ord b => (a -> b) -> Set a -> Set b

请注意,这几乎 fmap,但它需要额外的Ord b约束。由于您有此约束,因此无法将其设为Functor

的实例

请注意,即使有此限制,Set也不是Haskell的仿函数。鉴于巧妙设置Eq个实例,我们可以违反fmap f . fmap g === fmap (f . g)的法律。有关进一步的讨论,请参阅此Stack Overflow question

如上所述,Set ({1}}""子类别中的(endo)仿函数。将有序类型作为集合并使用保留订单的地图作为态射。

所以,即使它不明显,我们不能使Hask成为一个仿函数,这实际上暗示了一个真正的数学问题,而不仅仅是对我们类型类机器的限制。