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