## Summary

- Locality of names
- Generalisation as a programming tactic, and generalisation in Haskell.

## Local Definitions

Haskell can support local definitions. I used this in the practical. It takes the form:

```
equation
where
local equations
```

You can also use `let`

, not sure what the difference is. Something about `let`

being expression level?

I used this to add an accumulator function to a function by having a `function/2`

and `function'/3`

where the added parameter is the accumulator. For example (taken from my week3.hs practical answers):

```
positions :: Eq a => [a] -> a -> [Int]
-- I think there's a neater way of doing this
positions [] _ = []
positions x y = positions' x y 1
where
positions' [] _ _ = []
positions' (x:xs) y n | x == y = n : positions' xs y (n+1)
positions' (x:xs) y n = positions' xs y (n+1)
```

Here’s an example we did in the lecture:

```
diff [] ys = []
diff (x:xs) ys = if xful ys then d else x : d
where
d = diff xs ys
xful [] = False
xful (y:ys) = if x == y then True else xful ys
```

I’ve made a mistake in my positions code; the variables don’t need to be passed on. So it could instead read:

```
positions :: Eq a => [a] -> a -> [Int]
positions [] _ = []
positions x y = positions' x 1
where
positions' [] _ = []
positions' (x:xs) n | x == y = n : positions' xs (n+1)
positions' (x:xs) n = positions' xs (n+1)
```

## Generalisations

Nothing ground breaking here. Generalise where possible as you can then reuse code. Also allows you to potentially do more clever things. Gave the example of producing a Fibonacci sequence purely based off how it works mathematically, which is a very poor performing way of doing it. Making a ‘generic sequence’ function allows you to have auxiliary arguments and so on (more flexibility).