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 a
is also calledLens' a b
and 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