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 ?

3 Answers 3

19

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

I guess, a reference to currying and partial application for details wouldn't hurt.
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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.