# haskell functions

Haskell is a pure functional language. This means functions in Haskell behave closer to mathematical functions. A function operates on the input parameters and returns a result. Functions do not modify state.

Here we will be introducing Haskell functions by examples presented in the following code snippet.

# simple functions and type inference

Let’s start with simple functions that accept a single input value and output a single result.

## half

**half x = x / 2**

This function takes a single value x and transforms it into a value that is half of the input. Note that we did not specify any types here. Haskell infers the types. A

command for the function reveals the following type signature.**:t**

`*HaskellFunctions> :t half`

**half :: Fractional a => a -> a**

Key points to note here are:

**half**

and outputs a value of type**a****a**- Haskell has inferred the type
**a****Fractional** - Since we did not explicitly specify a type for

, Haskell inferred the most general type that will support the function’s requirements.**a** - A

command on**:info**

reveals that it mandates support for**Fractional**

operator function. This selection was based on the use of the**(/)**

in the**/****half**

`*HaskellFunctions> :info Fractional`

class **Num a => Fractional** a where

** (/) :: a -> a -> a**

recip :: a -> a

fromRational :: Rational -> a

{-# MINIMAL fromRational, (recip | (/)) #-}

-- Defined in `GHC.Real'

instance Fractional Float -- Defined in `GHC.Float'

instance Fractional Double -- Defined in `GHC.Float'

## square

**square x = x * x**

**square**** **uses the ******* **operation. This results in an inferred type

.**Num**

**square :: Num a => a -> a**

`:i`

on `Num`

shows us that `Num`

requires the support of

.*****

`*HaskellFunctions> :i Num`

class **Num **a where

(+) :: a -> a -> a

(-) :: a -> a -> a

**(*) :: a -> a -> a**

negate :: a -> a

abs :: a -> a

signum :: a -> a

fromInteger :: Integer -> a

{-# MINIMAL (+), (*), abs, signum, fromInteger, (negate | (-)) #-}

-- Defined in `GHC.Num'

instance Num Word -- Defined in `GHC.Num'

instance Num Integer -- Defined in `GHC.Num'

instance Num Int -- Defined in `GHC.Num'

instance Num Float -- Defined in `GHC.Float'

instance Num Double -- Defined in `GHC.Float'

## areaCircle

**areaCircle radius = pi * square radius**

The **areaCircle**** **function invokes the **square**** **function we had just defined.

`*HaskellFunctions> :t areaCircle`

**areaCircle :: Floating a => a -> a**

Note that the inferred type class is now less general than **square**** **as the **areaCircle**** **uses the **pi**** **constant defined in **Floating**** **type class.

`*HaskellFunctions> :t pi`

**pi :: Floating a => a**

on **:i****Floating**** **shows that it extends the **Fractional**** **type class. So, some generality has been lost here.

`*HaskellFunctions> :i Floating`

class **Fractional a => Floating** a where

** pi :: a**

exp :: a -> a

log :: a -> a

sqrt :: a -> a

(**) :: a -> a -> a

logBase :: a -> a -> a

sin :: a -> a

cos :: a -> a

tan :: a -> a

asin :: a -> a

acos :: a -> a

atan :: a -> a

sinh :: a -> a

cosh :: a -> a

tanh :: a -> a

asinh :: a -> a

acosh :: a -> a

atanh :: a -> a

GHC.Float.log1p :: a -> a

GHC.Float.expm1 :: a -> a

GHC.Float.log1pexp :: a -> a

GHC.Float.log1mexp :: a -> a

{-# MINIMAL pi, exp, log, sin, cos, asin, acos, atan, sinh, cosh,

asinh, acosh, atanh #-}

-- Defined in `GHC.Float'

instance Floating Float -- Defined in `GHC.Float'

instance Floating Double -- Defined in `GHC.Float'

An important take away from the discussion above is that:

Haskell function definitions without explicit type specifications are as general as they possibly can be. Keeping functions as general as possible, promotes code reuse.

# multi-parameter functions and currying

We have seen single parameter functions. How does Haskell support multi-parameter functions?

In Haskell all functions take only one argument. Multi-argument functions are formed by cascading multiple function applications. This is best explained with an example.

## volumeCylinder

**volumeCylinder r h = areaCircle r * h**

The above function appears to take two arguments, radius (r) and height (h).

`*HaskellFunctions> :t volumeCylinder`

**volumeCylinder :: Floating a => a -> a -> a**

The signature of the function is shown above. The first two arrows represent the radius and height parameters. The third arrow represents the return value. This is further clarified below.

**volumeCylinder :: Floating a **

=> a -- ^ radius

-> a -- ^ height

-> a -- ^ volume

It appears that the **volumeCylinder**** **function takes two parameters. Haskell however treats the above declaration as a cascade of two function applications:

**volumeCylinder**- The second function takes the height as a parameter and returns the volume of the cylinder.

Strictly speaking, the **volumeCylinder**** **signature should be written as shown below.

**volumeCylinder :: Floating a => a -> (a -> a)**

Haskell implements functions this way to facilitate partial application. Partial application is explained by the **gauge10Volume**** **function that is formed by partially applying the parameters to the **volumeCylinder**** **function.

## guage10Volume

**gauge10Volume :: Floating a => a -> a**

gauge10Volume = volumeCylinder (2.58826 / 2)

Consider the above function that determines the volume of a gauge 10 cable of given length. The function’s body just consists of partial application of the **volumeCylinder**** **function with just the radius parameter. The **gauge10Volume**** **just takes the height parameter (length of the cable) and will return the volume of a gauge 10 cable.

# operations

Operations like +, * are also functions. The operations can be invoked in the conventional infix operation

or as a function **a+b**

.**(+) a b**

add1 = (+) 10 2 -- Add as a function

add2 = 10 + 2 -- Infix addmul1 = (*) 10 2 -- Multiply as a function

mul2 = 10 * 2 -- Infix multiplyfloatingDiv = 10 / 4 -- Haskell division returns Double

intDiv1 = div 10 4 -- div performs an integer division

intDiv2 = 10 `div` 4 -- infix version of div

You can learn more about the functions by issuing in the

command in GHCI. You can see the function signatures as well as operator precedence.**:i**

*HaskellFunctions> :i (+) (-) (*) (/)

class Num a where

(+) :: a -> a -> a

...

-- Defined in `GHC.Num'infixl 6 +class Num a where

...

(-) :: a -> a -> a

...

-- Defined in `GHC.Num'infixl 6 -

class Num a where

...

(*) :: a -> a -> a

...

-- Defined in `GHC.Num'infixl 7 *

class Num a => Fractional a where

(/) :: a -> a -> a

...

-- Defined in `GHC.Real'infixl 7 /

# recursive function defined using equations

Haskell supports parameter pattern matching in functions. You can specify multiple declarations of the same function with different parameter patterns. For example, the **factorial**** **function is shown below with two declarations:

specifies the factorial for the number 0**factorial 0**

defines the factorial for all integers other than 0.**factorial n**

**factorial :: Integral a => a -> a**

factorial 0 = 1

factorial n = n * factorial (n-1)

Also note the definition of

is recursively defined in terms of **factorial n**

. Recursion is a very common pattern in functional programming. We will see it being used for function definitions, data structure definition and loops.**factorial (n-1)**