traverse :: Applicative f => (a -> f b) -> t a -> f (t b)
您好,
有很多功能我无法理解签名。当然,我认为遍历得到两个参数,首先是函数。然而,
什么意思是(a -> f b)
?我能理解(a -> b)
相似,t a
,f (t b)
你能解释一下吗?
答案 0 :(得分:3)
traverse
是一个类型类函数,很遗憾,这个函数的行为取决于我们选择t
到底是什么。这与>>=
或fmap
不相似。然而,它的行为有规则,就像那些情况一样。规则应该捕捉到traverse
采用函数a -> f b
的想法,这是从a
到b
的有效转换,并将其提升为整个“容器” “a
s,收集每个局部变换的影响。
例如,如果我们Maybe a
traverse
的实施将是
traverse f (Just a) = Just <$> f a
traverse f Nothing = pure Nothing
列表
traverse f [a1, a2, ...] = (:) <$> f a1 <*> ((:) <$> f a2 <*> ...))
请注意我们如何利用“效果”f
不仅仅是一个仿函数,而且是适用的这一事实,因此我们可以进行两次f-ful计算,f a
和{{1并将它们粉碎在一起以获得f b
。现在我们想要提出一些法律,解释所有遍历可以做的是将f (a, b)
应用于元素并构建原始f
,同时收集对其的影响外。我们说那个
t a
现在这看起来相当复杂,但它所做的只是澄清“基本上四处走动并应用本地转型”的含义。所有这一切归结为,虽然你不能只是阅读签名来理解 traverse Identity = Identity -- We don't lose elements
t . traverse f = traverse (t . f) -- For nicely composing t
traverse (Compose . fmap g . f) = Compose . fmap (traverse g) . traverse f
的作用,但签名的直觉是
traverse
f :: a -> f b
s a
,ala b
f
的仿函数
fmap
的所有效果,因此我们得到f
,而不只是f (t b)
。请记住,t b
可以用一些奇怪的方式使用。例如,镜头包充满了使用traverse
和非常奇怪的仿函数,效果很好。
作为快速测试,您能否弄清楚如何使用合法traverse
为traverse
实施fmap
?那是
t
或fmapOverkill :: Traversable f => (a -> b) -> (f a -> f b)
headMay
这两个都是可遍历实例也满足headMay :: Traversable t => t a -> Maybe a
和Functor
这一事实的结果!