An alternative definition for Data.List.groupBy
Publish date: Feb 10, 2010
Last updated: Jan 2, 2025
Last updated: Jan 2, 2025
The function
groupBy from haskell’s standard library is defined in terms
of span, the effect being that the supplied predicate function is used to
compare the first element of a group with successive elements.
This isn’t clear from the docs, and you might try to do this and wonder at the output you got:
*Main> groupBy (< =) [3,4,5,3,2,1,4,4,1,1,2,3,4,5,4,5,6,7]
[[3,4,5,3],[2],[1,4,4,1,1,2,3,4,5,4,5,6,7]]
We can redefine groupBy as follows, so that the supplied predicate function
compares adjacent elements one-by-one and returns True if they should be
grouped together:
groupBy' :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy' c [] = []
groupBy' c (a:as) = (a:ys) : groupBy' c zs
where (ys,zs) = spanC a as
spanC _ [] = ([], [])
spanC a' (x:xs)
| a' `c` x = let (ps,qs) = spanC x xs
in (x:ps,qs)
| otherwise = ([], x:xs)
Now we can use the groupBy function to return a list of ascending lists,
like we (probably) wanted:
*Main> groupBy' (< =) [3,4,5,3,2,1,4,4,1,1,2,3,4,5,4,5,6,7]
[[3,4,5],[3],[2],[1,4,4],[1,1,2,3,4,5],[4,5,6,7]]
The functionality is of course the same for groupBy (==).