content: {-# LANGUAGE StandaloneDeriving, DeriveGeneric, CPP #-}
  module GHC.Data.SizedSeq
    ( SizedSeq(..)
    , emptySS
    , addToSS
    , addListToSS
    , ssElts
    , sizeSS
    ) where
  
  import Prelude -- See note [Why do we import Prelude here?]
  import Control.DeepSeq
  import Data.Binary
  import GHC.Generics
  
  #if ! MIN_VERSION_base(4,20,0)
  import Data.List (foldl')
  #endif
  
  data SizedSeq a = SizedSeq {-# UNPACK #-} !Word [a]
    deriving (Generic, Show)
  
  instance Functor SizedSeq where
    fmap f (SizedSeq sz l) = SizedSeq sz (fmap f l)
  
  instance Foldable SizedSeq where
    foldr f c ss = foldr f c (ssElts ss)
  
  instance Traversable SizedSeq where
    traverse f (SizedSeq sz l) = SizedSeq sz . reverse <$> traverse f (reverse l)
  
  instance Binary a => Binary (SizedSeq a)
  
  instance NFData a => NFData (SizedSeq a) where
    rnf (SizedSeq _ xs) = rnf xs
  
  emptySS :: SizedSeq a
  emptySS = SizedSeq 0 []
  
  addToSS :: SizedSeq a -> a -> SizedSeq a
  addToSS (SizedSeq n r_xs) x = SizedSeq (n+1) (x:r_xs)
  
  -- NB, important this is eta-expand so that foldl' is inlined.
  addListToSS :: SizedSeq a -> [a] -> SizedSeq a
  addListToSS s xs = foldl' addToSS s xs
  
  ssElts :: SizedSeq a -> [a]
  ssElts (SizedSeq _ r_xs) = reverse r_xs
  
  sizeSS :: SizedSeq a -> Word
  sizeSS (SizedSeq n _) = n
  