2016-12-03 51 views
6

Haskell's Prelude中是否存在這樣的事情?Haskell中的同構`fmap`

wfmap :: Functor f 
     => a 
     -> (a -> b) 
     -> (b -> a) 
     -> (b -> f b) 
     -> f a 
wfmap x u w g = fmap (w) (g (u x)) 

在一個項目中我的工作,我經常發現自己一型「轉換」到另一個過程中它和「轉換」回來。

+0

把'x :: a'作爲最後一個參數會更有意義嗎? – leftaroundabout

+0

@leftaroundabout哦,是的,它的確如此。感謝您指出了這一點。但這只是僞代碼來解釋我的問題。它只是我有很多函數和類型使用類似於這個模式,我想知道是否有更好的方式去做這件事。 – iluvAS

+2

您的'wfmap'在類型中聲明瞭5個參數,但在定義中只有4個參數。我想你只是在類型中增加了一個'a'類型的參數。 – chepner

回答

7

重新排序的參數,如leftaroundabout所暗示的,允許整潔定義:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = fmap w . g . u 

至於庫的支持,透鏡提供nifty support for isomorphisms。有點更廣泛,如Gurkenglas指出...

Functor f => (b -> f b) -> a -> f a也被稱爲Lens' a b,是鏡頭庫的核心。

沒有在深入的如何以及爲什麼這樣的作品,一個後果是細節,你的函數可以被定義爲:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap u w g = (iso u w) g 

甚至:

wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a 
wfmap = iso 

wfmap只是( iso的一個特殊版本,它給出了一個函數,它可以用來將同構「目標」上的一個b -> f b函數轉換爲一個a -> f a函數同構「源」。

還值得一提的mapping,可用於在同構的另一側將fmap的有所不同的目的:

GHCi> :t \u w g -> over (mapping (iso u w)) (fmap g) 
\u w g -> over (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> t) -> (a -> b) -> f s -> f t 
GHCi> :t \u w g -> under (mapping (iso u w)) (fmap g) 
\u w g -> under (mapping (iso u w)) (fmap g) 
    :: Functor f => (s -> a) -> (b -> a1) -> (a1 -> s) -> f b -> f a 

最後,請注意iso u w可以通過任何Iso代替你可能會在圖書館中找到或在其他地方預定義。

+0

感謝您的支持! :) – iluvAS