Complementing Carsten's answer, sometimes in functional programming (or programming in general) you might want to divide the tasks you want to do into several subtasks. So here are 2 tasks:
- Pairing an element with its neighbour.
- Applying a function to a list of pairs.
For the first task, we can simply define a function pairing that does the followings (and also assuming you want to ignore empty list or singleton list):
pairing :: [a] -> [(a,a)]
pairing [] = []
pairing [x] = []
pairing (x:y:xs) = (x,y) : pairing xs
For example:
pairing [] == []
pairing [1] == []
pairing [1,2,3,4] == [(1,2),(3,4)]
pairing [1,2,3,4,5] == [(1,2),(3,4)]
Then for task 2, there is an operation in Haskell that applies a function to a list of elements called map (these functions that take a function as an argument are called higher-order functions):
For example:
f x = x^2
map f [0,1,2] == [0,1,4]
So we can now implement the function applyPairwise like this:
applyPairwise :: ((a,a) -> b) -> [a] -> [b]
applyPairwise f xs = map f (pairing xs)
Or even better using composition:
applyPairwise f = map f . pairing