{-|
Lazy Deque API lifted to a Reader monad, \"mtl\"-style.
-}
module Deque.Lazy.Reader
where

import Deque.Prelude hiding (tail, init, last, head, null, dropWhile, takeWhile, reverse)
import Deque.Lazy (Deque)
import qualified Deque.Lazy as Deque
import qualified Deque.Prelude as Prelude


{-|
\(\mathcal{O}(n)\).
Modify each element of the queue.
-}
map :: MonadReader (Deque a) m => (a -> b) -> m (Deque b)
map :: (a -> b) -> m (Deque b)
map a -> b
f = (Deque a -> Deque b) -> m (Deque b)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((a -> b) -> Deque a -> Deque b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f)

{-|
\(\mathcal{O}(n)\).
Add elements to the begginning.
-}
prepend :: MonadReader (Deque a) m => Deque a -> m (Deque a)
prepend :: Deque a -> m (Deque a)
prepend Deque a
deque = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (Deque a
deque Deque a -> Deque a -> Deque a
forall a. Semigroup a => a -> a -> a
<>)

{-|
\(\mathcal{O}(n)\).
Add elements to the ending.
-}
append :: MonadReader (Deque a) m => Deque a -> m (Deque a)
append :: Deque a -> m (Deque a)
append Deque a
deque = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (Deque a -> Deque a -> Deque a
forall a. Semigroup a => a -> a -> a
<> Deque a
deque)

{-|
\(\mathcal{O}(1)\).
Add element in the beginning.
-}
cons :: MonadReader (Deque a) m => a -> m (Deque a)
cons :: a -> m (Deque a)
cons a
a = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (a -> Deque a -> Deque a
forall a. a -> Deque a -> Deque a
Deque.cons a
a)

{-|
\(\mathcal{O}(1)\).
Add element in the ending.
-}
snoc :: MonadReader (Deque a) m => a -> m (Deque a)
snoc :: a -> m (Deque a)
snoc a
a = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (a -> Deque a -> Deque a
forall a. a -> Deque a -> Deque a
Deque.snoc a
a)

{-|
\(\mathcal{O}(1)\).
Reverse the deque.
-}
reverse :: MonadReader (Deque a) m => m (Deque a)
reverse :: m (Deque a)
reverse = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Deque a
forall a. Deque a -> Deque a
Deque.reverse

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Move the first element to the end.
-}
shiftLeft :: MonadReader (Deque a) m => m (Deque a)
shiftLeft :: m (Deque a)
shiftLeft = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Deque a
forall a. Deque a -> Deque a
Deque.shiftLeft

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Move the last element to the beginning.
-}
shiftRight :: MonadReader (Deque a) m => m (Deque a)
shiftRight :: m (Deque a)
shiftRight = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Deque a
forall a. Deque a -> Deque a
Deque.shiftRight

{-|
\(\mathcal{O}(n)\).
Leave only the elements satisfying the predicate.
-}
filter :: MonadReader (Deque a) m => (a -> Bool) -> m (Deque a)
filter :: (a -> Bool) -> m (Deque a)
filter a -> Bool
predicate = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((a -> Bool) -> Deque a -> Deque a
forall a. (a -> Bool) -> Deque a -> Deque a
Deque.filter a -> Bool
predicate)

{-|
\(\mathcal{O}(n)\).
Leave only the specified amount of first elements.
-}
take :: MonadReader (Deque a) m => Int -> m (Deque a)
take :: Int -> m (Deque a)
take = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((Deque a -> Deque a) -> m (Deque a))
-> (Int -> Deque a -> Deque a) -> Int -> m (Deque a)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> Deque a -> Deque a
forall a. Int -> Deque a -> Deque a
Deque.take

{-|
\(\mathcal{O}(n)\).
Drop the specified amount of first elements.
-}
drop :: MonadReader (Deque a) m => Int -> m (Deque a)
drop :: Int -> m (Deque a)
drop = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((Deque a -> Deque a) -> m (Deque a))
-> (Int -> Deque a -> Deque a) -> Int -> m (Deque a)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> Deque a -> Deque a
forall a. Int -> Deque a -> Deque a
Deque.drop

{-|
\(\mathcal{O}(n)\).
Leave only the first elements satisfying the predicate.
-}
takeWhile :: MonadReader (Deque a) m => (a -> Bool) -> m (Deque a)
takeWhile :: (a -> Bool) -> m (Deque a)
takeWhile a -> Bool
predicate = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((a -> Bool) -> Deque a -> Deque a
forall a. (a -> Bool) -> Deque a -> Deque a
Deque.takeWhile a -> Bool
predicate)

{-|
\(\mathcal{O}(n)\).
Drop the first elements satisfying the predicate.
-}
dropWhile :: MonadReader (Deque a) m => (a -> Bool) -> m (Deque a)
dropWhile :: (a -> Bool) -> m (Deque a)
dropWhile a -> Bool
predicate = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((a -> Bool) -> Deque a -> Deque a
forall a. (a -> Bool) -> Deque a -> Deque a
Deque.dropWhile a -> Bool
predicate)

{-|
\(\mathcal{O}(n)\).
Same as @(,) '<$>' `takeWhile` predicate '<*>' `dropWhile` predicate@.
-}
span :: MonadReader (Deque a) m => (a -> Bool) -> m (Deque a, Deque a)
span :: (a -> Bool) -> m (Deque a, Deque a)
span a -> Bool
predicate = (Deque a -> (Deque a, Deque a)) -> m (Deque a, Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader ((a -> Bool) -> Deque a -> (Deque a, Deque a)
forall a. (a -> Bool) -> Deque a -> (Deque a, Deque a)
Deque.span a -> Bool
predicate)

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Get the first element and deque without it if it's not empty.
-}
uncons :: MonadReader (Deque a) m => m (Maybe a, Deque a)
uncons :: m (Maybe a, Deque a)
uncons = (Deque a -> (Maybe a, Deque a)) -> m (Maybe a, Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (\ Deque a
deque -> case Deque a -> Maybe (a, Deque a)
forall a. Deque a -> Maybe (a, Deque a)
Deque.uncons Deque a
deque of
  Maybe (a, Deque a)
Nothing -> (Maybe a
forall a. Maybe a
Nothing, Deque a
deque)
  Just (a
a, Deque a
newDeque) -> (a -> Maybe a
forall a. a -> Maybe a
Just a
a, Deque a
newDeque))

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Get the last element and deque without it if it's not empty.
-}
unsnoc :: MonadReader (Deque a) m => m (Maybe a, Deque a)
unsnoc :: m (Maybe a, Deque a)
unsnoc = (Deque a -> (Maybe a, Deque a)) -> m (Maybe a, Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader (\ Deque a
deque -> case Deque a -> Maybe (a, Deque a)
forall a. Deque a -> Maybe (a, Deque a)
Deque.unsnoc Deque a
deque of
  Maybe (a, Deque a)
Nothing -> (Maybe a
forall a. Maybe a
Nothing, Deque a
deque)
  Just (a
a, Deque a
newDeque) -> (a -> Maybe a
forall a. a -> Maybe a
Just a
a, Deque a
newDeque))

{-|
\(\mathcal{O}(1)\). 
Check whether deque is empty.
-}
null :: MonadReader (Deque a) m => m Bool
null :: m Bool
null = (Deque a -> Bool) -> m Bool
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Bool
forall a. Deque a -> Bool
Deque.null

{-|
\(\mathcal{O}(1)\). 
Check whether deque is empty.
-}
length :: MonadReader (Deque a) m => m Int
length :: m Int
length = (Deque a -> Int) -> m Int
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
Prelude.length

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Get the first element if deque is not empty.
-}
head :: MonadReader (Deque a) m => m (Maybe a)
head :: m (Maybe a)
head = (Deque a -> Maybe a) -> m (Maybe a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Maybe a
forall a. Deque a -> Maybe a
Deque.head

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Get the last element if deque is not empty.
-}
last :: MonadReader (Deque a) m => m (Maybe a)
last :: m (Maybe a)
last = (Deque a -> Maybe a) -> m (Maybe a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Maybe a
forall a. Deque a -> Maybe a
Deque.last

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Keep all elements but the first one.
-}
tail :: MonadReader (Deque a) m => m (Deque a)
tail :: m (Deque a)
tail = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Deque a
forall a. Deque a -> Deque a
Deque.tail

{-|
\(\mathcal{O}(1)\), occasionally \(\mathcal{O}(n)\).
Keep all elements but the last one.
-}
init :: MonadReader (Deque a) m => m (Deque a)
init :: m (Deque a)
init = (Deque a -> Deque a) -> m (Deque a)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
reader Deque a -> Deque a
forall a. Deque a -> Deque a
Deque.init