Does such a thing exist in Haskell's Prelude?
wfmap :: Functor f
      => a
      -> (a -> b)
      -> (b -> a)
      -> (b -> f b)
      -> f a
wfmap x u w g = fmap (w) (g (u x))
In a project I'm working on, I often found myself 'converting' a type to another, process it and 'converting' it back.
Reordering the arguments, as leftaroundabout suggests, allows for a tidier definition:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap u w g = fmap w . g . u
As for library support, lens provides nifty support for isomorphisms. A bit more broadly, as Gurkenglas notes...
Functor f => (b -> f b) -> a -> f ais also calledLens' a band is the centerpiece of the lens library.
Without diving into the details of how and why that works, one consequence is that your function might be defined as:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap u w g = (iso u w) g
Or even:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> f b) -> a -> f a
wfmap = iso
wfmap is just (a specialised version of) iso, which gives out a function which can be used to convert an b -> f b function on the isomorphism "destination" to an a -> f a one on the isomorphism "source".
It is also worth mentioning mapping, which can be used for the somewhat different purpose of applying fmap on the other side of an isomorphism:
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
Finally, note that iso u w can be replaced by any Iso you might find in the libraries or have predefined elsewhere.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With