packages feed

mutable-containers 0.1.2.0 → 0.2.0

raw patch · 15 files changed

+476/−126 lines, 15 files

Files

ChangeLog.md view
@@ -1,3 +1,7 @@+## 0.2.0++* Restructure under the Data.Mutable module.+ ## 0.1.2.0  * Added PRef
+ Data/Mutable.hs view
@@ -0,0 +1,58 @@+-- | 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+    , asPRef+    , URef+    , asURef+    , SRef+    , asSRef+    , BRef+    , asBRef+      -- *** Standard re-exports+    , IORef+    , asIORef+    , STRef+    , asSTRef+    , MutVar+    , asMutVar+      -- ** Collections/queues+    , Deque+    , UDeque+    , asUDeque+    , SDeque+    , asSDeque+    , BDeque+    , asBDeque+    , DList+    , asDList+      -- * Type classes+    , MutableContainer (..)+    , MutableRef (..)+    , MutableAtomicRef (..)+    , MutableCollection (..)+    , MutablePushFront (..)+    , MutablePushBack (..)+    , MutablePopFront (..)+    , MutablePopBack (..)+      -- * Constraint kinds+    , MutableQueue+    , MutableStack+    , MutableDeque+      -- * Convenience re-exports+    , PrimMonad+    , PrimState+    , RealWorld+    ) 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.DList
+ 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 #-}
Data/Mutable/Class.hs view
@@ -7,6 +7,7 @@     ( PrimMonad     , PrimState     , RealWorld+    , MutableQueue     , MutableStack     , MutableDeque     , IORef@@ -23,6 +24,10 @@     , MutablePushBack (..)     , MutablePopFront (..)     , MutablePopBack (..)+    , pushFrontRef+    , pushBackRef+    , popFrontRef+    , popBackRef     ) where  import           Control.Monad.Primitive@@ -33,7 +38,14 @@ 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 primtive.+    --+    -- Since 0.2.0     type MCState c  instance MutableContainer (IORef a) where@@ -43,22 +55,52 @@ 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)@@ -101,12 +143,22 @@     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@@ -123,8 +175,18 @@     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@@ -140,7 +202,13 @@     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))@@ -171,7 +239,13 @@     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@@ -198,7 +272,13 @@     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))@@ -229,7 +309,13 @@     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@@ -256,15 +342,32 @@     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/DList.hs view
@@ -13,8 +13,13 @@     (MutVar s (Maybe (Node s a))) -- previous     (MutVar s (Maybe (Node s a))) -- next +-- | A doubly-linked list.+--+-- Since 0.2.0 data DList s a = DList (MutVar s (Maybe (Node s a))) (MutVar s (Maybe (Node s a))) +-- |+-- Since 0.2.0 asDList :: DList s a -> DList s a asDList = id {-# INLINE asDList #-}
Data/Mutable/Deque.hs view
@@ -1,8 +1,11 @@ {-# LANGUAGE TypeFamilies #-} module Data.Mutable.Deque     ( Deque+    , UDeque     , asUDeque+    , SDeque     , asSDeque+    , BDeque     , asBDeque     , module Data.Mutable.Class     ) where@@ -19,15 +22,41 @@     {-# 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)) -asUDeque :: Deque U.MVector s a -> Deque U.MVector 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 -asSDeque :: Deque S.MVector s a -> Deque S.MVector s a+-- |+-- Since 0.2.0+asSDeque :: SDeque s a -> SDeque s a asSDeque = id -asBDeque :: Deque B.MVector s a -> Deque B.MVector s a+-- |+-- Since 0.2.0+asBDeque :: BDeque s a -> BDeque s a asBDeque = id  instance MutableContainer (Deque v s a) where
Data/Mutable/PRef.hs view
@@ -23,8 +23,12 @@ 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 #-}
Data/Mutable/SRef.hs view
@@ -17,8 +17,12 @@ import qualified Data.Vector.Storable.Mutable as VS  -- | A storable vector reference, supporting any monad.+--+-- Since 0.2.0 newtype SRef s a = SRef (VS.MVector s a) +-- |+-- Since 0.2.0 asSRef :: SRef s a -> SRef s a asSRef x = x {-# INLINE asSRef #-}
Data/Mutable/URef.hs view
@@ -17,8 +17,12 @@ 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 #-}
− Data/Mutable/VRef.hs
@@ -1,47 +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.VRef-    ( -- * Types-      VRef-    , IOVRef-      -- * Functions-    , asVRef-    , MutableRef (..)-    ) where--import           Control.Monad               (liftM)-import           Data.Mutable.Class-import qualified Data.Vector.Generic.Mutable as V-import qualified Data.Vector.Mutable         as VB---- | A boxed vector reference, supporting any monad.-newtype VRef s a = VRef (VB.MVector s a)--asVRef :: VRef s a -> VRef s a-asVRef x = x-{-# INLINE asVRef #-}---- | A boxed IO vector reference.-type IOVRef = VRef (PrimState IO)--instance MutableContainer (VRef s a) where-    type MCState (VRef s a) = s-instance MutableRef (VRef s a) where-    type RefElement (VRef s a) = a--    newRef = liftM VRef . V.replicate 1-    {-# INLINE newRef#-}--    readRef (VRef v) = V.unsafeRead v 0-    {-# INLINE readRef #-}--    writeRef (VRef v) = V.unsafeWrite v 0-    {-# INLINE writeRef #-}--    modifyRef (VRef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f-    {-# INLINE modifyRef #-}--    modifyRef' = modifyRef-    {-# INLINE modifyRef' #-}
README.md view
@@ -1,91 +1,214 @@-This package provides common mutable containers, such as double-ended queues-and doubly-linked lists. It is implemented as both an abstract set of type-classes, and concrete implementations.+One of Haskell's strengths is immutable data structures. These structures make+it easier to reason about code, simplify concurrency and parallelism, and in+some case can improve performance by allowing sharing. However, there are still+classes of problems where mutable data structures can both be more convenient,+and provide a performance boost. This library is meant to provide such+structures in a performant, well tested way. It also provides a simple+abstraction over such data structures via typeclasses. -Note that this library should be considered extremely experimental. That said,-it currently has 100% test coverage and has some performance tuning, though the-API is expected to change significantly.+Before anything else, let me provide the caveats of this package: +* Don't use this package unless you have a good reason to! Immutable data structures are a better approach most of the time!+* This code is intentionally *not* multithread safe. If you need something like a concurrent queue, there are many options on Hackage, from `Chan` to `TChan`, to [chaselev-deque](http://hackage.haskell.org/package/chaselev-deque).++We'll first talk about the general approach to APIs in this package. Next,+there are two main sets of abstractions provided, which we'll cover in the+following two sections, along with their concrete implementations. Finally,+we'll cover benchmarks.++## API structure++The API takes heavy advantage of the `PrimMonad` typeclass from the primitive+package. This allows our data structures to work in both `IO` and `ST` code.+Each data structure has an associated type, `MCState`, which gives the+primitive state for that structure. For example, in the case of `IORef`, that+state is `RealWorld`, whereas for `STRef s`, it would be `s`. This associated+type is quite similar to the `PrimState` associated type from primitive, and in+many type signatures you'll see an equality constraint along the lines of:++```haskell+PrimState m ~ MCState c+```++For those who are wondering, `MCState` stands for "mutable container state."++All actions are part of a typeclass, which allows for generic access to+different types of structures quite easily. In addition, we provide type hint+functions, such as `asIORef`, which can help specify types when using such+generic functions. For example, a common idiom might be:++```haskell+ioref <- fmap asIORef $ newRef someVal+```++Wherever possible, we stick to well accepted naming and type signature+standards. For example, note how closely `modifyRef` and `modifyRef'` match+`modifyIORef` and `modifyIORef'`.++## Single cell references++The base package provides both `IORef` and `STRef` as boxed mutable references,+for storing a single value. The primitive package also provides `MutVar`, which+generalizes over both of those and works for any `PrimMonad` instance. The+`MutableRef` typeclass in this package abstracts over all three of those. It+has two associated types: `MCState` for the primitive state, and `RefElement`+to specify what is contained by the reference.++You may be wondering: why not just take the reference as a type parameter? That+wouldn't allow us to have monomorphic reference types, which may be useful+under some circumstances. This is a similar motivation to how the+`mono-traversable` package works.++In addition to providing an abstraction over `IORef`, `STRef`, and `MutVar`,+this package provides four addition single-cell mutable references. `URef`,+`SRef`, and `BRef` all contain a 1-length mutable vector under the surface,+which is unboxed, storable, and boxed, respectively. The advantage of the first+two over boxed standard boxed references is that it can avoid a significant+amount of allocation overhead. See [the relevant Stack Overflow+discussion](http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes)+and the benchmarks below.++While `BRef` doesn't give this same advantage (since the values are still+boxed), it was trivial to include it along with the other two, and does+actually demonstrate a performance advantage. Unlike `URef` and `SRef`, there+is no restriction on the type of value it can store.++The finally reference type is `PRef`. Unlike the other three mentioned, it+doesn't use vectors at all, but instead drops down directly to a mutable+bytearray to store values. This means it has slightly less overhead (no need to+store the size of the vector), but also restricts the types of things that can+be stored (only instances of `Prim`).++You should benchmark your program to determine the most efficient reference+type, but generally speaking `PRef` will be most performant, followed by `URef`+and `SRef`, and finally `BRef`.++## Collections++Collections allow you to push and pop values to the beginning and end of+themselves. Since different data structures allow different operations, each+operation goes into its own typeclass, appropriately named `MutablePushFront`,+`MutablePushBack`, `MutablePopFront`, and `MutablePopBack`. There is also a+parent typeclass `MutableCollection` which provides:++1. The `CollElement` associated type to indicate what kinds of values are in the collection.+2. The `newColl` function to create a new, empty collection.++The `mono-traversable` package provides a typeclass `IsSequence` which+abstracts over sequence-like things. In particular, it provides operations for+`cons`, `snoc`, `uncons`, and `unsnoc`. Using this abstraction, we can provide+an instance for all of the typeclasses listed above for any mutable reference+containing an instance of `IsSequence`, e.g. `IORef [Int]` or `BRef s (Seq+Double)`.++Note that the performance of some of these combinations is *terrible*. In+particular, `pushBack` or `popBack` on a list requires traversing the entire+list, and any push operations on a `Vector` requires copying the entire+contents of the vector. Caveat emptor! If you *must* use one of these+structures, it's highly recommended to use `Seq`, which gives the best overall+performance.++However, in addition to these instances, this package also provides two+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.++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,+and see the benchmark results below.+ ## Benchmark results -The following benchmarks were performed on January 4, 2015, against version 0.1.1.0.+The following benchmarks were performed on January 7, 2015, against version 0.2.0. -### Deque benchmark+### Ref benchmark  ```-benchmarking IORef [Int]-time                 8.355 ms   (8.350 ms .. 8.362 ms)+benchmarking IORef+time                 4.322 μs   (4.322 μs .. 4.323 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 8.353 ms   (8.348 ms .. 8.358 ms)-std dev              15.89 μs   (11.83 μs .. 23.66 μs)+mean                 4.322 μs   (4.322 μs .. 4.323 μs)+std dev              1.401 ns   (1.114 ns .. 1.802 ns) -benchmarking IORef (Seq Int)-time                 140.5 μs   (140.4 μs .. 140.6 μs)+benchmarking STRef+time                 4.484 μs   (4.484 μs .. 4.485 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 140.5 μs   (140.4 μs .. 140.6 μs)-std dev              313.3 ns   (239.0 ns .. 404.1 ns)+mean                 4.484 μs   (4.484 μs .. 4.484 μs)+std dev              941.0 ps   (748.5 ps .. 1.164 ns) -benchmarking UDeque-time                 101.2 μs   (101.2 μs .. 101.2 μs)+benchmarking MutVar+time                 4.482 μs   (4.482 μs .. 4.483 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 101.2 μs   (101.2 μs .. 101.2 μs)-std dev              16.11 ns   (13.38 ns .. 21.34 ns)+mean                 4.482 μs   (4.482 μs .. 4.483 μs)+std dev              843.2 ps   (707.9 ps .. 1.003 ns) -benchmarking SDeque-time                 97.86 μs   (97.85 μs .. 97.88 μs)+benchmarking URef+time                 2.020 μs   (2.019 μs .. 2.020 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 97.88 μs   (97.87 μs .. 97.89 μs)-std dev              38.61 ns   (31.34 ns .. 50.52 ns)+mean                 2.020 μs   (2.019 μs .. 2.020 μs)+std dev              955.2 ps   (592.2 ps .. 1.421 ns) -benchmarking BDeque-time                 113.7 μs   (113.7 μs .. 113.7 μs)+benchmarking PRef+time                 2.015 μs   (2.014 μs .. 2.015 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 113.7 μs   (113.7 μs .. 113.7 μs)-std dev              29.87 ns   (22.98 ns .. 39.57 ns)+mean                 2.014 μs   (2.014 μs .. 2.015 μs)+std dev              901.3 ps   (562.8 ps .. 1.238 ns) -benchmarking DList-time                 160.8 μs   (160.7 μs .. 160.9 μs)+benchmarking SRef+time                 2.231 μs   (2.230 μs .. 2.232 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 160.9 μs   (160.8 μs .. 161.0 μs)-std dev              331.8 ns   (277.0 ns .. 401.2 ns)+mean                 2.231 μs   (2.230 μs .. 2.231 μs)+std dev              1.938 ns   (1.589 ns .. 2.395 ns)++benchmarking BRef+time                 4.279 μs   (4.279 μs .. 4.279 μs)+                     1.000 R²   (1.000 R² .. 1.000 R²)+mean                 4.279 μs   (4.279 μs .. 4.279 μs)+std dev              1.281 ns   (1.016 ns .. 1.653 ns) ``` -### Ref benchmark+### Deque benchmark  ```-benchmarking IORef-time                 4.321 μs   (4.320 μs .. 4.322 μs)+time                 8.371 ms   (8.362 ms .. 8.382 ms)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 4.322 μs   (4.321 μs .. 4.323 μs)-std dev              4.840 ns   (3.746 ns .. 6.242 ns)+mean                 8.386 ms   (8.378 ms .. 8.398 ms)+std dev              29.25 μs   (20.73 μs .. 42.47 μs) -benchmarking STRef-time                 4.481 μs   (4.480 μs .. 4.481 μs)+benchmarking IORef (Seq Int)+time                 142.9 μs   (142.7 μs .. 143.1 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 4.481 μs   (4.481 μs .. 4.481 μs)-std dev              1.127 ns   (805.5 ps .. 1.758 ns)+mean                 142.7 μs   (142.6 μs .. 142.9 μs)+std dev              542.8 ns   (426.5 ns .. 697.0 ns) -benchmarking MutVar-time                 4.478 μs   (4.476 μs .. 4.481 μs)+benchmarking UDeque+time                 107.5 μs   (107.4 μs .. 107.6 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 4.479 μs   (4.477 μs .. 4.481 μs)-std dev              6.500 ns   (5.199 ns .. 8.246 ns)+mean                 107.5 μs   (107.4 μs .. 107.6 μs)+std dev              227.4 ns   (171.8 ns .. 297.8 ns) -benchmarking URef-time                 2.019 μs   (2.019 μs .. 2.020 μs)+benchmarking SDeque+time                 97.82 μs   (97.76 μs .. 97.89 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 2.020 μs   (2.019 μs .. 2.020 μs)-std dev              471.2 ps   (371.2 ps .. 671.9 ps)+mean                 97.82 μs   (97.78 μs .. 97.89 μs)+std dev              169.5 ns   (110.6 ns .. 274.5 ns) -benchmarking SRef-time                 2.175 μs   (2.174 μs .. 2.176 μs)+benchmarking BDeque+time                 113.5 μs   (113.4 μs .. 113.6 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 2.172 μs   (2.170 μs .. 2.173 μs)-std dev              5.106 ns   (4.054 ns .. 6.660 ns)+mean                 113.6 μs   (113.5 μs .. 113.7 μs)+std dev              300.4 ns   (221.8 ns .. 424.1 ns) -benchmarking VRef-time                 4.280 μs   (4.279 μs .. 4.280 μs)+benchmarking DList+time                 156.5 μs   (156.3 μs .. 156.6 μs)                      1.000 R²   (1.000 R² .. 1.000 R²)-mean                 4.281 μs   (4.280 μs .. 4.283 μs)-std dev              4.552 ns   (1.911 ns .. 8.892 ns)+mean                 156.4 μs   (156.3 μs .. 156.6 μs)+std dev              389.5 ns   (318.3 ns .. 502.8 ns) ```++## Test coverage++As of version 0.2.0, this package has 100% test coverage. If you look at the+report yourself, you'll see some uncovered code; it's just the automatically+derived `Show` instance needed for QuickCheck inside the test suite itself.
bench/deque.hs view
@@ -2,9 +2,7 @@ {-# LANGUAGE TypeFamilies    #-} import Control.Monad import Criterion.Main-import Data.Mutable.Class-import Data.Mutable.Deque-import Data.Mutable.DList+import Data.Mutable import Data.Sequence      (Seq)  test :: (MCState c ~ PrimState IO, CollElement c ~ Int, MutableDeque c)
bench/ref.hs view
@@ -1,11 +1,7 @@ {-# LANGUAGE TypeFamilies #-} import Control.Monad import Criterion.Main-import Data.Mutable.Class-import Data.Mutable.SRef-import Data.Mutable.URef-import Data.Mutable.PRef-import Data.Mutable.VRef+import Data.Mutable  test :: (MCState c ~ PrimState IO, RefElement c ~ Int, MutableRef c)      => String@@ -30,5 +26,5 @@     , test "URef" asURef     , test "PRef" asPRef     , test "SRef" asSRef-    , test "VRef" asVRef+    , test "BRef" asBRef     ]
mutable-containers.cabal view
@@ -1,5 +1,5 @@ name:                mutable-containers-version:             0.1.2.0+version:             0.2.0 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/fpco/mutable-containers@@ -13,11 +13,12 @@ cabal-version:       >=1.10  library-  exposed-modules:     Data.Mutable.SRef+  exposed-modules:     Data.Mutable+  other-modules:       Data.Mutable.SRef                        Data.Mutable.Class                        Data.Mutable.URef                        Data.Mutable.PRef-                       Data.Mutable.VRef+                       Data.Mutable.BRef                        Data.Mutable.DList                        Data.Mutable.Deque   build-depends:       base >= 4.7 && < 5@@ -27,6 +28,7 @@                      , mono-traversable                      , ghc-prim   default-language:    Haskell2010+  ghc-options:         -O2  test-suite test   type:                exitcode-stdio-1.0
test/Spec.hs view
@@ -1,11 +1,6 @@ {-# LANGUAGE TypeFamilies #-} import Control.Monad             (forM_)-import Data.Mutable.Deque-import Data.Mutable.DList-import Data.Mutable.SRef-import Data.Mutable.URef-import Data.Mutable.PRef-import Data.Mutable.VRef+import Data.Mutable import Data.Sequence             (Seq) import Data.Vector               (Vector) import Test.Hspec@@ -81,6 +76,7 @@         test "DList" asDList         test "MutVar Seq" (id :: MutVar (PrimState IO) (Seq Int) -> MutVar (PrimState IO) (Seq Int))         test "STRef Vector" (id :: STRef (PrimState IO) (Vector Int) -> STRef (PrimState IO) (Vector Int))+        test "BRef Vector" (id :: BRef (PrimState IO) (Vector Int) -> BRef (PrimState IO) (Vector Int))     describe "Ref" $ do         let test name forceType atomic atomic' = prop name $ \start actions -> do                 base <- fmap asIORef $ newRef start@@ -114,7 +110,7 @@         test "URef" asURef modifyRefHelper modifyRefHelper'         test "PRef" asPRef modifyRefHelper modifyRefHelper'         test "SRef" asSRef modifyRefHelper modifyRefHelper'-        test "VRef" asVRef modifyRefHelper modifyRefHelper'+        test "BRef" asBRef modifyRefHelper modifyRefHelper'         test "STRef" asSTRef modifyRefHelper modifyRefHelper'         test "MutVar" asMutVar atomicModifyRef atomicModifyRef'