combobuffer-0.1: src/Data/RingBuffer/SeqBuffer.hs
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wall #-}
-- | A 'RingBuffer' based on 'Data.Sequence.Seq'. Asymptotic behavior is quite
-- good in all cases, but constant factors are very high.
module Data.RingBuffer.SeqBuffer (
SeqBuffer
,RingBuffer (..)
,new
)
where
import Prelude hiding (length, (!!))
import Data.RingBuffer.Class
import qualified Data.Sequence as S
import Data.Foldable
newtype SeqBuffer a = RB (S.Seq a) deriving (Eq, Ord, Show)
type instance El (SeqBuffer a) = a
instance Initializable (SeqBuffer a) where
{-# INLINE newInit #-}
newInit = newInit'
instance RingBuffer (SeqBuffer a) where
{-# INLINE length #-}
length = length'
{-# INLINE push #-}
push = push'
{-# INLINE (!) #-}
(!) = (!!)
{-# INLINE slice #-}
slice (RB sq) start num = toList . S.take num $ S.drop start sq
-- | Create a new SeqBuffer, initialized to all 0's, of the given size
new :: (Num a) => Int -> SeqBuffer a
new = newInit' 0
{-# INLINE new #-}
-- | Create a new SeqBuffer from a given initial value
newInit' :: a -> Int -> SeqBuffer a
newInit' _ sz | sz <= 0 = error "can't make empty ringbuffer"
newInit' i sz = RB (S.replicate sz i)
{-# INLINE newInit' #-}
-- | Get the total size of a SeqBuffer.
length' :: SeqBuffer a -> Int
length' (RB vec) = S.length vec
{-# INLINE length' #-}
-- | Look up a value in a SeqBuffer.
(!!) :: SeqBuffer a -> Int -> a
(!!) (RB vec) = S.index vec
{-# INLINE (!!) #-}
-- | Push a new value into a SeqBuffer. The following will hold:
-- NewSeqBuffer ! 0 === added element
-- NewSeqBuffer ! 1 === OldSeqBuffer ! 0
push' :: SeqBuffer a -> a -> SeqBuffer a
push' (RB vec) el = case S.viewr vec of
v' S.:> _ -> RB $ el S.<| v'
_ -> error "internal error"
{-# INLINE push' #-}