
#11815: Data.List: Add a function to get consecutive elements (mapConsecutives) -------------------------------------+------------------------------------- Reporter: holmisen | Owner: Type: feature request | Status: new Priority: low | Milestone: Component: libraries/base | Version: Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by holmisen: @@ -24,0 +24,38 @@ + + ---- + + 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. New description: 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. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11815#comment:14 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler