如何显示遍历与fmap的合理交互?

时间:2015-09-25 23:45:44

标签: haskell traversal

直觉上很明显,以下法律应该成立:

traverse f . fmap g = traverse (f . g)

似乎直接申请的唯一Traversable法律是

fmap g = runIdentity . traverse (Identity . g)

将问题更改为

traverse f . runIdentity . traverse (Identity . g)

唯一适用于此的模糊形式的法则是自然法。然而,那是关于应用变换的,我没有看到任何这些变换。

除非我遗漏了什么,否则唯一剩下的就是参数化证明,而我还没有弄清楚如何写这些。

2 个答案:

答案 0 :(得分:6)

请注意,这个证明实际上并不是必需的,因为所讨论的结果确实是一个自由定理。请参阅Reid Barton的回答。

我相信这样做:

traverse f . fmap g -- LHS

根据fmap/traverse法律,

traverse f . runIdentity . traverse (Identity . g)

fmap的{​​{1}}实际上是Identity

id

runIdentity . fmap (traverse f) . traverse (Identity . g) 法律提供了将两个遍历合并为一个的方法,但我们必须首先使用Compose引入Compose

getCompose . Compose = id

再次使用runIdentity . getCompose . Compose . fmap (traverse f) . traverse (Identity . g) -- Composition law: runIdentity . getCompose . traverse (Compose . fmap f . Identity . g) Identity

fmap

runIdentity . getCompose . traverse (Compose . Identity . f . g) 是一种应用转型,因此本质上是

Compose . Identity

折叠反转,

runIdentity . getCompose . Compose . Identity . traverse (f . g)

为了完整起见,引用法律和推论:

traverse (f . g) -- RHS

后一事实遵循身份法-- Composition: traverse (Compose . fmap g . f) = Compose . fmap (traverse g) . traverse f -- Naturality: t . traverse f = traverse (t . f) -- for every applicative transformation t -- `fmap` as traversal: fmap g = runIdentity . traverse (Identity . g) ,加上traverse Identity = Identity的唯一性。

答案 1 :(得分:4)

根据lambdabot,它是一个自由定理(参数)。

响应@free traverse :: (a -> F b) -> T a -> F (T b),lamdabot产生

$map_F g . h = k . f => $map_F ($map_T g) . traverse h = traverse k . $map_T f

设置g = id以便h = k . f。然后结论变成

traverse (k . f) = traverse k . fmap f