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(!)) [1].
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.
[1] http://hackage.haskell.org/package/utility-ht-0.0.11/docs/Data-List-HT.html#v:mapAdjacent
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.