Data.List: Add a function to get consecutive elements (mapConsecutives)
A recurring pattern is to get a list of all consecutive elements of a list, for further processing.
I propose adding the following function to
Data.List for this:
mapConsecutives :: (a -> a -> b) -> [a] -> [b] mapConsecutives _  =  mapConsecutives f xs = zipWith f xs (tail xs)
Since it requires pattern matching, to separate the empty case, it is not practical to inline at each use site.
Sidenote: A similar function
mapAdjacent is available in the
utility-ht library (with a partial implementation(!)) .
I realise that
Data.List is often imported unqualified and hence additions may cause trouble. I would have raised this on the libraries mailing list first, but the guidelines for proposals pointed me here.
UPDATE FROM DISCUSSION:
The modified proposal is to add the following two functions:
zipConsecutives :: [a] -> [(a,a)] zipConsecutives xs = zip xs (tail xs) zipConsecutivesWith :: (a -> a -> b) -> [a] -> [b] zipConsecutivesWith f xs = zipWith f xs (tail xs)
with possibly more efficient implementations. The first would mainly be for consistency with the other zip functions.
(Maybe we could abbreviate "Consecutives" into "Consecs".)
Some use cases that immediately comes to mind:
-- diff consecutive elements: diffs = zipConsecutivesWith (flip (-)) -- determine if list is ascending (similar for descending and strict): isAscending = and . zipConsecutivesWith (<=) -- an old friend of ours: fibs = 1 : 1 : zipConsecutivesWith (+) fibs -- get the edges of a closed path defined by points (ps): edges ps = zipConsecutivesWith makeEdge (ps ++ take 1 ps)
The last one is from a real world case where a polygon (represented as points) was to be translated to a list of corresponding edges.