# [Haskell-beginners] Function Type Confusion ..

Tom Poliquin poliquin at softcomp.com
Tue Jan 27 13:47:40 EST 2009

```On Tue, Jan 27, 2009 at 09:42:54AM -0800, Tom Poliquin wrote:
>
> I was reading "Arrows and Computation"
>
> http://www.soi.city.ac.uk/~ross/papers/fop.ps.gz
>
> (trying to lose my 'beginner' status) when I saw (on page
> one)
>
> add :: (b -> Int) -> (b -> Int) -> (b -> Int)
> add f g b = f b + g b
>
> It seemed like the type definition was wrong (short at least).

> .....

> The trick is this:
> add :: (b -> Int) -> (b -> Int) -> (b -> Int)
> is equal to
> add :: (b -> Int) -> (b -> Int) -> b -> Int

Wow! .. Thanks everyone for the fast and informative responses.

I get it now.

I'm an old time imperative (C, Java, etc) programmer and
I find Haskell incredibly powerful ... and fun!

Now I can move on to  page two in "Arrows and Computation" ..

Thanks again ..

Tom

On Tuesday 27 January 2009 10:39, Brent Yorgey wrote:
> On Tue, Jan 27, 2009 at 09:42:54AM -0800, Tom Poliquin wrote:
> > I was reading "Arrows and Computation"
> >
> > http://www.soi.city.ac.uk/~ross/papers/fop.ps.gz
> >
> > (trying to lose my 'beginner' status) when I saw (on page
> > one)
> >
> > add :: (b -> Int) -> (b -> Int) -> (b -> Int)
> > add f g b = f b + g b
> >
> > It seemed like the type definition was wrong (short at least).
>
> Hi Tom, that's a great paper to read!  I think your confusion seems to
> stem from this simple fact: every function in Haskell only takes one
> argument.
>
> Functions that look like they take multiple arguments, for example
>
>   add :: Int -> Int -> Int
>   add x y = x + y
>
> are really one-argument functions which return functions.  In the
> above example, 'add' is a function which takes a single Int, and
> returns a function as output.  This output function also takes a
> single Int and finally returns an Int.  Observe:
>
> Prelude> let add x y = (x + y :: Int)
> add :: Int -> Int -> Int
> add 3 :: Int -> Int
> Prelude> :t (add 3) 5
> (add 3) 5 :: Int
> 8
> 8
>
> So we could also write the type of 'add' like this:
>
>   add :: Int -> (Int -> Int)
>
> and in fact, this add's real type.  Int -> Int -> Int is just an
> abbreviation; -> associates to the right, so we can omit parentheses
> that occur at the rightmost end of a type.  As you can see above, by
> the same token, function application associates to the left, so 'add 3
> 5' is really just an abbreviation for '(add 3) 5': ie., first apply
> 'add' to 3, obtaining another function as output, then apply that
> function to 5.
>
> By now I'm sure you can see that
>
>   (b -> Int) -> (b -> Int) -> (b -> Int)
>
> is exactly the same type as
>
>   (b -> Int) -> (b -> Int) -> b -> Int.
>
> You can think of something of this type *either* as something which
> takes two arguments of type (b -> Int) and returns a function of type
> (b -> Int); *or* as something which takes three arguments, two of type
> (b -> Int) and one of type b, and returns something of type Int; these
> are in fact just two different ways to think about the same thing.
>