{-# LANGUAGE StandaloneDeriving, DeriveGeneric #-}
module 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 Data.List
import GHC.Generics

data SizedSeq a = SizedSeq {-# UNPACK #-} !Word [a]
  deriving ((forall x. SizedSeq a -> Rep (SizedSeq a) x)
-> (forall x. Rep (SizedSeq a) x -> SizedSeq a)
-> Generic (SizedSeq a)
forall x. Rep (SizedSeq a) x -> SizedSeq a
forall x. SizedSeq a -> Rep (SizedSeq a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (SizedSeq a) x -> SizedSeq a
forall a x. SizedSeq a -> Rep (SizedSeq a) x
$cto :: forall a x. Rep (SizedSeq a) x -> SizedSeq a
$cfrom :: forall a x. SizedSeq a -> Rep (SizedSeq a) x
Generic, Int -> SizedSeq a -> ShowS
[SizedSeq a] -> ShowS
SizedSeq a -> String
(Int -> SizedSeq a -> ShowS)
-> (SizedSeq a -> String)
-> ([SizedSeq a] -> ShowS)
-> Show (SizedSeq a)
forall a. Show a => Int -> SizedSeq a -> ShowS
forall a. Show a => [SizedSeq a] -> ShowS
forall a. Show a => SizedSeq a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SizedSeq a] -> ShowS
$cshowList :: forall a. Show a => [SizedSeq a] -> ShowS
show :: SizedSeq a -> String
$cshow :: forall a. Show a => SizedSeq a -> String
showsPrec :: Int -> SizedSeq a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> SizedSeq a -> ShowS
Show)

instance Functor SizedSeq where
  fmap :: forall a b. (a -> b) -> SizedSeq a -> SizedSeq b
fmap a -> b
f (SizedSeq Word
sz [a]
l) = Word -> [b] -> SizedSeq b
forall a. Word -> [a] -> SizedSeq a
SizedSeq Word
sz ((a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f [a]
l)

instance Foldable SizedSeq where
  foldr :: forall a b. (a -> b -> b) -> b -> SizedSeq a -> b
foldr a -> b -> b
f b
c SizedSeq a
ss = (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr a -> b -> b
f b
c (SizedSeq a -> [a]
forall a. SizedSeq a -> [a]
ssElts SizedSeq a
ss)

instance Traversable SizedSeq where
  traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> SizedSeq a -> f (SizedSeq b)
traverse a -> f b
f (SizedSeq Word
sz [a]
l) = Word -> [b] -> SizedSeq b
forall a. Word -> [a] -> SizedSeq a
SizedSeq Word
sz ([b] -> SizedSeq b) -> ([b] -> [b]) -> [b] -> SizedSeq b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [b] -> [b]
forall a. [a] -> [a]
reverse ([b] -> SizedSeq b) -> f [b] -> f (SizedSeq b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> f b) -> [a] -> f [b]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
l)

instance Binary a => Binary (SizedSeq a)

instance NFData a => NFData (SizedSeq a) where
  rnf :: SizedSeq a -> ()
rnf (SizedSeq Word
_ [a]
xs) = [a] -> ()
forall a. NFData a => a -> ()
rnf [a]
xs

emptySS :: SizedSeq a
emptySS :: forall a. SizedSeq a
emptySS = Word -> [a] -> SizedSeq a
forall a. Word -> [a] -> SizedSeq a
SizedSeq Word
0 []

addToSS :: SizedSeq a -> a -> SizedSeq a
addToSS :: forall a. SizedSeq a -> a -> SizedSeq a
addToSS (SizedSeq Word
n [a]
r_xs) a
x = Word -> [a] -> SizedSeq a
forall a. Word -> [a] -> SizedSeq a
SizedSeq (Word
nWord -> Word -> Word
forall a. Num a => a -> a -> a
+Word
1) (a
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:[a]
r_xs)

addListToSS :: SizedSeq a -> [a] -> SizedSeq a
addListToSS :: forall a. SizedSeq a -> [a] -> SizedSeq a
addListToSS (SizedSeq Word
n [a]
r_xs) [a]
xs
  = Word -> [a] -> SizedSeq a
forall a. Word -> [a] -> SizedSeq a
SizedSeq (Word
n Word -> Word -> Word
forall a. Num a => a -> a -> a
+ [a] -> Word
forall i a. Num i => [a] -> i
genericLength [a]
xs) ([a] -> [a]
forall a. [a] -> [a]
reverse [a]
xs [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
r_xs)

ssElts :: SizedSeq a -> [a]
ssElts :: forall a. SizedSeq a -> [a]
ssElts (SizedSeq Word
_ [a]
r_xs) = [a] -> [a]
forall a. [a] -> [a]
reverse [a]
r_xs

sizeSS :: SizedSeq a -> Word
sizeSS :: forall a. SizedSeq a -> Word
sizeSS (SizedSeq Word
n [a]
_) = Word
n