2

I have three functions x y z and a function called functionComposer.

I want functionComposer to have as arguments the functions x y z 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 x y z = x.y.z

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)

4
  • 1
    Your description is confusing; you initially say you have x and y as functions, a and b as args, but at the end you talk about an arg called x. Commented May 12, 2014 at 22:59
  • You can literally write what you already wrote and haskell will accept it : \x y z a b -> x(y(a),z(b)). Or without a tuple and extra parentheses: \x y z a b -> x (y a) (z b) Commented May 13, 2014 at 0:27
  • The problem with that is that if funcion y or z need more than one parameter the funcion would not work. I said that i got it just to be nice. But to be honest the solution here is just parcial. It works only if y and z are of the type y::a->c z::b->d . I was looking for a general solution. Commented May 13, 2014 at 1:37
  • for example. If i define a function: composer f1 f2 f3 = f1.f2.f3 the type of f3 is not necesary a->b , it can have more than one argument, it can be a->b->c->d or whatever. Commented May 13, 2014 at 1:42

4 Answers 4

10

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Lovely lovely Applicative. mmmmmm.
So, essentially, funcComp = liftA2.
This is not what the OP wants.
5

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.

Comments

1

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 (.)) .) . (.)

5 Comments

Something like this i was looking for. The point is that you are limiting the arguments that y and z can have. I dont want to define the type of y and z. I want them to be generinc functions that we know nothing about. If we define function composer without defining its type haskell should be able to infere the type of x y z (i believe...) and that would make the function more useful
For example, the previous point of this homework was to compone a function like this composingMachine1 x y z = x.y.z and the type of the function was composingMachine :: t1 -> t2 -> (t1 -> t2 -> t) ->t
@user3630355, all of the answers are generic.
Sorry if im extremely noobish but, in this case functionComposer x y z = (. z) . (x . y) the function is processing y and the result of that goes into x and the reslts of that goes into z right? If you can explaint it step by step i would be grateful.
That by itself is a little hard to explain, so let’s start with the full expansion of functionComposer x y z a b = x (y a) (z b). That can be turned into x (y a) on z, so functionComposer x y z a = x (y a) . z. x (y a) can also be written (x . y) a, so it’s functionComposer x y z a = (x . y) a . z. That can be written (.) ((x . y) a) z, which can be written flip (.) z ((x . y) a), and then it’s possible to take the a out in the same way as earlier as flip (.) z . (x . y). flip (.) z is (. z), so the whole thing ends up as (. z) . (x . y).
0

You're basically evaluating y and z "in parallel1". The most fundamental combinator to express this is (***) :: Arrow f => f a c -> f b d -> 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

1Mind, I don't mean parallel in the multithreading sense, only "semantically parallel".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.