Reputation: 511
I just started learning haskell and i'm not able to solve this issue. Can someone tell me why i get error that g
is applied to too few arguments in the code below.
f :: Int -> Int
f first = 5+first
g :: Int -> Int -> Int
g first second = first+second
compute :: (Int -> Int) -> (Int -> Int -> Int) -> Int -> Int -> Int
compute f g x y = (f . g) x y
Upvotes: 0
Views: 1419
Reputation: 531055
First, look at the definition of f . g
:
f . g = \x -> f (g x)
Then we can expand the definition of compute
as follows:
compute f g x y = (f . g) x y
= (\z -> f (g z)) x y
= (f (g x)) y
= (5 + (g x)) y
g x : Int -> Int
, for which there is no Num
instance, so you can't add it to 5.
The problem is that you want g
applied to both x
and y
before its result is passed to f
. To do that, you need something more than simple composition. The simplest way to write this is directly:
compute f g x y = f (g x y)
If you are aiming for something more point-free, you need to get fancy with the composition:
compute f g = \x -> \y -> f (g x y)
-- application is left-associative
= \x -> \y -> f ((g x) y)
-- def'n of (.)
= \x -> f . (g x)
-- eta abstraction
= \x -> (\z -> f . z) (g x)
-- def'n of an operator section
= \x -> (f .) (g x)
-- def'n of (.)
= (f .) . g
If you want to be completely point-free, you can write
compute = (.) . (.)
You compose the composition operator with itself.
Upvotes: 5
Reputation: 152707
A common mistake is to think that the function composition operator .
passes along "as many arguments as needed". But this isn't the case: it threads only one argument through.
So when you write
(f . g) x y
you are probably hoping that this meant
f (g x y)
but it actually means
f (g x) y
-- that is, y
gets passed to f
as a second argument, instead of g
. Whoops!
Upvotes: 8