I have three functions xyz and a function called functionComposer.
I want functionComposer to have as arguments the functions xyz and to return me a function that uses the result of y and z as arguments into x and applies x.
In mathematical notation: x(y(a),z(b))
Im NOT asking for this : functionComposer xyz = xyz
For example:
double x = x + x
summer x y = x + y
functionComposer summer double double = summer (double) (double)
if x = 2 the result should be 8 (2+2)+(2+2)
You can also use the applicative instance for (->) a
like so
import Control.Applicative
funcComp summer double1 double2 = summer <$> double1 <*> double2
Or the monad instance
funcComp summer double1 double2 = liftM2 summer double1 double2
The way to understand this is that for (->) a
, both the applicative and the monad instance are meant to "parametrize" over the function value that double1
and double2
both accept.
Using your notation:
functionComposer summer double1 double2 = \x -> summer (double1 x) (double2 x)
The \\x -> ...
represents the function mapping x
to the ...
.
Note I had to give different names to the double
function argument, since in general you want to compose different functions.
I somehow feel as if you wanted a confusing series of dots anyways, so:
functionComposer :: (c -> d -> e) -> (a -> c) -> (b -> d) -> a -> b -> e
functionComposer x y z = (. z) . (x . y)
which comes “naturally” from
functionComposer x y z a = (x . y) a . z
But why stop there?
functionComposer x y = (. (x . y)) . flip (.)
No, more:
functionComposer x = (. flip (.)) . flip (.) . (x .)
More!
functionComposer = (((. flip (.)) . flip (.)) .) . (.)
You're basically evaluating y
and z
"in parallel 1 ". The most fundamental combinator to express this is (***) :: Arrow f => fac -> fbd -> f (a, b) (c, d)
. The result of that you want to feed to x
, so basically you'd like to write
x . (y***z) -- or x <<< y***z
Now that doesn't quite do the trick because the arrow combinators work with tuples. So you need to uncurry x
. Much the same way, if you want the entire thing to accept the arguments in the normal curried fashion, then you must curry out the (a,b)
tuple. Easy enough though:
functionComposer :: (c -> d -> e) -> (a -> c) -> (b -> d) -> a -> b -> e
functionComposer x y z = curry $ uncurry x <<< y *** z
1 Mind, I don't mean parallel in the multithreading sense, only "semantically parallel".
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.