理解haskell中函数遍历的签名

时间:2016-04-01 08:14:54

标签: haskell type-signature

traverse :: Applicative f => (a -> f b) -> t a -> f (t b)

您好,
有很多功能我无法理解签名。当然,我认为遍历得到两个参数,首先是函数。然而,
什么意思是(a -> f b)?我能理解(a -> b) 相似,t af (t b)

你能解释一下吗?

1 个答案:

答案 0 :(得分:3)

traverse是一个类型类函数,很遗憾,这个函数的行为取决于我们选择t到底是什么。这与>>=fmap不相似。然而,它的行为有规则,就像那些情况一样。规则应该捕捉到traverse采用函数a -> f b的想法,这是从ab的有效转换,并将其提升为整个“容器” “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和非常奇怪的仿函数,效果很好。

作为快速测试,您能否弄清楚如何使用合法traversetraverse实施fmap?那是

t

fmapOverkill :: Traversable f => (a -> b) -> (f a -> f b)

headMay

这两个都是可遍历实例也满足headMay :: Traversable t => t a -> Maybe a Functor这一事实的结果!