Reordering the arguments, as leftaroundabout suggests, allows you to define a more precise definition:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> fb) -> a -> fa wfmap uwg = fmap w . g . u
Regarding library support, the lens provides excellent support for isomorphisms . A little wider, as Gurkenglas notes ...
Functor f => (b -> fb) -> a -> fa also called Lens' ab and is a central element of the lens library.
Without going into details of how and why this works, one of the consequences is that your function can be defined as:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> fb) -> a -> fa wfmap uwg = (iso uw) g
Or even:
wfmap :: Functor f => (a -> b) -> (b -> a) -> (b -> fb) -> a -> fa wfmap = iso
wfmap is just a (specialized version) iso that produces a function that can be used to convert the function b -> fb to the "destination" of an isomorphism on a -> fa on the "source" isomorphism.
It is also worth mentioning mapping , which can be used for a slightly different purpose of applying fmap on the other side of isomorphism:
GHCi> :t \uwg -> over (mapping (iso uw)) (fmap g) \uwg -> over (mapping (iso uw)) (fmap g) :: Functor f => (s -> a) -> (b -> t) -> (a -> b) -> fs -> ft GHCi> :t \uwg -> under (mapping (iso uw)) (fmap g) \uwg -> under (mapping (iso uw)) (fmap g) :: Functor f => (s -> a) -> (b -> a1) -> (a1 -> s) -> fb -> fa
Finally, note that iso uw can be replaced with any iso that you can find in libraries or predefined elsewhere.
source share