{- |
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 _ _ _ = []