Haskell 中的同构 `fmap`

Isomorphic `fmap` in Haskell

Haskell的Prelude里有这样的东西吗?

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

在我正在进行的项目中,我经常发现自己 'converting' 一个类型到另一个类型,处理它然后 'converting' 它返回。

按照 leftaroundabout 的建议重新排序参数,可以得到更整洁的定义:

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

至于图书馆支持,lens提供nifty support for isomorphisms。更广泛一点,正如 Gurkenglas 指出的那样...

Functor f => (b -> f b) -> a -> f a is also called Lens' a b and is the centerpiece of the lens library.

如果不深入了解其工作原理和原因的细节,一个结果是您的函数可能定义为:

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 的(特殊版本),它给出了一个函数,该函数可用于在同构 "destination" 上转换 b -> f b 函数到同构 "source".

上的 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