More on functions (Solutions)

## Contents

Here are several nice features that make using functions easier.

## let and where revisited

As discussed in earlier chapters, `let` and `where` are useful in local function definitions. Here, `sumStr` calls `addStr` function:

```addStr :: Float -> String -> Float

sumStr :: [String] -> Float
```

But what if we never need `addStr` anywhere else? Then we could rewrite `sumStr` using local bindings. We can do that either with a let binding...

```sumStr =
```

... or with a `where` clause...

```sumStr = foldl addStr 0.0
```

... and the difference appears to be just a question of style: Do we prefer the bindings to come before or after the rest of the definition?

However, there is another important difference between `let` and `where`. The let...in construct is an expression just like if/then/else. In contrast, `where` clauses are like guards and so are not expressions. Thus, `let` bindings can be used within complex expressions:

```f x =
if x > 0
then (let lsq = (log x) ^ 2 in tan lsq) * sin x
else 0
```

The expression within the outer parentheses is self-contained, and evaluates to the tangent of the square of the logarithm of `x`. Note that the scope of `lsq` does not extend beyond the parentheses; so changing the then-branch to

```        then (let lsq = (log x) ^ 2 in tan lsq) * (sin x + lsq)
```

does not work without dropping the parentheses around the `let`.

Despite not being full expressions, `where` clauses can be incorporated into `case` expressions:

```describeColour c =
"This colour "
++ case c of
Black -> "is black"
White -> "is white"
RGB red green blue -> " has an average of the components of " ++ show av
where av = (red + green + blue) `div` 3
++ ", yeah?"
```

In this example, the indentation of the where clause sets the scope of the av variable so that it only exists as far as the RGB red green blue case is concerned. Placing it at the same indentation of the cases would make it available for all cases. Here is an example with guards:

```doStuff :: Int -> String
doStuff x
| x < 3     = report "less than three"
| otherwise = report "normal"
where
report y = "the input is " ++ y
```

Note that since there is one equals sign for each guard there is no place we could put a `let` expression which would be in scope of all guards in the manner of the `where` clause. So this is a situation in which `where` is particularly convenient.

## Anonymous Functions - lambdas

Why create a formal name for a function like `addStr` when it only exists within another function's definition, never to be used again? Instead, we can make it an anonymous function also known as a `lambda function`. Then, `sumStr` could be defined like this:

```sumStr = foldl (\ x str -> x + read str) 0.0
```

The expression in the parentheses is a lambda function. The backslash is used as the nearest ASCII equivalent to the Greek letter lambda (λ). This lambda function takes two arguments, `x` and `str`, and it evaluates to "x + read str". So, the `sumStr` presented just above is precisely the same as the one that used `addStr` in a let binding.

Lambdas are handy for writing one-off functions to be used with maps, folds and their siblings, especially where the function in question is simple (beware of cramming complicated expressions in a lambda — it can hurt readability).

Since variables are being bound in a lambda expression (to the arguments, just like in a regular function definition), pattern matching can be used in them as well. A trivial example would be redefining `tail` with a lambda:

```tail' = (\ (_:xs) -> xs)
```

Note: Since lambdas are a special character in Haskell, the `\` on its own will be treated as the function and whatever non-space character is next will be the variable for the first argument. It is still good form to put a space between the lambda and the argument as in normal function syntax (especially to make things clearer when a lambda takes more than one argument).

## Operators

In Haskell, any function that takes two arguments and has a name consisting entirely of non-alphanumeric characters is considered an operator. The most common examples are the arithmetical ones like addition (+) and subtraction (-). Unlike other functions, operators are normally used infix (written between the two arguments). All operators can also be surrounded with parentheses and then used prefix like other functions:

```-- these are the same:
2 + 4
(+) 2 4
```

We can define new operators in the usual way as other functions — just don't use any alphanumeric characters in their names. For example, here's the set-difference definition from `Data.List`:

```(\\) :: (Eq a) => [a] -> [a] -> [a]
xs \\ ys = foldl (\zs y -> delete y zs) xs ys
```

As the example above shows, operators can be defined infix as well. The same definition written as prefix also works:

```(\\) xs ys = foldl (\zs y -> delete y zs) xs ys
```

Note that the type declarations for operators have no infix version and must be written with the parentheses.

### Sections

Sections are a nifty piece of syntactical sugar that can be used with operators. An operator within parentheses and flanked by one of its arguments...

```(2+) 4
(+4) 2
```

... is a new function in its own right. `(2+)`, for instance, has the type `(Num a) => a -> a`. We can pass sections to other functions, e.g. `map (+2) [1..4] == [3..6]`. For another example, we can add an extra flourish to the `multiplyList` function we wrote back in More about lists:

```multiplyList :: Integer -> [Integer] -> [Integer]
multiplyList m = map (m*)
```

If you have a "normal" prefix function and want to use it as an operator, simply surround it with backticks:

```1 `elem` [1..4]
```

This is called making the function infix. It's normally done for readability purposes: `1 `elem` [1..4]` reads better than `elem 1 [1..4]`. You can also define functions infix:

```elem :: (Eq a) => a -> [a] -> Bool
x `elem` xs = any (==x) xs
```

But once again notice that the type signature stays with the prefix style.

Sections even work with infix functions:

```(1 `elem`) [1..4]
(`elem` [1..4]) 1
```

Of course, remember that you can only make binary functions (that is, those that take two arguments) infix.

Exercises
• Lambdas are a nice way to avoid defining unnecessary separate functions. Convert the following let- or where-bindings to lambdas:
• `map f xs where f x = x * 2 + 3`
• `let f x y = read x + y in foldr f 1 xs`
• Sections are just syntactic sugar for lambda operations. I.e. `(+2)` is equivalent to `\x -> x + 2`. What would the following sections 'desugar' to? What would be their types?
• `(4+)`
• `(1 `elem`)`
• `(`notElem` "abc")`
 More on functions Solutions to exercises Elementary Haskell edit this chapter Haskell edit book structure