next up previous contents
Next: Defining functions in Haskell Up: Functional programming in Haskell Previous: Functional programming in Haskell   Contents

Types

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 $k$-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 $n$ arguments would have type (T1 x T2 x ... x Tn) -> T where Ti is the type of argument $i$ 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 $n$-argument function, the return value after consuming the first argument is a function of $n{-1}$ 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 $n$ 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


next up previous contents
Next: Defining functions in Haskell Up: Functional programming in Haskell Previous: Functional programming in Haskell   Contents
Madhavan Mukund 2004-04-29