{- | Utility functions that operate on lists, but are not part of `Data.List`. -} module Data.List.Extra where import "base" Data.List qualified as L {- | Takes elements from a list while the predicate holds, considers up to @window@ elements since the last element that satisfied the predicate. >>> takeWhileAnyInWindow 3 Prelude.odd [1, 2, 3, 6, 8, 10, 12] [1,2,3] -} takeWhileAnyInWindow :: -- | Number of elements to consider since the last element that satisfied the predicate. Int -> -- | Function to test each element. (a -> Bool) -> -- | Input list [a] -> {- | List of elements that satisfied the predicate. Ends at an element that satisfies the predicate. -} [a] takeWhileAnyInWindow wdw predicate = go wdw [] where go 0 _ _ = [] go cnt acc (x : xs) | predicate x = L.reverse (x : acc) <> go wdw [] xs | otherwise = go (pred cnt) (x : acc) xs go _ _ _ = []