Reputation: 6855
I sometimes find myself in a case where I need to create a function that maps a different function to two values, and then combines them together. How to do that without using a lambda ?
My functions are:
f :: a -> b
g :: c -> d
combine :: b -> d -> e
The question is: how to write \x y -> combine (f x) (g y)
without using a lambda ?
Upvotes: 3
Views: 222
Reputation: 2366
If f = g
you can use on
in Data.Function
. Otherwise there is no combinator for that in base
. A stackage search for the appropriate type reveals biSp
from concatenative
.
biSp :: (a -> c) -> (b -> d) -> (c -> d -> e) -> a -> b -> e
However if that is the only function you will be using from that package, you may not want to depend on a package just for that.
Other than that you can use the following which would be at least marginally shorter, but not really more readable.
(. g) . combine . f
Or using dimap
in Data.Profunctor
from profunctors
. While this also requires another package, it is likely that you are already depending on profunctors
indirectly anyway, because you are using lens
or some package depending on lens
.
dimap f (. g) combine
This can easily be extended to three arguments. The following all do the same and are ordered from shortest to most structured and with the last two it is especially easy to extend them to any number of arguments.
dimap f (dimap g (. h)) combine3
(dimap f . dimap g) (. h) combine3
(dimap f . dimap g . dimap h) id combine3
If you wonder what this dimap
does. This is a great tutorial: I love profunctors. They're so easy.
Or just write your own biSp
.
Upvotes: 7
Reputation: 34398
An alternative pointfree spelling involves handling the arguments as a pair by using curry
, uncurry
and either (***)
(from Control.Arrow
) or bimap
(from Data.Bifunctor
):
GHCi> :t \combine f g -> curry (uncurry combine . (f *** g))
\combine f g -> curry (uncurry combine . (f *** g))
:: (a1 -> b1 -> c) -> (a -> a1) -> (b -> b1) -> a -> b -> c
Note that, unlike jpath's suggestions, this isn't even shorter than the non-pointfree version.
Upvotes: 4