*We continue our exploration of the open source, advanced and purely functional programming language, Haskell. In the third article in the series, we will focus on more Haskell functions, conditional constructs and their usage.*

A function in Haskell has the function name followed by arguments. An infix operator function has operands on either side of it. A simple infix *add* operation is shown below:

*Main> 3 + 5 8

If you wish to convert an infix function to a prefix function, it must be enclosed within parentheses:

*Main> (+) 3 5 8

Similarly, if you wish to convert a prefix function into an infix function, you must enclose the function name within *backquotes(`)*. The* elem* function takes an element and a list, and returns true if the element is a member of the list:

*Main> 3 `elem` [1, 2, 3] True *Main> 4 `elem` [1, 2, 3] False

Functions can also be partially applied in Haskell. A function that subtracts* ten* from a given number can be defined as:

diffTen :: Integer -> Integer diffTen = (10 -)

Loading the file in GHCi and passing three as an argument yields:

*Main> diffTen 3 7

Haskell exhibits polymorphism. A type variable in a function is said to be polymorphic if it can take any type. Consider the last function that returns the last element in an array. Its type signature is:

*Main> :t last last :: [a] -> a

The a in the above snippet refers to a type variable and can represent any type. Thus, the last function can operate on a list of integers or characters (string):

*Main> last [1, 2, 3, 4, 5] 5 *Main> last "Hello, World" 'd'

You can use a* where* clause for local definitions inside a function, as shown in the following example, to compute the area of a circle:

areaOfCircle :: Float -> Float areaOfCircle radius = pi * radius * radius where pi = 3.1415

Loading it in GHCi and computing the area for radius 1 gives:

*Main> areaOfCircle 1 3.1415

You can also use the* let* expression with the* in* statement to compute the area of a circle:

areaOfCircle :: Float -> Float areaOfCircle radius = let pi = 3.1415 in pi * radius * radius

Executing the above with input radius 1 gives:

*Main> areaOfCircle 1 3.1415

Indentation is very important in Haskell as it helps in code readability the compiler will emit errors otherwise. You must make use of white spaces instead of tab when aligning code. If the* let* and* in* constructs in a function span multiple lines, they must be aligned vertically as shown below:

compute :: Integer -> Integer -> Integer compute x y = let a = x + 1 b = y + 2 in a * b

Loading the example with GHCi, you get the following output:

*Main> compute 1 2 8

Similarly, the* if* and *else* constructs must be neatly aligned. The* else* statement is mandatory in Haskell. For example:

sign :: Integer -> String sign x = if x > 0 then "Positive" else if x < 0 then "Negative" else "Zero"

Running the example with GHCi, you get:

*Main> sign 0 "Zero" *Main> sign 1 "Positive" *Main> sign (-1) "Negative"

The case construct can be used for pattern matching against possible expression values. It needs to be combined with the *of* keyword. The different values need to be aligned and the resulting action must be specified after the -> symbol for each case. For example:

sign :: Integer -> String sign x = case compare x 0 of LT -> "Negative" GT -> "Positive" EQ -> "Zero"

The compare function compares two arguments and returns *LT* if the first argument is lesser than the second, *GT* if the first argument is greater than the second, and* EQ* if both are equal. Executing the above example, you get:

*Main> sign 2 "Positive" *Main> sign 0 "Zero" *Main> sign (-2) "Negative"

The* sign* function can also be expressed using guards (|) for readability. The action for a matching case must be specified after the = sign. You can use a default guard with the *otherwise* keyword:

sign :: Integer -> String sign x | x > 0 = "Positive" | x < 0 = "Negative" | otherwise = "Zero"

The guards have to be neatly aligned:

*Main> sign 0 "Zero" *Main> sign 3 "Positive" *Main> sign (-3) "Negative"

There are three very important higher order functions in Haskell *map, filter* and* fold.*

The *map* function takes a function and a list, and applies the function to each and every element of the list. Its type signature is:

*Main> :t map map :: (a -> b) -> [a] -> [b]

The first function argument accepts an element of type a and returns an element of type b. An example of adding two to every element in a list can be implemented using* map:*

*Main> map (+ 2) [1, 2, 3, 4, 5]

[3,4,5,6,7]

The* filter* function accepts a *predicate* function for evaluation, and a list, and returns the list with those elements that satisfy the *predicate.* For example:

*Main> filter (> 0) [-2, -1, 0, 1, 2] [1,2]

Its type signature is:

filter :: (a -> Bool) -> [a] -> [a]

The *predicate* function for filter takes as its first argument an element of type a and returns *True* or *False.*

The *fold* function performs a cumulative operation on a list. It takes as arguments a function, an accumulator (starting with an initial value) and a list. It cumulatively aggregates the computation of the function on the accumulator value as well as each member of the list. There are two types of *folds left* and *right fold*.

*Main> foldl (+) 0 [1, 2, 3, 4, 5] 15 *Main> foldr (+) 0 [1, 2, 3, 4, 5] 15

Their type signatures are, respectively:

*Main> :t foldl foldl :: (a -> b -> a) -> a -> [b] -> a *Main> :t foldr foldr :: (a -> b -> b) -> b -> [a] -> b

The way the *fold* is evaluated among the two types is different and is demonstrated below:

*Main> foldl (+) 0 [1, 2, 3] 6 *Main> foldl (+) 1 [2, 3] 6 *Main> foldl (+) 3 [3] 6

It can be represented as* f (f (f a b1) b2) b3* where* f* is the function, *a* is the accumulator value, and* b1, b2* and *b3* are the elements of the list. The parenthesis is accumulated on the left for a *left fold.* The computation looks like this:

*Main> (+) ((+) ((+) 0 1) 2) 3 6 *Main> (+) 0 1 1 *Main> (+) ((+) 0 1) 2 3 *Main> (+) ((+) ((+) 0 1) 2) 3 6

With the recursion, the expression is constructed and evaluated only when it is finally formed. It can thus cause stack overflow or never complete when working with infinite lists. The *foldr* evaluation looks like this:

*Main> foldr (+) 0 [1, 2, 3] 6 *Main> foldr (+) 0 [1, 2] + 3 6 *Main> foldr (+) 0 [1] + 2 + 3 6

It can be represented as* f b1 (f b2 (f b3 a))* where* f* is the function*, a* is the accumulator value, and *b1, b2* and *b3* are the elements of the list. The computation looks like this:

*Main> (+) 1 ((+) 2 ((+) 3 0)) 6 *Main> (+) 3 0 3 *Main> (+) 2 ((+) 3 0) 5 *Main> (+) 1 ((+) 2 ((+) 3 0)) 6

There are some statements like condition checking where *f b1* can be computed even without requiring the subsequent arguments, and hence the* foldr* function can work with infinite lists. There is also a strict version of *foldl (foldl*) that forces the computation before proceeding with the recursion.

If you want a reference to a matched pattern, you can use the as pattern syntax. The tail function accepts an input list and returns everything except the head of the list. You can write a *tailString* function that accepts a string as input and returns the string with the first character removed:

tailString :: String -> String tailString "" = "" tailString [email protected](x:xs) = "Tail of " ++ input ++ " is " ++ xs

The entire matched pattern is represented by* input* in the above code snippet.

Functions can be chained to create other functions. This is called composing functions. The mathematical definition is as under:

(f o g)(x) = f(g(x))

This dot (.) operator has the highest precedence and is left-associative. If you want to force an evaluation, you can use the function application operator ($) that has the second highest precedence and is right-associative. For example:

*Main> (reverse ((++) "yrruC " (unwords ["skoorB", "lleksaH"]))) "Haskell Brooks Curry"

You can rewrite the above using the function application operator that is right-associative:

Prelude> reverse $ (++) "yrruC " $ unwords ["skoorB", "lleksaH"] "Haskell Brooks Curry"

You can also use the dot notation to make it even more readable, but the final argument needs to be evaluated first; hence, you need to use the function application operator for it:

*Main> reverse . (++) "yrruC " . unwords $ ["skoorB", "lleksaH"] "Haskell Brooks Curry"

## Connect With Us