在深入研究Applicative
时,我来到了Traversable
。虽然我已经知道LYHGG中的Foldable
,但我还没有见过前者,所以我开始阅读Haskell wiki about Traversable。
在阅读时,我理解为什么Foldable.fold
与Traversable.sequenceA
平行且Foldable.foldMap
与Traversable.traverse
平行。
我还看到每个Traversable
也是Foldable
和Functor
,sequenceA
和traversal
都有默认实现彼此的条款:
traverse f = sequenceA . fmap f
sequenceA = traverse id
所以,正如我在LYHGG中看到foldMap
是Foldable
的最小完整定义,我认为,它与traverse
平行,所以fold
(与sequenceA
平行的,也是一个最小的完整定义(它不是......)Foldable
不是像Functor
那样的Traversable
,所以我们不能应用这个:
foldMap f = fold . fmap f
fold = foldMap id -- this is ok
为什么不是每Foldable
个Functor
,Foldable
实际上不是Functor
的实例是什么?
答案 0 :(得分:9)
正如dfeuer所说,Set
是Foldable
的一个很好的例子,它不是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
成为一个仿函数,这实际上暗示了一个真正的数学问题,而不仅仅是对我们类型类机器的限制。