Haskell has basic built-in scalar types Int, Float, Bool and Char. In addition, given a type T, you can form a list of elements of type T. The list has type [T]. Also, given types T1, T2, ..., Tk, you can form -tuples of type (T1,T2,...,Tk).
Functions have types--a function whose input type is T1 and output type is T2 has type T1 -> T2. For instance, the factorial function has type
factorial :: Int -> Int
Note the syntax :: to denote the type of a function.
What about a function such as max, that computes the maximum of two integer inputs? A natural definition of its type would be
max :: (Int x Int) -> Int
where (Int x Int) denotes the set of all pairs of type Int. In general a function of arguments would have type (T1 x T2 x ... x Tn) -> T where Ti is the type of argument and T is the return type. However, for this we have to record with each function its arity--that is, the number of arguments that it takes.
A convenient way to bypass this is to assume that each function takes only one argument. In the case of an -argument function, the return value after consuming the first argument is a function of arguments.
For instance, we rewrite the type of max as
max :: Int -> (Int -> Int)
This says that max takes as argument an Int and returns a function Int->Int. If we write
max 2 3
then (max 2) returns a function that we may think of as
``max_of_2_and
'' where
max_of_2_and :: Int -> Int max_of_2_and n = n, if n > 2 2, otherwise
In other words, we take a two argument function, freeze one argument and generate a new one argument function that reads only the second argument and has the frozen first argument ``built in'' to the definition.
To take another example, the function plus that adds two integers would now become
plus :: Int -> (Int -> Int)
and plus 2 3 would work as follows. (plus 2) returns a
function ``plus_2
'' where
plus_2 :: Int -> Int plus_2 n = 2+n
Given this convention, we write a function f(x1,x2,...,xn) as f x1 x2 ... xn. This expression is implicitly bracketed from the left, so we have
f x1 x2 ... xn = (((f x1) x2) ... xn)
Let T1, T2, ..., Tn be the types of the arguments of f and let T be the type of the return value. Then, rather than writing the type of f as (T1 x T2 x ... x Tn) -> T, we write
f :: T1 -> T2 -> ... -> Tn -> T
To be consistent with the implicit left bracketing of f x1 .. xn, we have to introduce brackets in the type expression from the right, as follows:
f :: T1 -> (T2 -> ... -> (Tn -> T))
This convention by which all functions are regarding as functions of a single argument is called currying, after the logician Haskell Curry, who has also lent his name to the Haskell language.11.1