2016-12-03 63 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