module Deque.Strict.Defs
where
import Control.Monad (fail)
import Deque.Prelude hiding (tail, init, last, head, null, dropWhile, takeWhile, reverse, filter, take)
import qualified StrictList
data Deque a = Deque !(StrictList.List a) !(StrictList.List a)
fromConsAndSnocLists :: [a] -> [a] -> Deque a
fromConsAndSnocLists consList snocList = Deque (fromList consList) (fromList snocList)
cons :: a -> Deque a -> Deque a
cons a (Deque consList snocList) = Deque (StrictList.Cons a consList) snocList
snoc :: a -> Deque a -> Deque a
snoc a (Deque consList snocList) = Deque consList (StrictList.Cons a snocList)
reverse :: Deque a -> Deque a
reverse (Deque consList snocList) = Deque snocList consList
shiftLeft :: Deque a -> Deque a
shiftLeft deque = maybe deque (uncurry snoc) (uncons deque)
shiftRight :: Deque a -> Deque a
shiftRight deque = maybe deque (uncurry cons) (unsnoc deque)
filter :: (a -> Bool) -> Deque a -> Deque a
filter predicate (Deque consList snocList) = let
newConsList = StrictList.prependReversed
(StrictList.filterReversed predicate consList)
(StrictList.filterReversed predicate snocList)
in Deque newConsList StrictList.Nil
take :: Int -> Deque a -> Deque a
take amount (Deque consList snocList) = let
newSnocList = let
buildFromConsList amount !list = if amount > 0
then \ case
StrictList.Cons head tail -> buildFromConsList (pred amount) (StrictList.Cons head list) tail
_ -> buildFromSnocList amount list (StrictList.reverse snocList)
else const list
buildFromSnocList amount !list = if amount > 0
then \ case
StrictList.Cons head tail -> buildFromSnocList (pred amount) (StrictList.Cons head list) tail
_ -> list
else const list
in buildFromConsList amount StrictList.Nil consList
in Deque StrictList.Nil newSnocList
drop :: Int -> Deque a -> Deque a
drop amount (Deque consList snocList) = let
buildFromConsList amount = if amount > 0
then \ case
StrictList.Cons _ tail -> buildFromConsList (pred amount) tail
_ -> buildFromSnocList amount (StrictList.reverse snocList)
else \ tail -> Deque tail snocList
buildFromSnocList amount = if amount > 0
then \ case
StrictList.Cons _ tail -> buildFromSnocList (pred amount) tail
_ -> Deque StrictList.Nil StrictList.Nil
else \ tail -> Deque tail StrictList.Nil
in buildFromConsList amount consList
takeWhile :: (a -> Bool) -> Deque a -> Deque a
takeWhile predicate (Deque consList snocList) = let
newConsList = foldr
(\ a nextState -> if predicate a
then StrictList.Cons a nextState
else StrictList.Nil)
(StrictList.takeWhileFromEnding predicate snocList)
consList
in Deque newConsList StrictList.Nil
dropWhile :: (a -> Bool) -> Deque a -> Deque a
dropWhile predicate (Deque consList snocList) = let
newConsList = StrictList.dropWhile predicate consList
in case newConsList of
StrictList.Nil -> Deque (StrictList.dropWhileFromEnding predicate snocList) StrictList.Nil
_ -> Deque newConsList snocList
uncons :: Deque a -> Maybe (a, Deque a)
uncons (Deque consList snocList) = case consList of
StrictList.Cons head tail -> Just (head, Deque tail snocList)
_ -> case StrictList.reverse snocList of
StrictList.Cons head tail -> Just (head, Deque tail StrictList.Nil)
_ -> Nothing
unsnoc :: Deque a -> Maybe (a, Deque a)
unsnoc (Deque consList snocList) = case snocList of
StrictList.Cons head tail -> Just (head, Deque consList tail)
_ -> case StrictList.reverse consList of
StrictList.Cons head tail -> Just (head, Deque StrictList.Nil tail)
_ -> Nothing
null :: Deque a -> Bool
null = \ case
Deque StrictList.Nil StrictList.Nil -> True
_ -> False
head :: Deque a -> Maybe a
head (Deque consList snocList) = case consList of
StrictList.Cons head _ -> Just head
_ -> StrictList.last snocList
last :: Deque a -> Maybe a
last (Deque consList snocList) = case snocList of
StrictList.Cons head _ -> Just head
_ -> StrictList.last consList
tail :: Deque a -> Deque a
tail (Deque consList snocList) = case consList of
StrictList.Nil -> Deque (StrictList.initReversed snocList) StrictList.Nil
_ -> Deque (StrictList.tail consList) snocList
init :: Deque a -> Deque a
init (Deque consList snocList) = case snocList of
StrictList.Nil -> Deque StrictList.Nil (StrictList.initReversed consList)
_ -> Deque consList (StrictList.tail snocList)
instance Eq a => Eq (Deque a) where
(==) a b = toList a == toList b
instance Show a => Show (Deque a) where
show = show . toList
instance IsList (Deque a) where
type Item (Deque a) = a
fromList list = Deque StrictList.Nil (StrictList.fromListReversed list)
toList (Deque consList snocList) = foldr (:) (toList (StrictList.reverse snocList)) consList
instance Semigroup (Deque a) where
(<>) (Deque snocList1 consList1) (Deque snocList2 consList2) = let
consList3 = consList1 <> StrictList.prependReversed snocList1 consList2
snocList3 = snocList2
in Deque consList3 snocList3
instance Monoid (Deque a) where
mempty = Deque StrictList.Nil StrictList.Nil
mappend = (<>)
deriving instance Functor Deque
instance Foldable Deque where
foldr step init (Deque consList snocList) = foldr step (foldr step init (StrictList.reverse snocList)) consList
foldl' step init (Deque consList snocList) = foldl' step (foldl' step init consList) (StrictList.reverse snocList)
instance Traversable Deque where
traverse f (Deque cs ss) =
(\cs' ss' -> Deque cs' (StrictList.reverse ss')) <$> traverse f cs <*> traverse f (StrictList.reverse ss)
instance Applicative Deque where
pure a = Deque (pure a) StrictList.Nil
fs <*> as = fromList (toList fs <*> toList as)
instance Monad Deque where
return = pure
m >>= f = fromList (toList m >>= toList . f)
fail = const mempty
instance Alternative Deque where
empty = mempty
(<|>) = mappend
instance MonadPlus Deque where
mzero = empty
mplus = (<|>)
instance MonadFail Deque where
fail = const mempty