module Data.List.Reverse.Private where

import qualified Data.List.Key.Private as Key
import Data.List.HT (segmentAfter, viewR, groupBy)

import Prelude hiding (dropWhile, takeWhile)


-- $setup
-- >>> import Test.Utility (forAllPredicates)
-- >>> import qualified Data.List.Reverse.StrictElement as Rev
-- >>> import Prelude hiding (dropWhile, takeWhile)


{- |
prop> forAllPredicates $ \p xs -> dropWhile p xs == Rev.dropWhile p xs
-}
dropWhile :: (a -> Bool) -> [a] -> [a]
dropWhile :: forall a. (a -> Bool) -> [a] -> [a]
dropWhile a -> Bool
p =
   forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a]
init forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [[a]]
segmentAfter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p)

{- |
prop> forAllPredicates $ \p xs -> takeWhile0 p xs == Rev.takeWhile p xs
-}
takeWhile0 :: (a -> Bool) -> [a] -> [a]
takeWhile0 :: forall a. (a -> Bool) -> [a] -> [a]
takeWhile0 a -> Bool
p =
   forall a. [a] -> a
last forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Bool) -> [a] -> [[a]]
segmentAfter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p)

{- |
Doesn't seem to be superior to the naive implementation.

prop> forAllPredicates $ \p xs -> takeWhile1 p xs == Rev.takeWhile p xs
-}
takeWhile1 :: (a -> Bool) -> [a] -> [a]
takeWhile1 :: forall a. (a -> Bool) -> [a] -> [a]
takeWhile1 a -> Bool
p =
   (\Maybe ([[(Bool, a)]], [(Bool, a)])
mx ->
      case Maybe ([[(Bool, a)]], [(Bool, a)])
mx of
         Just ([[(Bool, a)]]
_, xs :: [(Bool, a)]
xs@((Bool
True,a
_):[(Bool, a)]
_)) -> forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [(Bool, a)]
xs
         Maybe ([[(Bool, a)]], [(Bool, a)])
_ -> []) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
   forall a. [a] -> Maybe ([a], a)
viewR forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall key a b c.
(((key, a) -> (key, a) -> b) -> [(key, a)] -> c)
-> (key -> key -> b) -> (a -> key) -> [a] -> c
Key.aux forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy forall a. Eq a => a -> a -> Bool
(==) a -> Bool
p

{- |
However it is more inefficient,
because of repeatedly appending single elements. :-(

prop> forAllPredicates $ \p xs -> takeWhile2 p xs == Rev.takeWhile p xs
-}
takeWhile2 :: (a -> Bool) -> [a] -> [a]
takeWhile2 :: forall a. (a -> Bool) -> [a] -> [a]
takeWhile2 a -> Bool
p =
   forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\[a]
xs a
x -> if a -> Bool
p a
x then [a]
xsforall a. [a] -> [a] -> [a]
++[a
x] else []) []