Khan Saab
Khan Saab

Reputation: 511

Function is applied to too few arguments in haskell

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

Answers (2)

chepner
chepner

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

Daniel Wagner
Daniel Wagner

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

Related Questions