mutable-containers 0.3.3 → 0.3.4
raw patch · 21 files changed
+1033/−999 lines, 21 filesdep +gaugedep −criteriondep ~base
Dependencies added: gauge
Dependencies removed: criterion
Dependency ranges changed: base
Files
- ChangeLog.md +4/−0
- Data/Mutable.hs +0/−68
- Data/Mutable/BRef.hs +0/−71
- Data/Mutable/Class.hs +0/−373
- Data/Mutable/DLList.hs +0/−101
- Data/Mutable/Deque.hs +0/−152
- Data/Mutable/PRef.hs +0/−64
- Data/Mutable/SRef.hs +0/−55
- Data/Mutable/URef.hs +0/−51
- README.md +2/−1
- bench/deque.hs +1/−1
- bench/ref.hs +1/−1
- mutable-containers.cabal +92/−61
- src/Data/Mutable.hs +68/−0
- src/Data/Mutable/BRef.hs +71/−0
- src/Data/Mutable/Class.hs +373/−0
- src/Data/Mutable/DLList.hs +101/−0
- src/Data/Mutable/Deque.hs +152/−0
- src/Data/Mutable/PRef.hs +62/−0
- src/Data/Mutable/SRef.hs +55/−0
- src/Data/Mutable/URef.hs +51/−0
ChangeLog.md view
@@ -1,3 +1,7 @@+## 0.3.4++* Switch to gauge+ ## 0.3.3 * Move into mono-traversable repo
− Data/Mutable.hs
@@ -1,68 +0,0 @@--- | Classes and concrete implementations for mutable data structures.------ For more information on the design of this library, see the README file,--- also available at <http://www.stackage.org/package/mutable-containers>.-module Data.Mutable- ( -- * Data types- -- ** Single-cell mutable references- PRef- , IOPRef- , asPRef- , URef- , IOURef- , asURef- , SRef- , IOSRef- , asSRef- , BRef- , IOBRef- , asBRef- -- *** Standard re-exports- , IORef- , asIORef- , STRef- , asSTRef- , MutVar- , asMutVar- -- ** Collections/queues- , Deque- , UDeque- , asUDeque- , SDeque- , asSDeque- , BDeque- , asBDeque- , DLList- , asDLList- -- * Type classes- , MutableContainer (..)- , MutableRef (..)- , MutableAtomicRef (..)- , MutableCollection (..)- , MutablePushFront (..)- , MutablePushBack (..)- , MutablePopFront (..)- , MutablePopBack (..)- -- * Constraint kinds- , MutableQueue- , MutableStack- , MutableDeque- -- * Convenience re-exports- , PrimMonad- , PrimState- , RealWorld- , Prim- , Unbox- , Storable- ) where--import Data.Mutable.Class-import Data.Mutable.URef-import Data.Mutable.SRef-import Data.Mutable.PRef-import Data.Mutable.BRef-import Data.Mutable.Deque-import Data.Mutable.DLList-import Data.Vector.Unboxed (Unbox)-import Data.Primitive (Prim)-import Data.Vector.Storable (Storable)
− Data/Mutable/BRef.hs
@@ -1,71 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--- | Use 1-length mutable boxed vectors for mutable references.------ Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.-module Data.Mutable.BRef- ( -- * Types- BRef- , IOBRef- -- * Functions- , asBRef- , MutableRef (..)- ) where--import Control.Monad (liftM)-import Data.Monoid (Monoid, mempty)-import Data.MonoTraversable (Element)-import Data.Mutable.Class-import Data.Sequences (IsSequence)-import qualified Data.Vector.Generic.Mutable as V-import qualified Data.Vector.Mutable as VB---- | A boxed vector reference, supporting any monad.------ Since 0.2.0-newtype BRef s a = BRef (VB.MVector s a)---- |--- Since 0.2.0-asBRef :: BRef s a -> BRef s a-asBRef x = x-{-# INLINE asBRef #-}---- | A boxed IO vector reference.-type IOBRef = BRef (PrimState IO)--instance MutableContainer (BRef s a) where- type MCState (BRef s a) = s-instance MutableRef (BRef s a) where- type RefElement (BRef s a) = a-- newRef = liftM BRef . V.replicate 1- {-# INLINE newRef#-}-- readRef (BRef v) = V.unsafeRead v 0- {-# INLINE readRef #-}-- writeRef (BRef v) = V.unsafeWrite v 0- {-# INLINE writeRef #-}-- modifyRef (BRef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f- {-# INLINE modifyRef #-}-- modifyRef' = modifyRef- {-# INLINE modifyRef' #-}--instance Monoid w => MutableCollection (BRef s w) where- type CollElement (BRef s w) = Element w- newColl = newRef mempty- {-# INLINE newColl #-}-instance IsSequence seq => MutablePushFront (BRef s seq) where- pushFront = pushFrontRef- {-# INLINE pushFront #-}-instance IsSequence seq => MutablePushBack (BRef s seq) where- pushBack = pushBackRef- {-# INLINE pushBack #-}-instance IsSequence seq => MutablePopFront (BRef s seq) where- popFront = popFrontRef- {-# INLINE popFront #-}-instance IsSequence seq => MutablePopBack (BRef s seq) where- popBack = popBackRef- {-# INLINE popBack #-}
− Data/Mutable/Class.hs
@@ -1,373 +0,0 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeFamilies #-}--- | Various typeclasses for mutable containers.-module Data.Mutable.Class- ( PrimMonad- , PrimState- , RealWorld- , MutableQueue- , MutableStack- , MutableDeque- , IORef- , asIORef- , STRef- , asSTRef- , MutVar- , asMutVar- , MutableContainer (..)- , MutableRef (..)- , MutableAtomicRef (..)- , MutableCollection (..)- , MutablePushFront (..)- , MutablePushBack (..)- , MutablePopFront (..)- , MutablePopBack (..)- , pushFrontRef- , pushBackRef- , popFrontRef- , popBackRef- ) where--import Control.Monad.Primitive-import Data.IORef-import Data.Monoid-import Data.MonoTraversable (Element)-import Data.Primitive.MutVar-import qualified Data.Sequences as Seqs-import Data.STRef---- | The parent typeclass for all mutable containers.------ Since 0.2.0-class MutableContainer c where- -- | Associated type giving the primitive state token for the given- -- container, much like 'PrimState' from primitive.- --- -- Since 0.2.0- type MCState c--instance MutableContainer (IORef a) where- type MCState (IORef a) = PrimState IO-instance MutableContainer (STRef s a) where- type MCState (STRef s a) = s-instance MutableContainer (MutVar s a) where- type MCState (MutVar s a) = s---- | Typeclass for single-cell mutable references.------ Since 0.2.0-class MutableContainer c => MutableRef c where- -- | Associated type giving the type of the value inside the mutable- -- reference.- --- -- Since 0.2.0- type RefElement c-- -- | Create a new mutable reference with the given value.- --- -- Since 0.2.0- newRef :: (PrimMonad m, PrimState m ~ MCState c)- => RefElement c- -> m c-- -- | Read the current value in the mutable reference.- --- -- Since 0.2.0- readRef :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> m (RefElement c)-- -- | Write a new value to the mutable reference.- --- -- Since 0.2.0- writeRef :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> RefElement c- -> m ()-- -- | Modify the value in the mutable reference, without necessarily forcing the result.- --- -- Note: some implementations /will/ force the result, in particular- -- @PRef@, @SRef@, and @URef@.- --- -- Since 0.2.0- modifyRef :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> (RefElement c -> RefElement c)- -> m ()-- -- | Modify the value in the mutable reference, forcing the result.- --- -- Since 0.2.0- modifyRef' :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> (RefElement c -> RefElement c)- -> m ()--instance MutableRef (IORef a) where- type RefElement (IORef a) = a- newRef = primToPrim . newIORef- {-# INLINE newRef #-}- readRef = primToPrim . readIORef- {-# INLINE readRef #-}- writeRef c = primToPrim . writeIORef c- {-# INLINE writeRef #-}- modifyRef c = primToPrim . modifyIORef c- {-# INLINE modifyRef #-}- modifyRef' c = primToPrim . modifyIORef' c- {-# INLINE modifyRef' #-}-instance MutableRef (STRef s a) where- type RefElement (STRef s a) = a- newRef = primToPrim . newSTRef- {-# INLINE newRef #-}- readRef = primToPrim . readSTRef- {-# INLINE readRef #-}- writeRef c = primToPrim . writeSTRef c- {-# INLINE writeRef #-}- modifyRef c = primToPrim . modifySTRef c- {-# INLINE modifyRef #-}- modifyRef' c = primToPrim . modifySTRef' c- {-# INLINE modifyRef' #-}-instance MutableRef (MutVar s a) where- type RefElement (MutVar s a) = a- newRef = newMutVar- {-# INLINE newRef #-}- readRef = readMutVar- {-# INLINE readRef #-}- writeRef = writeMutVar- {-# INLINE writeRef #-}- modifyRef = modifyMutVar- {-# INLINE modifyRef #-}- modifyRef' = modifyMutVar'- {-# INLINE modifyRef' #-}---- | @MutableRef@s that provide for atomic modifications of their contents.------ Since 0.2.0-class MutableRef c => MutableAtomicRef c where- -- | Modify the value without necessarily forcing the result.- --- -- Since 0.2.0- atomicModifyRef- :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> (RefElement c -> (RefElement c, a))- -> m a-- -- | Modify the value, forcing the result.- --- -- Since 0.2.0- atomicModifyRef'- :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> (RefElement c -> (RefElement c, a))- -> m a-instance MutableAtomicRef (IORef a) where- atomicModifyRef c = primToPrim . atomicModifyIORef c- {-# INLINE atomicModifyRef #-}- atomicModifyRef' c = primToPrim . atomicModifyIORef' c- {-# INLINE atomicModifyRef' #-}-instance MutableAtomicRef (MutVar s a) where- atomicModifyRef = atomicModifyMutVar- {-# INLINE atomicModifyRef #-}- atomicModifyRef' = atomicModifyMutVar'- {-# INLINE atomicModifyRef' #-}---- | Containers which contain 0 or more values.------ Since 0.2.0-class MutableContainer c => MutableCollection c where- -- | The type of each value in the collection.- --- -- Since 0.2.0- type CollElement c-- -- | Create a new, empty collection.- --- -- Since 0.2.0- newColl :: (PrimMonad m, PrimState m ~ MCState c)- => m c-instance Monoid w => MutableCollection (IORef w) where- type CollElement (IORef w) = Element w- newColl = newRef mempty- {-# INLINE newColl #-}-instance Monoid w => MutableCollection (STRef s w) where- type CollElement (STRef s w) = Element w- newColl = newRef mempty- {-# INLINE newColl #-}-instance Monoid w => MutableCollection (MutVar s w) where- type CollElement (MutVar s w) = Element w- newColl = newRef mempty- {-# INLINE newColl #-}---- | Take a value from the front of the collection, if available.------ Since 0.2.0-class MutableCollection c => MutablePopFront c where- -- | Take a value from the front of the collection, if available.- --- -- Since 0.2.0- popFront :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> m (Maybe (CollElement c))-popFrontRef- :: ( PrimMonad m- , PrimState m ~ MCState c- , MutableRef c- , CollElement c ~ Element (RefElement c)- , Seqs.IsSequence (RefElement c)- )- => c- -> m (Maybe (CollElement c))-popFrontRef c = do- l <- readRef c- case Seqs.uncons l of- Nothing -> return Nothing- Just (x, xs) -> do- writeRef c xs- return (Just x)-{-# INLINE popFrontRef #-}-instance Seqs.IsSequence a => MutablePopFront (IORef a) where- popFront = popFrontRef- {-# INLINE popFront #-}-instance Seqs.IsSequence a => MutablePopFront (STRef s a) where- popFront = popFrontRef- {-# INLINE popFront #-}-instance Seqs.IsSequence a => MutablePopFront (MutVar s a) where- popFront = popFrontRef- {-# INLINE popFront #-}---- | Place a value at the front of the collection.------ Since 0.2.0-class MutableCollection c => MutablePushFront c where- -- | Place a value at the front of the collection.- --- -- Since 0.2.0- pushFront :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> CollElement c- -> m ()-pushFrontRef- :: ( PrimMonad m- , PrimState m ~ MCState c- , MutableRef c- , CollElement c ~ Element (RefElement c)- , Seqs.IsSequence (RefElement c)- )- => c- -> CollElement c- -> m ()-pushFrontRef c e = modifyRef' c (Seqs.cons e)-{-# INLINE pushFrontRef #-}-instance Seqs.IsSequence a => MutablePushFront (IORef a) where- pushFront = pushFrontRef- {-# INLINE pushFront #-}-instance Seqs.IsSequence a => MutablePushFront (STRef s a) where- pushFront = pushFrontRef- {-# INLINE pushFront #-}-instance Seqs.IsSequence a => MutablePushFront (MutVar s a) where- pushFront = pushFrontRef- {-# INLINE pushFront #-}---- | Take a value from the back of the collection, if available.------ Since 0.2.0-class MutableCollection c => MutablePopBack c where- -- | Take a value from the back of the collection, if available.- --- -- Since 0.2.0- popBack :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> m (Maybe (CollElement c))-popBackRef- :: ( PrimMonad m- , PrimState m ~ MCState c- , MutableRef c- , CollElement c ~ Element (RefElement c)- , Seqs.IsSequence (RefElement c)- )- => c- -> m (Maybe (CollElement c))-popBackRef c = do- l <- readRef c- case Seqs.unsnoc l of- Nothing -> return Nothing- Just (xs, x) -> do- writeRef c xs- return (Just x)-{-# INLINE popBackRef #-}-instance Seqs.IsSequence a => MutablePopBack (IORef a) where- popBack = popBackRef- {-# INLINE popBack #-}-instance Seqs.IsSequence a => MutablePopBack (STRef s a) where- popBack = popBackRef- {-# INLINE popBack #-}-instance Seqs.IsSequence a => MutablePopBack (MutVar s a) where- popBack = popBackRef- {-# INLINE popBack #-}---- | Place a value at the back of the collection.------ Since 0.2.0-class MutableCollection c => MutablePushBack c where- -- | Place a value at the back of the collection.- --- -- Since 0.2.0- pushBack :: (PrimMonad m, PrimState m ~ MCState c)- => c- -> CollElement c- -> m ()-pushBackRef- :: ( PrimMonad m- , PrimState m ~ MCState c- , MutableRef c- , CollElement c ~ Element (RefElement c)- , Seqs.IsSequence (RefElement c)- )- => c- -> CollElement c- -> m ()-pushBackRef c e = modifyRef' c (`Seqs.snoc` e)-{-# INLINE pushBackRef #-}-instance Seqs.IsSequence a => MutablePushBack (IORef a) where- pushBack = pushBackRef- {-# INLINE pushBack #-}-instance Seqs.IsSequence a => MutablePushBack (STRef s a) where- pushBack = pushBackRef- {-# INLINE pushBack #-}-instance Seqs.IsSequence a => MutablePushBack (MutVar s a) where- pushBack = pushBackRef- {-# INLINE pushBack #-}---- | Collections which allow pushing and popping at the front (aka FIFOs).------ Since 0.2.0-type MutableQueue c = (MutablePopFront c, MutablePushBack c)---- | Collections which allow pushing at the back and popping at the front (aka FILOs).------ Since 0.2.0-type MutableStack c = (MutablePopFront c, MutablePushFront c)---- | Collections which allow pushing and popping at the front and back.------ Since 0.2.0-type MutableDeque c = (MutableQueue c, MutablePushFront c, MutablePopBack c)---- |--- Since 0.2.0-asIORef :: IORef a -> IORef a-asIORef = id---- |--- Since 0.2.0-asSTRef :: STRef s a -> STRef s a-asSTRef = id---- |--- Since 0.2.0-asMutVar :: MutVar s a -> MutVar s a-asMutVar = id
− Data/Mutable/DLList.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--- | Doubly-linked list-module Data.Mutable.DLList- ( DLList- , asDLList- , module Data.Mutable.Class- ) where--import Data.Mutable.Class--data Node s a = Node- a- (MutVar s (Maybe (Node s a))) -- previous- (MutVar s (Maybe (Node s a))) -- next---- | A doubly-linked list.------ Since 0.3.0-data DLList s a = DLList (MutVar s (Maybe (Node s a))) (MutVar s (Maybe (Node s a)))---- |--- Since 0.2.0-asDLList :: DLList s a -> DLList s a-asDLList = id-{-# INLINE asDLList #-}--instance MutableContainer (DLList s a) where- type MCState (DLList s a) = s-instance MutableCollection (DLList s a) where- type CollElement (DLList s a) = a- newColl = do- x <- newRef $! Nothing- y <- newRef $! Nothing- return $! DLList x y- {-# INLINE newColl #-}-instance MutablePopFront (DLList s a) where- popFront (DLList frontRef backRef) = do- mfront <- readRef frontRef- case mfront of- Nothing -> return Nothing- Just (Node val _ nextRef) -> do- mnext <- readRef nextRef- case mnext of- Nothing -> do- writeRef frontRef $! Nothing- writeRef backRef $! Nothing- Just next@(Node _ prevRef _) -> do- writeRef prevRef $! Nothing- writeRef frontRef $! Just next- return $ Just val- {-# INLINE popFront #-}-instance MutablePopBack (DLList s a) where- popBack (DLList frontRef backRef) = do- mback <- readRef backRef- case mback of- Nothing -> return Nothing- Just (Node val prevRef _) -> do- mprev <- readRef prevRef- case mprev of- Nothing -> do- writeRef frontRef $! Nothing- writeRef backRef $! Nothing- Just prev@(Node _ _ nextRef) -> do- writeRef nextRef $! Nothing- writeRef backRef (Just prev)- return $ Just val- {-# INLINE popBack #-}-instance MutablePushFront (DLList s a) where- pushFront (DLList frontRef backRef) val = do- mfront <- readRef frontRef- case mfront of- Nothing -> do- prevRef <- newRef $! Nothing- nextRef <- newRef $! Nothing- let node = Just $ Node val prevRef nextRef- writeRef frontRef node- writeRef backRef node- Just front@(Node _ prevRef _) -> do- prevRefNew <- newRef $! Nothing- nextRef <- newRef $ Just front- let node = Just $ Node val prevRefNew nextRef- writeRef prevRef node- writeRef frontRef node- {-# INLINE pushFront #-}-instance MutablePushBack (DLList s a) where- pushBack (DLList frontRef backRef) val = do- mback <- readRef backRef- case mback of- Nothing -> do- prevRef <- newRef $! Nothing- nextRef <- newRef $! Nothing- let node = Just $! Node val prevRef nextRef- writeRef frontRef $! node- writeRef backRef $! node- Just back@(Node _ _ nextRef) -> do- nextRefNew <- newRef $! Nothing- prevRef <- newRef $! Just back- let node = Just $! Node val prevRef nextRefNew- writeRef nextRef $! node- writeRef backRef $! node- {-# INLINE pushBack #-}
− Data/Mutable/Deque.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-module Data.Mutable.Deque- ( Deque- , UDeque- , asUDeque- , SDeque- , asSDeque- , BDeque- , asBDeque- , module Data.Mutable.Class- ) where--import Control.Exception (assert)-import Control.Monad (liftM)-import Data.Mutable.Class-import qualified Data.Vector.Generic.Mutable as V-import qualified Data.Vector.Mutable as B-import qualified Data.Vector.Storable.Mutable as S-import qualified Data.Vector.Unboxed.Mutable as U--data DequeState v s a = DequeState- (v s a)- {-# UNPACK #-} !Int -- start- {-# UNPACK #-} !Int -- size---- | A double-ended queue supporting any underlying vector type and any monad.------ This implements a circular double-ended queue with exponential growth.------ Since 0.2.0-newtype Deque v s a = Deque (MutVar s (DequeState v s a))---- | A 'Deque' specialized to unboxed vectors.------ Since 0.2.0-type UDeque = Deque U.MVector---- | A 'Deque' specialized to storable vectors.------ Since 0.2.0-type SDeque = Deque S.MVector---- | A 'Deque' specialized to boxed vectors.------ Since 0.2.0-type BDeque = Deque B.MVector---- |--- Since 0.2.0-asUDeque :: UDeque s a -> UDeque s a-asUDeque = id---- |--- Since 0.2.0-asSDeque :: SDeque s a -> SDeque s a-asSDeque = id---- |--- Since 0.2.0-asBDeque :: BDeque s a -> BDeque s a-asBDeque = id--instance MutableContainer (Deque v s a) where- type MCState (Deque v s a) = s-instance V.MVector v a => MutableCollection (Deque v s a) where- type CollElement (Deque v s a) = a- newColl = do- v <- V.new baseSize- liftM Deque $ newRef (DequeState v 0 0)- where- baseSize = 32- {-# INLINE newColl #-}-instance V.MVector v a => MutablePopFront (Deque v s a) where- popFront (Deque var) = do- DequeState v start size <- readRef var- if size == 0- then return Nothing- else do- x <- V.unsafeRead v start- let start' = start + 1- start''- | start' >= V.length v = 0- | otherwise = start'- writeRef var $! DequeState v start'' (size - 1)- return $! Just x- {-# INLINE popFront #-}-instance V.MVector v a => MutablePopBack (Deque v s a) where- popBack (Deque var) = do- DequeState v start size <- readRef var- if size == 0- then return Nothing- else do- let size' = size - 1- end = start + size'- end'- | end >= V.length v = end - V.length v- | otherwise = end- x <- V.unsafeRead v end'- writeRef var $! DequeState v start size'- return $! Just x- {-# INLINE popBack #-}-instance V.MVector v a => MutablePushFront (Deque v s a) where- pushFront (Deque var) x = do- DequeState v start size <- readRef var- inner v start size- where- inner v start size = do- if size >= V.length v- then newVector v start size inner- else do- let size' = size + 1- start' = (start - 1) `rem` V.length v- start''- | start' < 0 = V.length v + start'- | otherwise = start'- V.unsafeWrite v start'' x- writeRef var $! DequeState v start'' size'- {-# INLINE pushFront #-}-instance V.MVector v a => MutablePushBack (Deque v s a) where- pushBack (Deque var) x = do- DequeState v start size <- readRef var- inner v start size- where- inner v start size = do- if size >= V.length v- then newVector v start size inner- else do- let end = start + size- end'- | end >= V.length v = end - V.length v- | otherwise = end- V.unsafeWrite v end' x- writeRef var $! DequeState v start (size + 1)- {-# INLINE pushBack #-}--newVector :: (PrimMonad m, V.MVector v a)- => v (PrimState m) a- -> Int- -> Int- -> (v (PrimState m) a -> Int -> Int -> m b)- -> m b-newVector v size2 sizeOrig f = assert (sizeOrig == V.length v) $ do- v' <- V.unsafeNew (V.length v * 2)- let size1 = V.length v - size2- V.unsafeCopy- (V.unsafeTake size1 v')- (V.unsafeSlice size2 size1 v)- V.unsafeCopy- (V.unsafeSlice size1 size2 v')- (V.unsafeTake size2 v)- f v' 0 sizeOrig-{-# INLINE newVector #-}
− Data/Mutable/PRef.hs
@@ -1,64 +0,0 @@-{-# LANGUAGE MagicHash #-}-{-# LANGUAGE TypeFamilies #-}--- | Use @ByteArray@s containing one element for mutable references.------ This is similar to @URef@s, but avoids the overhead of storing the length of--- the @Vector@, which we statically know will always be 1. This allows it to--- be a bit faster.------ Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.-module Data.Mutable.PRef- ( -- * Types- PRef- , IOPRef- -- * Functions- , asPRef- , MutableRef (..)- ) where--import Control.Monad (liftM)-import Data.Mutable.Class-import Data.Primitive (sizeOf)-import Data.Primitive.ByteArray (MutableByteArray, newByteArray, readByteArray,- writeByteArray)-import Data.Primitive.Types (Prim)-import GHC.Types (Int (..))---- | A primitive ByteArray reference, supporting any monad.------ Since 0.2.0-newtype PRef s a = PRef (MutableByteArray s)---- |--- Since 0.2.0-asPRef :: PRef s a -> PRef s a-asPRef x = x-{-# INLINE asPRef #-}---- | A primitive ByteArray IO reference.-type IOPRef = PRef (PrimState IO)--instance MutableContainer (PRef s a) where- type MCState (PRef s a) = s-instance Prim a => MutableRef (PRef s a) where- type RefElement (PRef s a) = a-- newRef x = do- ba <- newByteArray (sizeOf $! x)- writeByteArray ba 0 x- return $! PRef ba- {-# INLINE newRef #-}-- readRef (PRef ba) = readByteArray ba 0- {-# INLINE readRef #-}-- writeRef (PRef ba) = writeByteArray ba 0- {-# INLINE writeRef #-}-- modifyRef (PRef ba) f = do- x <- readByteArray ba 0- writeByteArray ba 0 $! f x- {-# INLINE modifyRef #-}-- modifyRef' = modifyRef- {-# INLINE modifyRef' #-}
− Data/Mutable/SRef.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--- | Use 1-length mutable storable vectors for mutable references.------ Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.-module Data.Mutable.SRef- ( -- * Types- SRef- , IOSRef- -- * Functions- , asSRef- , MutableRef (..)- ) where--import Data.Mutable.Class-import Foreign.ForeignPtr-import Foreign.Storable-import Control.Monad.Primitive---- | A storable vector reference, supporting any monad.------ Since 0.2.0-newtype SRef s a = SRef (ForeignPtr a)---- |--- Since 0.2.0-asSRef :: SRef s a -> SRef s a-asSRef x = x-{-# INLINE asSRef #-}---- | A storable IO vector reference.-type IOSRef = SRef (PrimState IO)--instance MutableContainer (SRef s a) where- type MCState (SRef s a) = s-instance Storable a => MutableRef (SRef s a) where- type RefElement (SRef s a) = a-- newRef x = unsafePrimToPrim $ do- fptr <- mallocForeignPtr- withForeignPtr fptr $ flip poke x- return $! SRef fptr- {-# INLINE newRef#-}-- readRef (SRef fptr) = unsafePrimToPrim $ withForeignPtr fptr peek- {-# INLINE readRef #-}-- writeRef (SRef fptr) x = unsafePrimToPrim $ withForeignPtr fptr $ flip poke x- {-# INLINE writeRef #-}-- modifyRef (SRef fptr) f = unsafePrimToPrim $ withForeignPtr fptr $ \ptr ->- peek ptr >>= poke ptr . f- {-# INLINE modifyRef #-}-- modifyRef' = modifyRef- {-# INLINE modifyRef' #-}
− Data/Mutable/URef.hs
@@ -1,51 +0,0 @@-{-# LANGUAGE TypeFamilies #-}--- | Use 1-length mutable unboxed vectors for mutable references.------ Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.-module Data.Mutable.URef- ( -- * Types- URef- , IOURef- -- * Functions- , asURef- , MutableRef (..)- ) where--import Control.Monad (liftM)-import Data.Mutable.Class-import qualified Data.Vector.Generic.Mutable as V-import qualified Data.Vector.Unboxed.Mutable as VU---- | An unboxed vector reference, supporting any monad.------ Since 0.2.0-newtype URef s a = URef (VU.MVector s a)---- |--- Since 0.2.0-asURef :: URef s a -> URef s a-asURef x = x-{-# INLINE asURef #-}---- | An unboxed IO vector reference.-type IOURef = URef (PrimState IO)--instance MutableContainer (URef s a) where- type MCState (URef s a) = s-instance VU.Unbox a => MutableRef (URef s a) where- type RefElement (URef s a) = a-- newRef = liftM URef . V.replicate 1- {-# INLINE newRef#-}-- readRef (URef v) = V.unsafeRead v 0- {-# INLINE readRef #-}-- writeRef (URef v) = V.unsafeWrite v 0- {-# INLINE writeRef #-}-- modifyRef (URef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f- {-# INLINE modifyRef #-}-- modifyRef' = modifyRef- {-# INLINE modifyRef' #-}
README.md view
@@ -115,7 +115,7 @@ additional data structures: double-ended queues and doubly-linked lists. The former is based around mutable vectors, and therefore as unboxed (`UDeque`), storable (`SDeque`), and boxed (`BDeque`) variants. Doubly-linked lists have no-such variety, and are simply `DList`s.+such variety, and are simply `DLList`s. For general purpose queue-like structures, `UDeque` or `SDeque` is likely to give you best performance. As usual, benchmark your own program to be certain,@@ -174,6 +174,7 @@ ### Deque benchmark ```+benchmarking IORef [Int] time 8.371 ms (8.362 ms .. 8.382 ms) 1.000 R² (1.000 R² .. 1.000 R²) mean 8.386 ms (8.378 ms .. 8.398 ms)
bench/deque.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE TypeFamilies #-} import Control.Monad-import Criterion.Main+import Gauge.Main import Data.Mutable import Data.Sequence (Seq)
bench/ref.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE TypeFamilies #-} import Control.Monad-import Criterion.Main+import Gauge.Main import Data.Mutable test :: (MCState c ~ PrimState IO, RefElement c ~ Int, MutableRef c)
mutable-containers.cabal view
@@ -1,69 +1,100 @@-name: mutable-containers-version: 0.3.3-synopsis: Abstactions and concrete implementations of mutable containers-description: See docs and README at <http://www.stackage.org/package/mutable-containers>-homepage: https://github.com/snoyberg/mono-traversable-license: MIT-license-file: LICENSE-author: Michael Snoyman-maintainer: michael@fpcomplete.com-category: Data-build-type: Simple-extra-source-files: README.md ChangeLog.md-cabal-version: >=1.10+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 40dea8fdbd3dd312e239092feaa21012ad064fac2c05429d687759366016cfe7 +name: mutable-containers+version: 0.3.4+synopsis: Abstactions and concrete implementations of mutable containers+description: See docs and README at <http://www.stackage.org/package/mutable-containers>+category: Data+homepage: https://github.com/snoyberg/mono-traversable#readme+bug-reports: https://github.com/snoyberg/mono-traversable/issues+author: Michael Snoyman+maintainer: michael@fpcomplete.com+license: MIT+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10++extra-source-files:+ ChangeLog.md+ README.md++source-repository head+ type: git+ location: https://github.com/snoyberg/mono-traversable+ library- exposed-modules: Data.Mutable- other-modules: Data.Mutable.SRef- Data.Mutable.Class- Data.Mutable.URef- Data.Mutable.PRef- Data.Mutable.BRef- Data.Mutable.DLList- Data.Mutable.Deque- build-depends: base >= 4.7 && < 5- , primitive >= 0.5.2.1- , containers- , vector- , mono-traversable- , ghc-prim- default-language: Haskell2010- ghc-options: -O2+ hs-source-dirs:+ src+ ghc-options: -O2+ build-depends:+ base >=4.9 && <5+ , containers+ , ghc-prim+ , mono-traversable+ , primitive >=0.5.2.1+ , vector+ exposed-modules:+ Data.Mutable+ other-modules:+ Data.Mutable.BRef+ Data.Mutable.Class+ Data.Mutable.Deque+ Data.Mutable.DLList+ Data.Mutable.PRef+ Data.Mutable.SRef+ Data.Mutable.URef+ Paths_mutable_containers+ default-language: Haskell2010 test-suite test- type: exitcode-stdio-1.0- hs-source-dirs: test- main-is: Spec.hs- build-depends: base- , mutable-containers- , hspec- , QuickCheck- , vector- , primitive- , containers- default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs:+ test+ build-depends:+ QuickCheck+ , base >=4.9 && <5+ , containers+ , hspec+ , mutable-containers+ , primitive+ , vector+ other-modules:+ Paths_mutable_containers+ default-language: Haskell2010 benchmark deque- type: exitcode-stdio-1.0- hs-source-dirs: bench- main-is: deque.hs- build-depends: base- , mutable-containers- , criterion- , containers- ghc-options: -Wall -O2 -rtsopts- default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: deque.hs+ hs-source-dirs:+ bench+ ghc-options: -Wall -O2 -rtsopts+ build-depends:+ base >=4.9 && <5+ , containers+ , gauge+ , mutable-containers+ , vector+ other-modules:+ Paths_mutable_containers+ default-language: Haskell2010 benchmark ref- type: exitcode-stdio-1.0- hs-source-dirs: bench- main-is: ref.hs- build-depends: base- , mutable-containers- , criterion- ghc-options: -Wall -O2 -rtsopts- default-language: Haskell2010--source-repository head- type: git- location: https://github.com/snoyberg/mono-traversable.git+ type: exitcode-stdio-1.0+ main-is: ref.hs+ hs-source-dirs:+ bench+ ghc-options: -Wall -O2 -rtsopts+ build-depends:+ base >=4.9 && <5+ , containers+ , gauge+ , mutable-containers+ , vector+ other-modules:+ Paths_mutable_containers+ default-language: Haskell2010
+ src/Data/Mutable.hs view
@@ -0,0 +1,68 @@+-- | Classes and concrete implementations for mutable data structures.+--+-- For more information on the design of this library, see the README file,+-- also available at <http://www.stackage.org/package/mutable-containers>.+module Data.Mutable+ ( -- * Data types+ -- ** Single-cell mutable references+ PRef+ , IOPRef+ , asPRef+ , URef+ , IOURef+ , asURef+ , SRef+ , IOSRef+ , asSRef+ , BRef+ , IOBRef+ , asBRef+ -- *** Standard re-exports+ , IORef+ , asIORef+ , STRef+ , asSTRef+ , MutVar+ , asMutVar+ -- ** Collections/queues+ , Deque+ , UDeque+ , asUDeque+ , SDeque+ , asSDeque+ , BDeque+ , asBDeque+ , DLList+ , asDLList+ -- * Type classes+ , MutableContainer (..)+ , MutableRef (..)+ , MutableAtomicRef (..)+ , MutableCollection (..)+ , MutablePushFront (..)+ , MutablePushBack (..)+ , MutablePopFront (..)+ , MutablePopBack (..)+ -- * Constraint kinds+ , MutableQueue+ , MutableStack+ , MutableDeque+ -- * Convenience re-exports+ , PrimMonad+ , PrimState+ , RealWorld+ , Prim+ , Unbox+ , Storable+ ) where++import Data.Mutable.Class+import Data.Mutable.URef+import Data.Mutable.SRef+import Data.Mutable.PRef+import Data.Mutable.BRef+import Data.Mutable.Deque+import Data.Mutable.DLList+import Data.Vector.Unboxed (Unbox)+import Data.Primitive (Prim)+import Data.Vector.Storable (Storable)
+ src/Data/Mutable/BRef.hs view
@@ -0,0 +1,71 @@+{-# LANGUAGE TypeFamilies #-}+-- | Use 1-length mutable boxed vectors for mutable references.+--+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.+module Data.Mutable.BRef+ ( -- * Types+ BRef+ , IOBRef+ -- * Functions+ , asBRef+ , MutableRef (..)+ ) where++import Control.Monad (liftM)+import Data.Monoid (Monoid, mempty)+import Data.MonoTraversable (Element)+import Data.Mutable.Class+import Data.Sequences (IsSequence)+import qualified Data.Vector.Generic.Mutable as V+import qualified Data.Vector.Mutable as VB++-- | A boxed vector reference, supporting any monad.+--+-- Since 0.2.0+newtype BRef s a = BRef (VB.MVector s a)++-- |+-- Since 0.2.0+asBRef :: BRef s a -> BRef s a+asBRef x = x+{-# INLINE asBRef #-}++-- | A boxed IO vector reference.+type IOBRef = BRef (PrimState IO)++instance MutableContainer (BRef s a) where+ type MCState (BRef s a) = s+instance MutableRef (BRef s a) where+ type RefElement (BRef s a) = a++ newRef = liftM BRef . V.replicate 1+ {-# INLINE newRef#-}++ readRef (BRef v) = V.unsafeRead v 0+ {-# INLINE readRef #-}++ writeRef (BRef v) = V.unsafeWrite v 0+ {-# INLINE writeRef #-}++ modifyRef (BRef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f+ {-# INLINE modifyRef #-}++ modifyRef' = modifyRef+ {-# INLINE modifyRef' #-}++instance Monoid w => MutableCollection (BRef s w) where+ type CollElement (BRef s w) = Element w+ newColl = newRef mempty+ {-# INLINE newColl #-}+instance IsSequence seq => MutablePushFront (BRef s seq) where+ pushFront = pushFrontRef+ {-# INLINE pushFront #-}+instance IsSequence seq => MutablePushBack (BRef s seq) where+ pushBack = pushBackRef+ {-# INLINE pushBack #-}+instance IsSequence seq => MutablePopFront (BRef s seq) where+ popFront = popFrontRef+ {-# INLINE popFront #-}+instance IsSequence seq => MutablePopBack (BRef s seq) where+ popBack = popBackRef+ {-# INLINE popBack #-}
+ src/Data/Mutable/Class.hs view
@@ -0,0 +1,373 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeFamilies #-}+-- | Various typeclasses for mutable containers.+module Data.Mutable.Class+ ( PrimMonad+ , PrimState+ , RealWorld+ , MutableQueue+ , MutableStack+ , MutableDeque+ , IORef+ , asIORef+ , STRef+ , asSTRef+ , MutVar+ , asMutVar+ , MutableContainer (..)+ , MutableRef (..)+ , MutableAtomicRef (..)+ , MutableCollection (..)+ , MutablePushFront (..)+ , MutablePushBack (..)+ , MutablePopFront (..)+ , MutablePopBack (..)+ , pushFrontRef+ , pushBackRef+ , popFrontRef+ , popBackRef+ ) where++import Control.Monad.Primitive+import Data.IORef+import Data.Monoid+import Data.MonoTraversable (Element)+import Data.Primitive.MutVar+import qualified Data.Sequences as Seqs+import Data.STRef++-- | The parent typeclass for all mutable containers.+--+-- Since 0.2.0+class MutableContainer c where+ -- | Associated type giving the primitive state token for the given+ -- container, much like 'PrimState' from primitive.+ --+ -- Since 0.2.0+ type MCState c++instance MutableContainer (IORef a) where+ type MCState (IORef a) = PrimState IO+instance MutableContainer (STRef s a) where+ type MCState (STRef s a) = s+instance MutableContainer (MutVar s a) where+ type MCState (MutVar s a) = s++-- | Typeclass for single-cell mutable references.+--+-- Since 0.2.0+class MutableContainer c => MutableRef c where+ -- | Associated type giving the type of the value inside the mutable+ -- reference.+ --+ -- Since 0.2.0+ type RefElement c++ -- | Create a new mutable reference with the given value.+ --+ -- Since 0.2.0+ newRef :: (PrimMonad m, PrimState m ~ MCState c)+ => RefElement c+ -> m c++ -- | Read the current value in the mutable reference.+ --+ -- Since 0.2.0+ readRef :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> m (RefElement c)++ -- | Write a new value to the mutable reference.+ --+ -- Since 0.2.0+ writeRef :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> RefElement c+ -> m ()++ -- | Modify the value in the mutable reference, without necessarily forcing the result.+ --+ -- Note: some implementations /will/ force the result, in particular+ -- @PRef@, @SRef@, and @URef@.+ --+ -- Since 0.2.0+ modifyRef :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> (RefElement c -> RefElement c)+ -> m ()++ -- | Modify the value in the mutable reference, forcing the result.+ --+ -- Since 0.2.0+ modifyRef' :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> (RefElement c -> RefElement c)+ -> m ()++instance MutableRef (IORef a) where+ type RefElement (IORef a) = a+ newRef = primToPrim . newIORef+ {-# INLINE newRef #-}+ readRef = primToPrim . readIORef+ {-# INLINE readRef #-}+ writeRef c = primToPrim . writeIORef c+ {-# INLINE writeRef #-}+ modifyRef c = primToPrim . modifyIORef c+ {-# INLINE modifyRef #-}+ modifyRef' c = primToPrim . modifyIORef' c+ {-# INLINE modifyRef' #-}+instance MutableRef (STRef s a) where+ type RefElement (STRef s a) = a+ newRef = primToPrim . newSTRef+ {-# INLINE newRef #-}+ readRef = primToPrim . readSTRef+ {-# INLINE readRef #-}+ writeRef c = primToPrim . writeSTRef c+ {-# INLINE writeRef #-}+ modifyRef c = primToPrim . modifySTRef c+ {-# INLINE modifyRef #-}+ modifyRef' c = primToPrim . modifySTRef' c+ {-# INLINE modifyRef' #-}+instance MutableRef (MutVar s a) where+ type RefElement (MutVar s a) = a+ newRef = newMutVar+ {-# INLINE newRef #-}+ readRef = readMutVar+ {-# INLINE readRef #-}+ writeRef = writeMutVar+ {-# INLINE writeRef #-}+ modifyRef = modifyMutVar+ {-# INLINE modifyRef #-}+ modifyRef' = modifyMutVar'+ {-# INLINE modifyRef' #-}++-- | @MutableRef@s that provide for atomic modifications of their contents.+--+-- Since 0.2.0+class MutableRef c => MutableAtomicRef c where+ -- | Modify the value without necessarily forcing the result.+ --+ -- Since 0.2.0+ atomicModifyRef+ :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> (RefElement c -> (RefElement c, a))+ -> m a++ -- | Modify the value, forcing the result.+ --+ -- Since 0.2.0+ atomicModifyRef'+ :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> (RefElement c -> (RefElement c, a))+ -> m a+instance MutableAtomicRef (IORef a) where+ atomicModifyRef c = primToPrim . atomicModifyIORef c+ {-# INLINE atomicModifyRef #-}+ atomicModifyRef' c = primToPrim . atomicModifyIORef' c+ {-# INLINE atomicModifyRef' #-}+instance MutableAtomicRef (MutVar s a) where+ atomicModifyRef = atomicModifyMutVar+ {-# INLINE atomicModifyRef #-}+ atomicModifyRef' = atomicModifyMutVar'+ {-# INLINE atomicModifyRef' #-}++-- | Containers which contain 0 or more values.+--+-- Since 0.2.0+class MutableContainer c => MutableCollection c where+ -- | The type of each value in the collection.+ --+ -- Since 0.2.0+ type CollElement c++ -- | Create a new, empty collection.+ --+ -- Since 0.2.0+ newColl :: (PrimMonad m, PrimState m ~ MCState c)+ => m c+instance Data.Monoid.Monoid w => MutableCollection (IORef w) where+ type CollElement (IORef w) = Element w+ newColl = newRef mempty+ {-# INLINE newColl #-}+instance Monoid w => MutableCollection (STRef s w) where+ type CollElement (STRef s w) = Element w+ newColl = newRef mempty+ {-# INLINE newColl #-}+instance Monoid w => MutableCollection (MutVar s w) where+ type CollElement (MutVar s w) = Element w+ newColl = newRef mempty+ {-# INLINE newColl #-}++-- | Take a value from the front of the collection, if available.+--+-- Since 0.2.0+class MutableCollection c => MutablePopFront c where+ -- | Take a value from the front of the collection, if available.+ --+ -- Since 0.2.0+ popFront :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> m (Maybe (CollElement c))+popFrontRef+ :: ( PrimMonad m+ , PrimState m ~ MCState c+ , MutableRef c+ , CollElement c ~ Element (RefElement c)+ , Seqs.IsSequence (RefElement c)+ )+ => c+ -> m (Maybe (CollElement c))+popFrontRef c = do+ l <- readRef c+ case Seqs.uncons l of+ Nothing -> return Nothing+ Just (x, xs) -> do+ writeRef c xs+ return (Just x)+{-# INLINE popFrontRef #-}+instance Seqs.IsSequence a => MutablePopFront (IORef a) where+ popFront = popFrontRef+ {-# INLINE popFront #-}+instance Seqs.IsSequence a => MutablePopFront (STRef s a) where+ popFront = popFrontRef+ {-# INLINE popFront #-}+instance Seqs.IsSequence a => MutablePopFront (MutVar s a) where+ popFront = popFrontRef+ {-# INLINE popFront #-}++-- | Place a value at the front of the collection.+--+-- Since 0.2.0+class MutableCollection c => MutablePushFront c where+ -- | Place a value at the front of the collection.+ --+ -- Since 0.2.0+ pushFront :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> CollElement c+ -> m ()+pushFrontRef+ :: ( PrimMonad m+ , PrimState m ~ MCState c+ , MutableRef c+ , CollElement c ~ Element (RefElement c)+ , Seqs.IsSequence (RefElement c)+ )+ => c+ -> CollElement c+ -> m ()+pushFrontRef c e = modifyRef' c (Seqs.cons e)+{-# INLINE pushFrontRef #-}+instance Seqs.IsSequence a => MutablePushFront (IORef a) where+ pushFront = pushFrontRef+ {-# INLINE pushFront #-}+instance Seqs.IsSequence a => MutablePushFront (STRef s a) where+ pushFront = pushFrontRef+ {-# INLINE pushFront #-}+instance Seqs.IsSequence a => MutablePushFront (MutVar s a) where+ pushFront = pushFrontRef+ {-# INLINE pushFront #-}++-- | Take a value from the back of the collection, if available.+--+-- Since 0.2.0+class MutableCollection c => MutablePopBack c where+ -- | Take a value from the back of the collection, if available.+ --+ -- Since 0.2.0+ popBack :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> m (Maybe (CollElement c))+popBackRef+ :: ( PrimMonad m+ , PrimState m ~ MCState c+ , MutableRef c+ , CollElement c ~ Element (RefElement c)+ , Seqs.IsSequence (RefElement c)+ )+ => c+ -> m (Maybe (CollElement c))+popBackRef c = do+ l <- readRef c+ case Seqs.unsnoc l of+ Nothing -> return Nothing+ Just (xs, x) -> do+ writeRef c xs+ return (Just x)+{-# INLINE popBackRef #-}+instance Seqs.IsSequence a => MutablePopBack (IORef a) where+ popBack = popBackRef+ {-# INLINE popBack #-}+instance Seqs.IsSequence a => MutablePopBack (STRef s a) where+ popBack = popBackRef+ {-# INLINE popBack #-}+instance Seqs.IsSequence a => MutablePopBack (MutVar s a) where+ popBack = popBackRef+ {-# INLINE popBack #-}++-- | Place a value at the back of the collection.+--+-- Since 0.2.0+class MutableCollection c => MutablePushBack c where+ -- | Place a value at the back of the collection.+ --+ -- Since 0.2.0+ pushBack :: (PrimMonad m, PrimState m ~ MCState c)+ => c+ -> CollElement c+ -> m ()+pushBackRef+ :: ( PrimMonad m+ , PrimState m ~ MCState c+ , MutableRef c+ , CollElement c ~ Element (RefElement c)+ , Seqs.IsSequence (RefElement c)+ )+ => c+ -> CollElement c+ -> m ()+pushBackRef c e = modifyRef' c (`Seqs.snoc` e)+{-# INLINE pushBackRef #-}+instance Seqs.IsSequence a => MutablePushBack (IORef a) where+ pushBack = pushBackRef+ {-# INLINE pushBack #-}+instance Seqs.IsSequence a => MutablePushBack (STRef s a) where+ pushBack = pushBackRef+ {-# INLINE pushBack #-}+instance Seqs.IsSequence a => MutablePushBack (MutVar s a) where+ pushBack = pushBackRef+ {-# INLINE pushBack #-}++-- | Collections which allow pushing and popping at the front (aka FIFOs).+--+-- Since 0.2.0+type MutableQueue c = (MutablePopFront c, MutablePushBack c)++-- | Collections which allow pushing at the back and popping at the front (aka FILOs).+--+-- Since 0.2.0+type MutableStack c = (MutablePopFront c, MutablePushFront c)++-- | Collections which allow pushing and popping at the front and back.+--+-- Since 0.2.0+type MutableDeque c = (MutableQueue c, MutablePushFront c, MutablePopBack c)++-- |+-- Since 0.2.0+asIORef :: IORef a -> IORef a+asIORef = id++-- |+-- Since 0.2.0+asSTRef :: STRef s a -> STRef s a+asSTRef = id++-- |+-- Since 0.2.0+asMutVar :: MutVar s a -> MutVar s a+asMutVar = id
+ src/Data/Mutable/DLList.hs view
@@ -0,0 +1,101 @@+{-# LANGUAGE TypeFamilies #-}+-- | Doubly-linked list+module Data.Mutable.DLList+ ( DLList+ , asDLList+ , module Data.Mutable.Class+ ) where++import Data.Mutable.Class++data Node s a = Node+ a+ (MutVar s (Maybe (Node s a))) -- previous+ (MutVar s (Maybe (Node s a))) -- next++-- | A doubly-linked list.+--+-- Since 0.3.0+data DLList s a = DLList (MutVar s (Maybe (Node s a))) (MutVar s (Maybe (Node s a)))++-- |+-- Since 0.2.0+asDLList :: DLList s a -> DLList s a+asDLList = id+{-# INLINE asDLList #-}++instance MutableContainer (DLList s a) where+ type MCState (DLList s a) = s+instance MutableCollection (DLList s a) where+ type CollElement (DLList s a) = a+ newColl = do+ x <- newRef $! Nothing+ y <- newRef $! Nothing+ return $! DLList x y+ {-# INLINE newColl #-}+instance MutablePopFront (DLList s a) where+ popFront (DLList frontRef backRef) = do+ mfront <- readRef frontRef+ case mfront of+ Nothing -> return Nothing+ Just (Node val _ nextRef) -> do+ mnext <- readRef nextRef+ case mnext of+ Nothing -> do+ writeRef frontRef $! Nothing+ writeRef backRef $! Nothing+ Just next@(Node _ prevRef _) -> do+ writeRef prevRef $! Nothing+ writeRef frontRef $! Just next+ return $ Just val+ {-# INLINE popFront #-}+instance MutablePopBack (DLList s a) where+ popBack (DLList frontRef backRef) = do+ mback <- readRef backRef+ case mback of+ Nothing -> return Nothing+ Just (Node val prevRef _) -> do+ mprev <- readRef prevRef+ case mprev of+ Nothing -> do+ writeRef frontRef $! Nothing+ writeRef backRef $! Nothing+ Just prev@(Node _ _ nextRef) -> do+ writeRef nextRef $! Nothing+ writeRef backRef (Just prev)+ return $ Just val+ {-# INLINE popBack #-}+instance MutablePushFront (DLList s a) where+ pushFront (DLList frontRef backRef) val = do+ mfront <- readRef frontRef+ case mfront of+ Nothing -> do+ prevRef <- newRef $! Nothing+ nextRef <- newRef $! Nothing+ let node = Just $ Node val prevRef nextRef+ writeRef frontRef node+ writeRef backRef node+ Just front@(Node _ prevRef _) -> do+ prevRefNew <- newRef $! Nothing+ nextRef <- newRef $ Just front+ let node = Just $ Node val prevRefNew nextRef+ writeRef prevRef node+ writeRef frontRef node+ {-# INLINE pushFront #-}+instance MutablePushBack (DLList s a) where+ pushBack (DLList frontRef backRef) val = do+ mback <- readRef backRef+ case mback of+ Nothing -> do+ prevRef <- newRef $! Nothing+ nextRef <- newRef $! Nothing+ let node = Just $! Node val prevRef nextRef+ writeRef frontRef $! node+ writeRef backRef $! node+ Just back@(Node _ _ nextRef) -> do+ nextRefNew <- newRef $! Nothing+ prevRef <- newRef $! Just back+ let node = Just $! Node val prevRef nextRefNew+ writeRef nextRef $! node+ writeRef backRef $! node+ {-# INLINE pushBack #-}
+ src/Data/Mutable/Deque.hs view
@@ -0,0 +1,152 @@+{-# LANGUAGE TypeFamilies #-}+module Data.Mutable.Deque+ ( Deque+ , UDeque+ , asUDeque+ , SDeque+ , asSDeque+ , BDeque+ , asBDeque+ , module Data.Mutable.Class+ ) where++import Control.Exception (assert)+import Control.Monad (liftM)+import Data.Mutable.Class+import qualified Data.Vector.Generic.Mutable as V+import qualified Data.Vector.Mutable as B+import qualified Data.Vector.Storable.Mutable as S+import qualified Data.Vector.Unboxed.Mutable as U++data DequeState v s a = DequeState+ (v s a)+ {-# UNPACK #-} !Int -- start+ {-# UNPACK #-} !Int -- size++-- | A double-ended queue supporting any underlying vector type and any monad.+--+-- This implements a circular double-ended queue with exponential growth.+--+-- Since 0.2.0+newtype Deque v s a = Deque (MutVar s (DequeState v s a))++-- | A 'Deque' specialized to unboxed vectors.+--+-- Since 0.2.0+type UDeque = Deque U.MVector++-- | A 'Deque' specialized to storable vectors.+--+-- Since 0.2.0+type SDeque = Deque S.MVector++-- | A 'Deque' specialized to boxed vectors.+--+-- Since 0.2.0+type BDeque = Deque B.MVector++-- |+-- Since 0.2.0+asUDeque :: UDeque s a -> UDeque s a+asUDeque = id++-- |+-- Since 0.2.0+asSDeque :: SDeque s a -> SDeque s a+asSDeque = id++-- |+-- Since 0.2.0+asBDeque :: BDeque s a -> BDeque s a+asBDeque = id++instance MutableContainer (Deque v s a) where+ type MCState (Deque v s a) = s+instance V.MVector v a => MutableCollection (Deque v s a) where+ type CollElement (Deque v s a) = a+ newColl = do+ v <- V.new baseSize+ liftM Deque $ newRef (DequeState v 0 0)+ where+ baseSize = 32+ {-# INLINE newColl #-}+instance V.MVector v a => MutablePopFront (Deque v s a) where+ popFront (Deque var) = do+ DequeState v start size <- readRef var+ if size == 0+ then return Nothing+ else do+ x <- V.unsafeRead v start+ let start' = start + 1+ start''+ | start' >= V.length v = 0+ | otherwise = start'+ writeRef var $! DequeState v start'' (size - 1)+ return $! Just x+ {-# INLINE popFront #-}+instance V.MVector v a => MutablePopBack (Deque v s a) where+ popBack (Deque var) = do+ DequeState v start size <- readRef var+ if size == 0+ then return Nothing+ else do+ let size' = size - 1+ end = start + size'+ end'+ | end >= V.length v = end - V.length v+ | otherwise = end+ x <- V.unsafeRead v end'+ writeRef var $! DequeState v start size'+ return $! Just x+ {-# INLINE popBack #-}+instance V.MVector v a => MutablePushFront (Deque v s a) where+ pushFront (Deque var) x = do+ DequeState v start size <- readRef var+ inner v start size+ where+ inner v start size = do+ if size >= V.length v+ then newVector v start size inner+ else do+ let size' = size + 1+ start' = (start - 1) `rem` V.length v+ start''+ | start' < 0 = V.length v + start'+ | otherwise = start'+ V.unsafeWrite v start'' x+ writeRef var $! DequeState v start'' size'+ {-# INLINE pushFront #-}+instance V.MVector v a => MutablePushBack (Deque v s a) where+ pushBack (Deque var) x = do+ DequeState v start size <- readRef var+ inner v start size+ where+ inner v start size = do+ if size >= V.length v+ then newVector v start size inner+ else do+ let end = start + size+ end'+ | end >= V.length v = end - V.length v+ | otherwise = end+ V.unsafeWrite v end' x+ writeRef var $! DequeState v start (size + 1)+ {-# INLINE pushBack #-}++newVector :: (PrimMonad m, V.MVector v a)+ => v (PrimState m) a+ -> Int+ -> Int+ -> (v (PrimState m) a -> Int -> Int -> m b)+ -> m b+newVector v size2 sizeOrig f = assert (sizeOrig == V.length v) $ do+ v' <- V.unsafeNew (V.length v * 2)+ let size1 = V.length v - size2+ V.unsafeCopy+ (V.unsafeTake size1 v')+ (V.unsafeSlice size2 size1 v)+ V.unsafeCopy+ (V.unsafeSlice size1 size2 v')+ (V.unsafeTake size2 v)+ f v' 0 sizeOrig+{-# INLINE newVector #-}
+ src/Data/Mutable/PRef.hs view
@@ -0,0 +1,62 @@+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE TypeFamilies #-}+-- | Use @ByteArray@s containing one element for mutable references.+--+-- This is similar to @URef@s, but avoids the overhead of storing the length of+-- the @Vector@, which we statically know will always be 1. This allows it to+-- be a bit faster.+--+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.+module Data.Mutable.PRef+ ( -- * Types+ PRef+ , IOPRef+ -- * Functions+ , asPRef+ , MutableRef (..)+ ) where++import Data.Mutable.Class+import Data.Primitive (sizeOf)+import Data.Primitive.ByteArray (MutableByteArray, newByteArray, readByteArray,+ writeByteArray)+import Data.Primitive.Types (Prim)++-- | A primitive ByteArray reference, supporting any monad.+--+-- Since 0.2.0+newtype PRef s a = PRef (MutableByteArray s)++-- |+-- Since 0.2.0+asPRef :: PRef s a -> PRef s a+asPRef x = x+{-# INLINE asPRef #-}++-- | A primitive ByteArray IO reference.+type IOPRef = PRef (PrimState IO)++instance MutableContainer (PRef s a) where+ type MCState (PRef s a) = s+instance Prim a => MutableRef (PRef s a) where+ type RefElement (PRef s a) = a++ newRef x = do+ ba <- newByteArray (sizeOf $! x)+ writeByteArray ba 0 x+ return $! PRef ba+ {-# INLINE newRef #-}++ readRef (PRef ba) = readByteArray ba 0+ {-# INLINE readRef #-}++ writeRef (PRef ba) = writeByteArray ba 0+ {-# INLINE writeRef #-}++ modifyRef (PRef ba) f = do+ x <- readByteArray ba 0+ writeByteArray ba 0 $! f x+ {-# INLINE modifyRef #-}++ modifyRef' = modifyRef+ {-# INLINE modifyRef' #-}
+ src/Data/Mutable/SRef.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE TypeFamilies #-}+-- | Use 1-length mutable storable vectors for mutable references.+--+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.+module Data.Mutable.SRef+ ( -- * Types+ SRef+ , IOSRef+ -- * Functions+ , asSRef+ , MutableRef (..)+ ) where++import Data.Mutable.Class+import Foreign.ForeignPtr+import Foreign.Storable+import Control.Monad.Primitive++-- | A storable vector reference, supporting any monad.+--+-- Since 0.2.0+newtype SRef s a = SRef (ForeignPtr a)++-- |+-- Since 0.2.0+asSRef :: SRef s a -> SRef s a+asSRef x = x+{-# INLINE asSRef #-}++-- | A storable IO vector reference.+type IOSRef = SRef (PrimState IO)++instance MutableContainer (SRef s a) where+ type MCState (SRef s a) = s+instance Storable a => MutableRef (SRef s a) where+ type RefElement (SRef s a) = a++ newRef x = unsafePrimToPrim $ do+ fptr <- mallocForeignPtr+ withForeignPtr fptr $ flip poke x+ return $! SRef fptr+ {-# INLINE newRef#-}++ readRef (SRef fptr) = unsafePrimToPrim $ withForeignPtr fptr peek+ {-# INLINE readRef #-}++ writeRef (SRef fptr) x = unsafePrimToPrim $ withForeignPtr fptr $ flip poke x+ {-# INLINE writeRef #-}++ modifyRef (SRef fptr) f = unsafePrimToPrim $ withForeignPtr fptr $ \ptr ->+ peek ptr >>= poke ptr . f+ {-# INLINE modifyRef #-}++ modifyRef' = modifyRef+ {-# INLINE modifyRef' #-}
+ src/Data/Mutable/URef.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE TypeFamilies #-}+-- | Use 1-length mutable unboxed vectors for mutable references.+--+-- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.+module Data.Mutable.URef+ ( -- * Types+ URef+ , IOURef+ -- * Functions+ , asURef+ , MutableRef (..)+ ) where++import Control.Monad (liftM)+import Data.Mutable.Class+import qualified Data.Vector.Generic.Mutable as V+import qualified Data.Vector.Unboxed.Mutable as VU++-- | An unboxed vector reference, supporting any monad.+--+-- Since 0.2.0+newtype URef s a = URef (VU.MVector s a)++-- |+-- Since 0.2.0+asURef :: URef s a -> URef s a+asURef x = x+{-# INLINE asURef #-}++-- | An unboxed IO vector reference.+type IOURef = URef (PrimState IO)++instance MutableContainer (URef s a) where+ type MCState (URef s a) = s+instance VU.Unbox a => MutableRef (URef s a) where+ type RefElement (URef s a) = a++ newRef = liftM URef . V.replicate 1+ {-# INLINE newRef#-}++ readRef (URef v) = V.unsafeRead v 0+ {-# INLINE readRef #-}++ writeRef (URef v) = V.unsafeWrite v 0+ {-# INLINE writeRef #-}++ modifyRef (URef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f+ {-# INLINE modifyRef #-}++ modifyRef' = modifyRef+ {-# INLINE modifyRef' #-}