5

I m new in haskell's world and I m having some troubles with function signatures :

What does it mean in simple worlds :

add:: Integer -> Integer -> Integer

Does it mean that the two first parameters are Integer and the returned value is Integer too ?

Can you explain me, the aim of using arrows to determine a type of parameter or at least give me a brief explanation about this function signature ?

Cactus
  • 27,075
  • 9
  • 69
  • 149
Thomas thomas
  • 795
  • 2
  • 9
  • 19

3 Answers3

18

Colloquially we may indeed refer to add as a function that takes two Integers and produces an Integer. However to understand the notation, you need to understand that technically there's no such thing as a function that takes two arguments in Haskell.

Rather every function takes exactly one argument and the type of a function is written a -> r where a is the type of the argument and r is the type of the result. The function arrow is right-associative, which means that the type a -> (b -> c) can be written without parentheses as a -> b -> c.

So Integer -> Integer -> Integer is the same as Integer -> (Integer -> Integer), which tells us that add is a function that takes an Integer and produces another function of type Integer -> Integer. This is known as currying and is the usual way to "encode" multi-argument functions in Haskell.

To call such a curried function, we can write add 1 2, which, because function application is left associative, is the same as (add 1) 2, first calling add 1 to get a function of type Integer -> Integer and then applying that function to the argument 2.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
5

As a simple mental model - yes, the thing after the last arrow is a return type, and everything else are parameters.

Signatures for 2-and-more-ary functions look this way because they are actually unary functions returning another 1-and-more-ary function.

In your case

add :: Integer -> (Integer -> Integer)

Passing add an argument gives

add 3 :: (Integer -> Integer)

And add 3 4, therefore is just Integer type.

arrowd
  • 33,231
  • 8
  • 79
  • 110
  • 6
    I guess, a reference to [currying](https://wiki.haskell.org/Currying) and [partial application](https://wiki.haskell.org/Partial_application) for details wouldn't hurt. – bereal Jan 11 '16 at 12:02
3

The short answer is yes: it's exactly what it means. The last type is the return value, all others are arguments.

This is so for a very simple reason, namely: there's no such thing as multi-agrument function in Haskell. All functions are single-argument in reallity, function's general type being a -> b. Then we have something looking like multi-parameter functions thanks to currying. All you need to understand this are parentheses:

add :: Integer -> (Integer -> Integer)

Which reads: add is a function which takes an Integer and returns a function Integer -> Integer. All parentheses sqeeze on the right-hand side here. On the contrary, when you apply, all parentheses squeeze on the left hand size, like so:

(add 5) 6

Which reads: apply add to argument 5. In return you'll get a function - then apply that function to 6 (the final result being 11). We could equally well define it like so:

add :: Integer -> (Integer -> Integer)
add x = \y -> x + y

So the fact that you can specify multiple arguments for a function is only a syntactic sugar so that you don't have to return all these lambdas down the road.

This very fact is also why we can do this:

add5 :: Integer -> Integer
add5 = (+5)
Sventimir
  • 1,996
  • 3
  • 14
  • 25