{-# language DeriveTraversable #-}
{-# language ScopedTypeVariables #-}
{-# language BangPatterns #-}
{-# language MagicHash #-}
{-# language UnboxedTuples #-}
{-# language PatternSynonyms #-}
{-# language ViewPatterns #-}
{-# language Trustworthy #-}
{-# language TypeFamilies #-}
{-# language FlexibleContexts #-}
{-# language LambdaCase #-}
module Data.CompactSequence.Deque.Simple.Internal
( Deque (.., Empty, (:<), (:>))
, (|>)
, (<|)
, empty
, cons
, snoc
, uncons
, unsnoc
, fromList
, fromListN
) where
import qualified Data.CompactSequence.Deque.Internal as D
import qualified Data.CompactSequence.Internal.Array as A
import qualified Data.CompactSequence.Internal.Size as Sz
import Data.CompactSequence.Internal.Size (Size)
import qualified Data.CompactSequence.Internal.Numbers as N
import qualified Data.Foldable as F
import qualified GHC.Exts as Exts
import Control.Monad.State.Strict
import qualified Prelude as P
import Prelude hiding (take)
newtype Deque a = Deque (D.Deque Sz.Sz1 a)
deriving (Functor, Traversable, Eq, Ord)
empty :: Deque a
empty = Deque D.empty
cons :: a -> Deque a -> Deque a
cons a (Deque q) = Deque $ D.consA Sz.one (A.singleton a) q
snoc :: Deque a -> a -> Deque a
snoc (Deque q) a = Deque $ D.snocA Sz.one q (A.singleton a)
(|>) :: Deque a -> a -> Deque a
(|>) = snoc
(<|) :: a -> Deque a -> Deque a
(<|) = cons
uncons :: Deque a -> Maybe (a, Deque a)
uncons (Deque q) = case D.viewLA Sz.one q of
D.EmptyL -> Nothing
D.ConsL sa q'
| (# a #) <- A.getSingleton# sa
-> Just (a, Deque q')
unsnoc :: Deque a -> Maybe (Deque a, a)
unsnoc (Deque q) = case D.viewRA Sz.one q of
D.EmptyR -> Nothing
D.SnocR q' ta
| (# a #) <- A.getSingleton# ta
-> Just (Deque q', a)
infixr 5 :<, `cons`
infixl 4 `snoc`, |>
pattern (:<) :: a -> Deque a -> Deque a
pattern x :< xs <- (uncons -> Just (x, xs))
where
x :< xs = x `cons` xs
pattern (:>) :: Deque a -> a -> Deque a
pattern xs :> x <- (unsnoc -> Just (xs, x))
where
xs :> x = xs `snoc` x
pattern Empty :: Deque a
pattern Empty = Deque D.Empty
{-# COMPLETE (:<), Empty #-}
{-# COMPLETE (:>), Empty #-}
instance Foldable Deque where
foldMap f (Deque q) = foldMap f q
foldr c n (Deque q) = foldr c n q
foldr' c n (Deque q) = F.foldr' c n q
foldl f b (Deque q) = foldl f b q
foldl' f b (Deque q) = F.foldl' f b q
null (Deque D.Empty) = True
null _ = False
length (Deque q) = go 0 Sz.one q
where
go :: Int -> Size m -> D.Deque m a -> Int
go !acc !_s D.Empty = acc
go !acc !s (D.Shallow _) = acc + Sz.getSize s
go !acc !s (D.Deep pr m sf) = go (acc + ld pr + ld sf) (Sz.twice s) m
where
ld = \case
D.One{} -> Sz.getSize s
D.Two{} -> 2*Sz.getSize s
D.Three{} -> 3*Sz.getSize s
D.Four{} -> 4*Sz.getSize s
instance Show a => Show (Deque a) where
showsPrec p xs = showParen (p > 10) $
showString "fromList " . shows (F.toList xs)
instance Exts.IsList (Deque a) where
type Item (Deque a) = a
toList = F.toList
fromList = fromList
fromListN = fromListN
instance Semigroup (Deque a) where
Empty <> q = q
q <> Empty = q
q <> r = fromListN (length q + length r) (F.toList q ++ F.toList r)
instance Monoid (Deque a) where
mempty = empty
fromList :: [a] -> Deque a
fromList = F.foldl' snoc empty
fromListN :: Int -> [a] -> Deque a
fromListN n xs
= Deque $ evalState (D.fromListNM Sz.one n) xs