請注意,這個證明實際上並非必要,因爲問題的結果確實是一個自由定理。見裏德巴頓的答案。
我相信,這將做到:
traverse f . fmap g -- LHS
由fmap/traverse
法律,
traverse f . runIdentity . traverse (Identity . g)
由於fmap
爲Identity
實際上是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)
再次使用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
,加的fmap
獨特如下。
這很令人印象深刻。你是怎麼想出這個'getCompose的。撰寫技巧? – dfeuer
我建議提交此證明以包含在Data.Traversable文檔中。 – dfeuer
@dfeuer這是在合適的地方應用構圖法獲得Compose的最快方法。正如Control.Lens.Traversal文檔所做的那樣,如果我們在使用前將'getCompose'應用於構圖法的兩端,那麼這一步甚至可能會被抑制。 – duplode