class (Functor t, Foldable t) => Traversable t where
traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
traverse g = sequenceA . fmap g
sequenceA :: Applicative f => t (f a) -> f (t a)
sequenceA = traverse idTraversable如何利用它同时继承了Foldable和Functor这一事实
作为一种可遍历类型,t意味着t也是一种函数式类型和一种可折叠类型。
我看到在traverse中使用了t是一个函数式类型,即fmap。
t是一种可折叠类型的事实是否在某些地方被使用?
traverse是否利用了t是可折叠类型的事实?
sequenceA使用哪个事实:t是函数式类型,t是可折叠类型,还是两者兼而有之?
我们能定义一个只是Functor的子类的类,并且以相同的方式定义traverse和sequenceA函数吗?
谢谢。
发布于 2019-07-30 12:12:39
未使用Foldable实例。尽管如此,请求Foldable是很好的,因为如果我们可以traverse一个东西,那么我们就可以foldMap它:
foldMapDefault :: (Traversable t, Monoid m) => (a -> m) -> t a -> m
foldMapDefault f = fst . traverse (\a -> (f a, ()))这里的基本思想是使用标准的编写器monad;由于编写器的绑定操作使用mappend来组合“写入”部分--这里是f a值-- traverse将把正确的东西绑定在一起( mappend )。(它还将构建一个我们实际上并不关心的t ();丢弃这一部分是fst的工作。)
为了简单和自包含,我使用了编写器monad,但真正的实现使用了稍微让人费解的Const应用程序,以避免构建(然后丢弃)毫无意义的t ()值。您可以查看foldMapDefault here及其实现here的文档。
发布于 2019-07-30 12:16:49
在here中,类Traversable是一个Functor和一个Foldable,并且必须满足以下规则:
Foldable可以看到更多here。这意味着它可以折叠(foldMap,foldr,foldl...)
traverse函数必须满足以下规则:
T.遍历f=遍历(t .f)对于每个应用变换t
遍历标识= Identity
traverse (合成fmap g.f) =作曲。fmap (导线g)。遍历f
和sequenceA:
T.sequenceA = sequenceA。
sequenceA。fmap标识= Identity
sequenceA。fmap Compose = Compose。fmap sequenceA。sequenceA
sequenceA使用哪个事实:不是函数式类型,不是可折叠类型,还是两者兼而有之?
Traversable,正如它的定义所说(以及上面引用的法律):
class (Functor t, Foldable t) => Traversable t where既是一个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的理由),因为它很有用。
发布于 2019-07-30 20:22:45
一般来说,子类化有两个主要原因:
Functor的情况。Foldable.的情况
https://stackoverflow.com/questions/57264117
复制相似问题