2015-09-25 37 views
13

似乎直觀明顯,下面的法律應持有:如何顯示遍歷與fmap的合理交互?

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

唯一Traversable法律,似乎申請是直接

fmap g = runIdentity . traverse (Identity . g) 

這改變了問題

traverse f . runIdentity . traverse (Identity . g) 

似乎有隱約適用於此的正確形狀的唯一法律是th自然法則。然而,這是關於應用性轉變,我沒有看到其中的任何轉變。

除非我遺漏了一些東西,剩下的唯一東西就是參數證明,而且我還沒有弄清楚如何編寫這些東西。

回答

6

請注意,這個證明實際上並非必要,因爲問題的結果確實是一個自由定理。見裏德巴頓的答案。

我相信,這將做到:

traverse f . fmap g -- LHS 

fmap/traverse法律,

traverse f . runIdentity . traverse (Identity . g) 

由於fmapIdentity實際上是id

runIdentity . fmap (traverse f) . traverse (Identity . g) 

Compose法提供了一種將兩次遍歷合併爲一個的方法,但是我們必須首先使用getCompose . Compose = id引入Compose

runIdentity . getCompose . Compose . fmap (traverse f) . traverse (Identity . g) 
-- Composition law: 
runIdentity . getCompose . traverse (Compose . fmap f . Identity . g) 

再次使用Identityfmap

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,加的fmap獨特如下。

+0

這很令人印象深刻。你是怎麼想出這個'getCompose的。撰寫技巧? – dfeuer

+0

我建議提交此證明以包含在Data.Traversable文檔中。 – dfeuer

+0

@dfeuer這是在合適的地方應用構圖法獲得Compose的最快方法。正如Control.Lens.Traversal文檔所做的那樣,如果我們在使用前將'getCompose'應用於構圖法的兩端,那麼這一步甚至可能會被抑制。 – duplode

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 
+0

'F'和'T'對於@free意味着什麼? – dfeuer

+1

什麼都不是,它們是任意類型的構造函數(也許它們需要是'$ map_F'的函數,但'traverse'類型中的'f'和't'無論如何都是函數)。 –

+0

大寫字母是否意味着它們代表特定類型而不是類型變量? – dfeuer