# Functional Programming¶

Functional programming is a programming paradigm that aims to structure programs in a manner similar to their mathematical definitions. For example, recursion is generally preferred to looping, and variables are often immutable declarations rather than actual mutating values. Functions are first-class objects, meaning that functions can be passed to other functions as arguments.

As with all languages there are many variations of functional programming languages. We often talk about static versus dynamic, or strongly typed versus weakly typed programming languages; with functional programming languages, we often talk about purely functional versus impure and lazy versus eager languages.

Many languages support programming in a functional style. Python, for example, has fairly good support for functional style. However, We will focus on a lazy, purely functional programming language called Haskell.

## Eager languages¶

An eager language is one where expressions are evaluated fully when they are encountered. Almost all traditional languages are eager, including C, C++, Python, Java, or Matlab.

## Lazy languages¶

Lazy languages, on the other hand, do not fully evaluate an expression until it is required. This potentially allows for more efficient code because only expressions that are actually needed are evaluated. For example, consider the following Python code

```
def foo(a, b):
x = expensive(a)
y = other_expensive(b)
if a < b:
return x
else:
return y
```

and its direct Haskell equivalent

```
foo a b | a < b = x
| otherwise = y
where
x = expensive a
y = otherExpensive b
```

In the Python code we will evaluate both the `expensive`

and
`otherExpensive`

function, while in the Haskell code at most one
will evaluated. Note that we say ‘at most one’ because, depending on
what the code calling `foo`

actually does with the result, the
return value might never need to be fully evaluated!

This example might not be entirely convincing, since the Python code
can be easily refactored to avoid computing more than one of the
functions. However, there is another benefit of laziness, which is
that it allows us to deal with infinite data structures. Suppose that
we are looking for the first three square numbers to satisfy some
predicate `p`

(which we know exists). In Python, we might write

```
def search():
i = 1
els = []
while len(els) < 3:
if p(i * i):
els.append(i * i)
i += 1
return els
```

In Haskell, we can just write

```
search = take 3 (filter p (map (^ 2) [1..])
```

Although we have the expression `map (^ 2) [1..]`

which appears to
square the positive integers, we only evaluate that infinite list in a
lazy fashion. In particular, when `search`

is evaluated, `take`

asks for (up to) 3 elements. `filter`

then needs to start looking
through elements of the list, and so `map`

starts applying the
squaring operation to the elements.

Many non-functional languages have support for lazy evaluation. In fact, Python makes extensive use of lazy evaluation with its generators. The above code could be re-written as

```
def squares():
i = 1
while True:
yield i * i
i += 1
def search():
matches = filter(p, squares())
for i in range(3):
els.append(next(matches))
return els
```

which could operate in a similar fashion.

## Purely functional languages¶

A purely functional programming language is one in which there is no mutation. Variable declarations are in fact simply names assigned to some value which can be obtained by evaluating an expression (which in turn contains only pure expressions. Functions are functions in the mathematical sense, in that they map a set of inputs to a set of outputs, and do not perform any side effects.

An immediate consequence of this is that traditional looping
constructs are not possible, since the iterator variable in a
`for`

-loop or the conditional in a `while`

-loop cannot change. To
compute the the $itext{th}$ Fibonacci number in Python, we might
write

```
def fib(i):
a = 0
b = 1
j = 1
while j < i:
(a, b) = (b, a + b)
j += 1
return b
```

In Haskell, a direct translation of this code would be

```
fib i = fib' 1 0 1
where
fib' j a b | j < i = fib' (j + 1) b (a + b)
| otherwise = b
```

Note that no variables are ever mutated; rather, we simply recursively call functions with new arguments.

## Haskell¶

Haskell is a purely functional lazy programming language. One of it’s greatest strengths is it’s hierarchy of abstractions which allow us to succinctly express common ideas.

### Implicit Recursion¶

Explicit recursion is ugly and almost as error-prone as manipulating
indices directly. Consider defining the functions `sum'`

and
`product'`

that compute the cumulative sum and product of a list of
numbers, respectively. We could write

```
sum' [] = 0
sum' (x:xs) = x + sum' xs
product' [] = 1
product' (x:xs) = x * product' xs
```

But we’re really expressing a fold, which is a function used to reduce a list-like structure with a binary operation into some summary value. We can re-write the above code as

```
sum' xs = foldr (+) 0 xs
product' xs = foldr (*) 1 xs
```

The symmetry between these functions is (perhaps) more apparent with these definitions.

Another slightly more interesting example is in defining the (infinite) Fibonacci sequence, where we could write

```
fibonacci :: [Integer]
fibonacci = 1 : 1 : f 1 1
where
f a b = (a + b) : f b (a + b)
```

This definition follows naturally from the mathematical definition, but what we’re really doing is combining two sequences with a binary operation. The two sequences are the Fibonacci sequence itself and the tail of the Fibonacci sequence, where the tail of a list is everything but the head of the list, and the binary operation is addition. We can instead write

```
fibonacci :: [Integer]
fibonacci = 1 : 1 : zipWith (+) fibonacci (tail fibonacci)
```

Idiomatic Haskell code rarely relies on explicit recursion, instead relying on these higher order functions.

### Functors¶

The next generalization we consider are functors. Functors are data
structures that can be ‘mapped over’. For example, consider the
`Maybe`

data structure that represents an optional value.

```
data Maybe a = Just a
| Nothing
```

A `Maybe a`

value can either contain a value of type `a`

, or
nothing. If we have a `Maybe a`

value, it would be nice to be able
to apply functions from `a -> b`

to get a `Maybe b`

value, where
in the presence of a `Nothing`

value we do the natural thing and
return a `Nothing`

. To be concrete, suppose we have implemented each
of

```
coolFunction :: Int -> Double
readInt :: Maybe Integer
```

How can we combine these two functions to get a `Maybe Double`

? We
could write

```
case readInt of
Nothing -> Nothing
Just x -> Just (coolFunction x)
```

With functors, we can instead write

```
fmap coolFunction readInt
```

Some more examples follow.

```
>>> fmap (+ 1) (Just 1)
Just 2
>>> fmap (+ 1) Nothing
Nothing
>>> fmap ("Hello " ++) (Just "Patrick")
Just "Hello Patrick"
>>> fmap ("Hello " ++) Nothing
Nothing
```

Many data structures are functors.

```
>>> fmap (^ 2) [1, 2, 5]
[1, 4, 25]
>>> fmap (^ 2) []
[]
>>> fmap (* pi) ("Any type here", 2)
("Any type here", 6.283185307179586)
```

You can, of course, define functor instances for your data structures.

### Applicative¶

Applicative functors generalize functors. In particular, with functors
we were able to add a regular number to a `Maybe Int`

, but we can’t
(easily) add two `Maybe Int`

values to get a `Maybe Int`

value.

```
>>> (+) <$> Just 1 <*> Just 3
Just 4
>>> (+) <$> Just 1 <*> Nothing
Nothing
>>> (+) <$> Nothing <*> Just 3
Nothing
>>> (++) <$> Just "Hello " <*> Just "Patrick"
Just "Hello Patrick"
>>> (++) <$> Just "Hello " <*> Nothing
Nothing
```

This is quite powerful. Imagine you are trying to solve a linear
program described by the matrix \(A\) and vectors \(b\) and
\(c\) where \(A\), \(b\), and \(c\) are read in from a
user-provided file. Since the user might make a mistake in typing the
files, to read these files we have to return a `Maybe`

value to
represent the possibility of failure. We can only run our solver if
none of \(A\), \(b\), or \(c\) return `Nothing`

. To make
this concrete, suppose we have implemented each of

```
readA :: Maybe Matrix
readB :: Maybe Vector
readC :: Maybe Vector
simplex :: Matrix -> Vector -> Vector -> Solution
```

How can we chain these functions together to get a `Maybe Solution`

? If we
were to do this without applicative functors, we would need to write
something like

```
solve :: Maybe Solution
solve = case readA of
Nothing -> Nothing
Just a -> case readB of
Nothing -> Nothing
Just b -> case readC of
Nothing -> Nothing
Just c -> Just (simplex a b c)
```

This is extremely tedious. Instead, we can simply write

```
solve = simplex <$> readA <*> readB <*> readC
```

There are more exotic instances of the applicative typeclass. For example, lists implement the applicative typeclass by creating the Cartesian product of possible outputs.

```
>>> (*) <$> [1, 2, 3] <*> [1, 2, 3]
[1,2,3,2,4,6,3,6,9]
```

### Hypothesis testing¶

A great example of the power of Haskell is the QuickCheck library. The idea of this library is to write propositions that map an input to a boolean, where returning true indicates a successful test and returning false indicates a failed test. What differentiates this from standard unit testing is that we only specify the types of the input, and not the input itself. The library randomly generates many valid inputs and tests the propositions on each one, looking for a counter example.

Consider the following (incorrect) sorting algorithm.

```
badSort [] = []
badSort (x:xs) = badSort lt ++ [x] ++ badSort gt
where
lt = filter (< x) xs
gt = filter (> x) xs
```

We can find the error by defining

```
import Data.List
import Test.QuickCheck
testBadSort :: (Ord a) => [a] -> Bool
testBadSort xs = badSort xs == sort xs
```

which simply compares the output of our sorting algorithm to one which is (presumably) correct. We can then run

```
>>> quickCheck testBadSort
*** Failed! Falsifiable (after 5 tests and 1 shrink):
[(),()]
```

This tells us that it found a counter example to our proposition,
namely `[(), ()]`

, where `()`

is pronounced ‘unit’. It is a
singleton value that compares equal with itself. If we run our sort on
this input, we can see the problem.

```
>>> badSort [(), ()]
[()]
```

More generally, we can see

```
>>> badSort [1, 1, 1, 1]
[1]
```

The problem is our algorithm was assuming that elements were unique. The fix is simple:

```
goodSort [] = []
goodSort (x:xs) = goodSort lt ++ [x] ++ goodSort gt
where
lt = filter (<= x) xs
gt = filter (> x) xs
```