mutable-containers 0.1.2.0 → 0.2.0
raw patch · 15 files changed
+476/−126 lines, 15 files
Files
- ChangeLog.md +4/−0
- Data/Mutable.hs +58/−0
- Data/Mutable/BRef.hs +71/−0
- Data/Mutable/Class.hs +103/−0
- Data/Mutable/DList.hs +5/−0
- Data/Mutable/Deque.hs +32/−3
- Data/Mutable/PRef.hs +4/−0
- Data/Mutable/SRef.hs +4/−0
- Data/Mutable/URef.hs +4/−0
- Data/Mutable/VRef.hs +0/−47
- README.md +180/−57
- bench/deque.hs +1/−3
- bench/ref.hs +2/−6
- mutable-containers.cabal +5/−3
- test/Spec.hs +3/−7
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'