module Data.BAByNF.Util.List
    ( drainOnce
    , drainIf
    , drainWhile
    , lsplitWhenNot
    , rsplitWhenNot
    , lstrip
    , rstrip
    , lrsplitWhenNot
    ) where

drainOnce :: [a] -> [a] -> ([a], [a])
drainOnce :: forall a. [a] -> [a] -> ([a], [a])
drainOnce [a]
from [a]
to =
    case [a]
from of
        [] -> ([a]
from, [a]
to)
        a
x:[a]
xs -> ([a]
xs, a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
to)

drainIf :: [a] -> [a] -> (a -> Bool) -> Maybe ([a], [a])
drainIf :: forall a. [a] -> [a] -> (a -> Bool) -> Maybe ([a], [a])
drainIf [a]
from [a]
to a -> Bool
cond = 
    case [a]
from of
        [] -> Maybe ([a], [a])
forall a. Maybe a
Nothing
        a
x:[a]
xs -> 
            if a -> Bool
cond a
x 
                then ([a], [a]) -> Maybe ([a], [a])
forall a. a -> Maybe a
Just ([a]
xs, a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
to)
                else Maybe ([a], [a])
forall a. Maybe a
Nothing

drainWhile :: [a] -> [a] -> (a -> Bool) -> ([a], [a])
drainWhile :: forall a. [a] -> [a] -> (a -> Bool) -> ([a], [a])
drainWhile [a]
from [a]
to a -> Bool
cond =
    case [a] -> [a] -> (a -> Bool) -> Maybe ([a], [a])
forall a. [a] -> [a] -> (a -> Bool) -> Maybe ([a], [a])
drainIf [a]
from [a]
to a -> Bool
cond of
        Just ([a]
from', [a]
to') -> [a] -> [a] -> (a -> Bool) -> ([a], [a])
forall a. [a] -> [a] -> (a -> Bool) -> ([a], [a])
drainWhile [a]
from' [a]
to' a -> Bool
cond
        Maybe ([a], [a])
Nothing -> ([a]
from, [a]
to)

lsplitWhenNot :: [a] -> (a -> Bool) -> ([a], [a])
lsplitWhenNot :: forall a. [a] -> (a -> Bool) -> ([a], [a])
lsplitWhenNot [a]
l a -> Bool
matches =
    case [a]
l of 
        [] -> ([], []) 
        (a
focus:[a]
rest) ->
            if a -> Bool
matches a
focus
                then let ([a]
prefixTail, [a]
suffix) = [a] -> (a -> Bool) -> ([a], [a])
forall a. [a] -> (a -> Bool) -> ([a], [a])
lsplitWhenNot [a]
rest a -> Bool
matches
                    in (a
focusa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
prefixTail, [a]
suffix)
            else ([], [a]
l)

rsplitWhenNot :: [a] -> (a -> Bool) -> ([a], [a])
rsplitWhenNot :: forall a. [a] -> (a -> Bool) -> ([a], [a])
rsplitWhenNot [a]
l a -> Bool
matches = (a -> ([a], [a]) -> ([a], [a])) -> ([a], [a]) -> [a] -> ([a], [a])
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> ([a], [a]) -> ([a], [a])
fn ([], []) [a]
l 
    where fn :: a -> ([a], [a]) -> ([a], [a])
fn a
x ([a], [a])
acc = case ([a], [a])
acc of
            ([], [a]
back) | a -> Bool
matches a
x -> ([], a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
back)  
                       | Bool
otherwise -> ([a
x], [a]
back)
            ([a]
front, [a]
back) -> (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
front, [a]
back)
rstrip :: [a] -> (a -> Bool) -> [a]
rstrip :: forall a. [a] -> (a -> Bool) -> [a]
rstrip [a]
l a -> Bool
matches = (a -> [a] -> [a]) -> [a] -> [a] -> [a]
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> [a] -> [a]
fn [] [a]
l
    where fn :: a -> [a] -> [a]
fn a
x [a]
acc = case [a]
acc of
            [] | a -> Bool
matches a
x -> []
               | Bool
otherwise -> [a
x]
            [a]
_ -> a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
acc

lstrip :: [a] -> (a -> Bool) -> [a]
lstrip :: forall a. [a] -> (a -> Bool) -> [a]
lstrip [a]
l a -> Bool
matches = case [a]
l of
    [] -> []
    a
x:[a]
xs | a -> Bool
matches a
x -> [a] -> (a -> Bool) -> [a]
forall a. [a] -> (a -> Bool) -> [a]
lstrip [a]
xs a -> Bool
matches
         | Bool
otherwise -> [a]
l

lrsplitWhenNot :: Show a => [a] -> (a -> Bool) -> ([a], [a], [a])
lrsplitWhenNot :: forall a. Show a => [a] -> (a -> Bool) -> ([a], [a], [a])
lrsplitWhenNot [a]
x a -> Bool
matches =
    let ([a]
l, [a]
x') = [a] -> (a -> Bool) -> ([a], [a])
forall a. [a] -> (a -> Bool) -> ([a], [a])
lsplitWhenNot [a]
x a -> Bool
matches
        ([a]
m, [a]
r) = [a] -> (a -> Bool) -> ([a], [a])
forall a. [a] -> (a -> Bool) -> ([a], [a])
rsplitWhenNot [a]
x' a -> Bool
matches
     in ([a]
l, [a]
m, [a]
r)