从这里可以看到,类Traversable
是一个Functor
和一个Foldable
,必须满足以下规律:
而Foldable
更多信息见这里。这意味着它可以被折叠(foldMap,foldr,foldl...)
traverse
函数必须满足以下规律:
自然性:
对于每个应用变换t,t.traverse f = traverse (t.f)
身份
traverse Identity = Identity
组合
traverse(Compose.fmap g.f)=Compose.fmap(traverse g).traverse f
还有sequenceA:
自然性
t.sequenceA = sequenceA.fmap t对于每个应用变换t
身份
sequenceA.fmap Identity = Identity
组合
sequenceA.fmap Compose = Compose.fmap sequenceA.sequenceA
sequenceA使用哪个事实:t是Functor类型,t是Foldable类型还是两者兼而有之?
Traversable
,正如它的定义所说(以及上面引用的规律):
class (Functor t, Foldable t) => Traversable t where
它既是一个Functor,又是一个Foldable,必须遵守的规则不仅限于Functor,它更为具体,但仍然是一个Functor,因为满足Functor的规则并且可以使用其类型类接口中的函数,甚至比Foldable更为具体,因此更强大、更少通用、更有约束力。
那么事实是什么呢?定义如此,但Traversable
的设计者为什么选择了这两个?因为它们很有用,正如@Daniel Wagner的回答所示。其他例子:
instance Traversable [] where
traverse f = List.foldr cons_f (pure [])
where cons_f x ys = liftA2 (:) (f x) ys
这个例子使用了foldr
函数。
instance Foldable [] where
elem = List.elem
foldl = List.foldl
foldl' = List.foldl'
foldl1 = List.foldl1
foldr = List.foldr
foldr1 = List.foldr1
length = List.length
maximum = List.maximum
minimum = List.minimum
null = List.null
product = List.product
sum = List.sum
toList = id
所以,
Traverse
是一个
Functor
和
Foldable
,所以在需要时可以使用其接口的函数。(例如中的示例只是一个示例,而不是为什么设计者选择使用
Functor
和
Foldable
来定义
Traversable
的正当理由),因为这很有用。
Const
应用函子了。 - Daniel Wagner