-- | Like span, but with a predicate that compares two successive elements. The
-- span ends when the two successive elements do not satisfy the predicate.
rollingSpan :: (a -> a -> Bool) -> [a] -> ([a], [a])
rollingSpan _ xs@[] = (xs, xs)
rollingSpan _ xs@[_] = (xs, [])
rollingSpan p (x1:xs@(x2:_))
| p x1 x2 =
let (ys, zs) = rollingSpan p xs
in (x1 : ys, zs)
| otherwise = ([x1], xs)
-- | Like 'groupBy' but with a predicate that compares two successive elements.
-- A group ends when two successive elements do not satisfy the predicate.
rollingGroupBy :: (a -> a -> Bool) -> [a] -> [[a]]
rollingGroupBy _ [] = []
rollingGroupBy cmp xs =
let (ys, zs) = rollingSpan cmp xs
in ys : rollingGroupBy cmp zs
Are there any existing functions that serve this purpose or is there any simpler way to achieve such functionality? If not, where is the right place for these, if any. Can they be included in Data.List in base?