X-Git-Url: http://git.haskell.org/darcs-mirrors/vector.git/blobdiff_plain/f31120ef85e2d5728e11375b803251065462a088..4b08bfcbcf5c3b4f45804bac6050c355fceb7ca2:/Data/Vector/MVector.hs
diff --git a/Data/Vector/MVector.hs b/Data/Vector/MVector.hs
index 32f358f..d519e61 100644
--- a/Data/Vector/MVector.hs
+++ b/Data/Vector/MVector.hs
@@ -1,4 +1,16 @@
{-# LANGUAGE MultiParamTypeClasses #-}
+-- |
+-- Module : Data.Vector.MVector
+-- Copyright : (c) Roman Leshchinskiy 2008
+-- License : BSD-style
+--
+-- Maintainer : rl@cse.unsw.edu.au
+-- Stability : experimental
+-- Portability : non-portable
+--
+-- Generic interface to mutable vectors
+--
+
module Data.Vector.MVector (
MVector(..),
@@ -21,20 +33,55 @@ import Prelude hiding ( length, read )
gROWTH_FACTOR :: Double
gROWTH_FACTOR = 1.5
+-- | Class of mutable vectors. The type @m@ is the monad in which the mutable
+-- vector can be transformed and @a@ is the type of elements. A vector does
+-- not necessarily have to be generic in either of them (indeed, it would be
+-- unusual for a vector to be generic in the monad). Use GADTs if this is the
+-- case. For instance, regular boxed vectors are defined as
+--
+-- > data Vector m a where
+-- > Vector :: !Int -> !Int -> MutableArray# s a -> Vector (ST s) a
+--
+-- This is a bit clumsy but I haven't been able to find a better solution. In
+-- particular, using a type function for the monad triggers
+-- and is probably less
+-- portable.
+--
class Monad m => MVector v m a where
+ -- | Length of the mutable vector
length :: v m a -> Int
- unsafeSlice :: v m a -> Int -> Int -> v m a
+ -- | Yield a part of the mutable vector without copying it. No range checks!
+ unsafeSlice :: v m a -> Int -- ^ starting index
+ -> Int -- ^ length of the slice
+ -> v m a
+
+ -- | Create a mutable vector of the given length. Length is not checked!
unsafeNew :: Int -> m (v m a)
+
+ -- | Create a mutable vector of the given length and fill it with an
+ -- initial value. Length is not checked!
unsafeNewWith :: Int -> a -> m (v m a)
+ -- | Yield the element at the given position. Index is not checked!
unsafeRead :: v m a -> Int -> m a
+
+ -- | Replace the element at the given position. Index is not checked!
unsafeWrite :: v m a -> Int -> a -> m ()
+ -- | Write the value at each position.
set :: v m a -> a -> m ()
- unsafeCopy :: v m a -> v m a -> m ()
+
+ -- | Copy a vector. The two vectors may not overlap. This is not checked!
+ unsafeCopy :: v m a -- ^ target
+ -> v m a -- ^ source
+ -> m ()
+
+ -- | Grow a vector by the given number of elements. The length is not
+ -- checked!
unsafeGrow :: v m a -> Int -> m (v m a)
+ -- Check whether two vectors overlap.
overlaps :: v m a -> v m a -> Bool
{-# INLINE unsafeNewWith #-}
@@ -72,42 +119,59 @@ class Monad m => MVector v m a where
where
n = length v
+-- | Test whether the index is valid for the vector
inBounds :: MVector v m a => v m a -> Int -> Bool
{-# INLINE inBounds #-}
inBounds v i = i >= 0 && i < length v
+-- | Yield a part of the mutable vector without copying it. Safer version of
+-- 'unsafeSlice'.
slice :: MVector v m a => v m a -> Int -> Int -> v m a
{-# INLINE slice #-}
slice v i n = assert (i >=0 && n >= 0 && i+n <= length v)
$ unsafeSlice v i n
+-- | Create a mutable vector of the given length. Safer version of
+-- 'unsafeNew'.
new :: MVector v m a => Int -> m (v m a)
{-# INLINE new #-}
new n = assert (n >= 0) $ unsafeNew n
+-- | Create a mutable vector of the given length and fill it with an
+-- initial value. Safer version of 'unsafeNewWith'.
newWith :: MVector v m a => Int -> a -> m (v m a)
{-# INLINE newWith #-}
newWith n x = assert (n >= 0) $ unsafeNewWith n x
+-- | Yield the element at the given position. Safer version of 'unsafeRead'.
read :: MVector v m a => v m a -> Int -> m a
{-# INLINE read #-}
read v i = assert (inBounds v i) $ unsafeRead v i
+-- | Replace the element at the given position. Safer version of
+-- 'unsafeWrite'.
write :: MVector v m a => v m a -> Int -> a -> m ()
{-# INLINE write #-}
write v i x = assert (inBounds v i) $ unsafeWrite v i x
+-- | Copy a vector. The two vectors may not overlap. Safer version of
+-- 'unsafeCopy'.
copy :: MVector v m a => v m a -> v m a -> m ()
{-# INLINE copy #-}
copy dst src = assert (not (dst `overlaps` src) && length dst == length src)
$ unsafeCopy dst src
+-- | Grow a vector by the given number of elements. Safer version of
+-- 'unsafeGrow'.
grow :: MVector v m a => v m a -> Int -> m (v m a)
{-# INLINE grow #-}
grow v by = assert (by >= 0)
$ unsafeGrow v by
+-- | Create a new mutable vector and fill it with elements from the 'Stream'.
+-- The vector will grow logarithmically if the 'Size' hint of the 'Stream' is
+-- inexact.
unstream :: MVector v m a => Stream a -> m (v m a)
{-# INLINE unstream #-}
unstream s = case upperBound (Stream.size s) of