I want to be able to build them. It does not make any sense, but it is for the purpose of training.
This is actually the problem here. How do you want to create them? Let's look at some possible compositions:
foo xy = sub x (add xy) -- x + y - x = y foo xy = sub y (add xy) -- x + y - y = x foo xy = sub x (add yy) -- 2 * y - x foo xy = sub y (add yy) -- 2 * y - y = y foo xy = sub y (sub y (add xx)) -- 2 * x - 2 * y
In doing so, we will check the type error by checking the types from hand:
type I = Integer
As you can see, (.) add already requires that another function can be of type a -> Integer for an arbitrary a . But sub type Integer -> (Integer -> Integer) (remember, (->) is the correct associative).
Now, what can you do to fix this? First, consider the proposed type of foo :
foo :: (Integer -> Integer) -> (Integer -> Integer) -> Integer
This is indeed a very interesting type of function. How would you actually get your result? You just have two functions, but no values:
> foo fg =
You can solve this problem using the fixed point of one of the functions, and then apply the other:
> let x = fx in gx > > example = foo (const 12) (+1) -- returns 13
But that’s not what you had in mind, is it? At the moment, it is very important to think about the semantics of your composition. Since this is not clear, you cannot write a general way to create both functions here.
However, if you really meant
foo :: Integer -> Integer -> Integer -> Integer foo xyz = add (sub xy) z
then it is possible with
foo = (add .) . sub
So
(.) add :: (a -> I) -> a -> (I -> I) (.) ((.) add) :: (a -> b -> Integer) -> a -> b -> Integer -> Integer
But (add .) . sub (add .) . sub is actually not that simple. You'd better write the exact definition of foo if this function was your original goal.