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).