{-# LANGUAGE CPP #-}
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
import qualified Deque.Prelude as Prelude
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
span :: (a -> Bool) -> Deque a -> (Deque a, Deque a)
span predicate (Deque consList snocList) = case StrictList.spanReversed predicate consList of
(consReversedPrefix, consSuffix) -> if Prelude.null consSuffix
then case StrictList.spanFromEnding predicate snocList of
(snocPrefix, snocSuffix) -> let
prefix = Deque (StrictList.prependReversed consReversedPrefix snocPrefix) StrictList.Nil
suffix = Deque snocSuffix StrictList.Nil
in (prefix, suffix)
else let
prefix = Deque StrictList.Nil consReversedPrefix
suffix = Deque consSuffix snocList
in (prefix, suffix)
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 consList1 snocList1) (Deque consList2 snocList2) = let
consList = consList1
snocList = snocList2 <> StrictList.prependReversed consList2 snocList1
in Deque consList snocList
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
(<*>) (Deque fnConsList fnSnocList) (Deque argConsList argSnocList) = let
snocList = let
fnStep resultSnocList fn = let
argStep resultSnocList arg = StrictList.Cons (fn arg) resultSnocList
in foldl' argStep (foldl' argStep resultSnocList argConsList) (StrictList.reverse argSnocList)
in foldl' fnStep (foldl' fnStep StrictList.Nil fnConsList) (StrictList.reverse fnSnocList)
in Deque StrictList.Nil snocList
instance Monad Deque where
return = pure
(>>=) (Deque aConsList aSnocList) k = let
snocList = let
aStep accBSnocList a = case k a of
Deque bConsList bSnocList -> StrictList.prependReversed bConsList (bSnocList <> accBSnocList)
in foldl' aStep (foldl' aStep StrictList.Nil aConsList) (StrictList.reverse aSnocList)
in Deque StrictList.Nil snocList
#if !(MIN_VERSION_base(4,13,0))
fail = const mempty
#endif
instance Alternative Deque where
empty = mempty
(<|>) = mappend
instance MonadPlus Deque where
mzero = empty
mplus = (<|>)
instance MonadFail Deque where
fail = const mempty