Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 93 additions & 95 deletions vector/src/Data/Vector/Generic/Mutable.hs

Large diffs are not rendered by default.

6 changes: 2 additions & 4 deletions vector/src/Data/Vector/Generic/Mutable/Base.hs
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,8 +11,7 @@
-- Stability : experimental
-- Portability : non-portable
--
-- Class of mutable vectors
--
-- Class of mutable vectors.

module Data.Vector.Generic.Mutable.Base (
MVector(..)
Expand All@@ -24,8 +23,7 @@ import Control.Monad.ST
#define NOT_VECTOR_MODULE
#include "vector.h"

-- | Class of mutable vectors parametrised with a primitive state token.
--
-- | Class of mutable vectors parameterised with a primitive state token.
class MVector v a where
-- | Length of the mutable vector. This method should not be
-- called directly, use 'length' instead.
Expand Down
103 changes: 55 additions & 48 deletions vector/src/Data/Vector/Mutable.hs
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,7 +15,6 @@
-- Portability : non-portable
--
-- Mutable boxed vectors.
--

module Data.Vector.Mutable (
-- * Mutable boxed vectors
Expand DownExpand Up@@ -220,7 +219,7 @@ length :: MVector s a -> Int
{-# INLINE length #-}
length = G.length

-- | Check whether the vector is empty
-- | Check whether the vector is empty.
null :: MVector s a -> Bool
{-# INLINE null #-}
null = G.null
Expand All@@ -237,32 +236,37 @@ slice :: Int -- ^ @i@ starting index
{-# INLINE slice #-}
slice = G.slice

-- | Take @n@ first elements of the mutable vector without making a
-- copy. For negative @n@ empty vector is returned. If @n@ is larger
-- than vector's length empty vector is returned,
-- | Take the @n@ first elements of the mutable vector without making a
-- copy. For negative @n@, the empty vector is returned. If @n@ is larger
-- than the vector's length, the vector is returned unchanged.
take :: Int -> MVector s a -> MVector s a
{-# INLINE take #-}
take = G.take

-- | Drop @n@ first element of the mutable vector without making a
-- copy. For negative @n@vector is returned unchanged and if @n@ is
-- larger than vector's length empty vector is returned.
-- | Drop the @n@ first element of the mutable vector without making a
-- copy. For negative @n@, the vector is returned unchanged. If @n@ is
-- larger than the vector's length, the empty vector is returned.
drop :: Int -> MVector s a -> MVector s a
{-# INLINE drop #-}
drop = G.drop

{-# INLINE splitAt #-}
-- | /O(1)/ Split the mutable vector into the first @n@ elements
-- and the remainder, without copying.
--
-- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@,
-- but slightly more efficient.
splitAt :: Int -> MVector s a -> (MVector s a, MVector s a)
{-# INLINE splitAt #-}
splitAt = G.splitAt

-- | Drop last element of the mutable vector without making a copy. If
-- vector is empty exception is thrown.
-- | Drop the last element of the mutable vector without making a copy.
-- If the vector is empty, an exception is thrown.
init :: MVector s a -> MVector s a
{-# INLINE init #-}
init = G.init

-- | Drop first element of the mutable vector without making a copy. If
-- vector is empty exception is thrown.
-- | Drop the first element of the mutable vector without making a copy.
-- If the vector is empty, an exception is thrown.
tail :: MVector s a -> MVector s a
{-# INLINE tail #-}
tail = G.tail
Expand All@@ -276,24 +280,24 @@ unsafeSlice :: Int -- ^ starting index
{-# INLINE unsafeSlice #-}
unsafeSlice = G.unsafeSlice

-- | Unsafe variant of 'take'. If called with out of range @n@ it will
-- simply create invalid slice that likely violate memory safety
-- | Unsafe variant of 'take'. If @n@ is out of range, it will
-- simply create an invalid slice that likely violate memory safety.
unsafeTake :: Int -> MVector s a -> MVector s a
{-# INLINE unsafeTake #-}
unsafeTake = G.unsafeTake

-- | Unsafe variant of 'drop'. If called with out of range @n@ it will
-- simply create invalid slice that likely violate memory safety
-- | Unsafe variant of 'drop'. If @n@ is out of range, it will
-- simply create an invalid slice that likely violate memory safety.
unsafeDrop :: Int -> MVector s a -> MVector s a
{-# INLINE unsafeDrop #-}
unsafeDrop = G.unsafeDrop

-- | Same as 'init' but doesn't do range checks.
-- | Same as 'init', but doesn't do range checks.
unsafeInit :: MVector s a -> MVector s a
{-# INLINE unsafeInit #-}
unsafeInit = G.unsafeInit

-- | Same as 'tail' but doesn't do range checks.
-- | Same as 'tail', but doesn't do range checks.
unsafeTail :: MVector s a -> MVector s a
{-# INLINE unsafeTail #-}
unsafeTail = G.unsafeTail
Expand All@@ -315,7 +319,7 @@ new :: PrimMonad m => Int -> m (MVector (PrimState m) a)
new = G.new

-- | Create a mutable vector of the given length. The vector elements
-- are set to bottom so accessing them will cause an exception.
-- are set to bottom, so accessing them will cause an exception.
--
-- @since 0.5
unsafeNew :: PrimMonad m => Int -> m (MVector (PrimState m) a)
Expand All@@ -336,6 +340,7 @@ replicateM = G.replicateM

-- | /O(n)/ Create a mutable vector of the given length (0 if the length is negative)
-- and fill it with the results of applying the function to each index.
-- Iteration starts at index 0.
--
-- @since 0.12.3.0
generate :: (PrimMonad m) => Int -> (Int -> a) -> m (MVector (PrimState m) a)
Expand All@@ -360,14 +365,14 @@ clone = G.clone
-- -------

-- | Grow a boxed vector by the given number of elements. The number must be
-- non-negative. Same semantics as in `G.grow` for generic vector. It differs
-- non-negative. This has the same semantics as 'G.grow' for generic vectors. It differs
-- from @grow@ functions for unpacked vectors, however, in that only pointers to
-- values are copied over, therefore values themselves will be shared between
-- values are copied over, therefore the values themselves will be shared between the
-- two vectors. This is an important distinction to know about during memory
-- usage analysis and in case when values themselves are of a mutable type, eg.
-- `Data.IORef.IORef` or another mutable vector.
-- usage analysis and in case the values themselves are of a mutable type, e.g.
-- 'Data.IORef.IORef' or another mutable vector.
--
-- ====__Examples__
-- ====__Examples__
--
-- >>> import qualified Data.Vector as V
-- >>> import qualified Data.Vector.Mutable as MV
Expand All@@ -394,24 +399,24 @@ clone = G.clone
--
-- @since 0.5
grow :: PrimMonad m
=> MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
=> MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
{-# INLINE grow #-}
grow = G.grow

-- | Grow a vector by the given number of elements. The number must be non-negative but
-- this is not checked. Same semantics as in `G.unsafeGrow` for generic vector.
-- | Grow a vector by the given number of elements. The number must be non-negative, but
-- this is not checked. This has the same semantics as 'G.unsafeGrow' for generic vectors.
--
-- @since 0.5
unsafeGrow :: PrimMonad m
=> MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
=> MVector (PrimState m) a -> Int -> m (MVector (PrimState m) a)
{-# INLINE unsafeGrow #-}
unsafeGrow = G.unsafeGrow

-- Restricting memory usage
-- ------------------------

-- | Reset all elements of the vector to some undefined value, clearing all
-- references to external objects. This is usually a noop for unboxed vectors.
-- references to external objects.
clear :: PrimMonad m => MVector (PrimState m) a -> m ()
{-# INLINE clear #-}
clear = G.clear
Expand DownExpand Up@@ -502,7 +507,7 @@ copy :: PrimMonad m => MVector (PrimState m) a -- ^ target
copy = G.copy

-- | Copy a vector. The two vectors must have the same length and may not
-- overlap. This is not checked.
-- overlap, but this is not checked.
unsafeCopy :: PrimMonad m => MVector (PrimState m) a -- ^ target
-> MVector (PrimState m) a -- ^ source
-> m ()
Expand DownExpand Up@@ -535,13 +540,15 @@ unsafeMove :: PrimMonad m => MVector (PrimState m) a -- ^ target
{-# INLINE unsafeMove #-}
unsafeMove = G.unsafeMove

-- | Compute the next (lexicographically) permutation of given vector in-place.
-- Returns False when input is the last permutation
nextPermutation :: (PrimMonad m,Ord e) => MVector (PrimState m) e -> m Bool
-- Modifying vectors
-- -----------------

-- | Compute the (lexicographically) next permutation of the given vector in-place.
-- Returns False when the input is the last permutation.
nextPermutation :: (PrimMonad m, Ord e) => MVector (PrimState m) e -> m Bool
{-# INLINE nextPermutation #-}
nextPermutation = G.nextPermutation


-- Folds
-- -----

Expand All@@ -560,15 +567,15 @@ imapM_ :: (PrimMonad m) => (Int -> a -> m b) -> MVector (PrimState m) a -> m ()
imapM_ = G.imapM_

-- | /O(n)/ Apply the monadic action to every element of the vector,
-- discarding the results. It's same as the @flip mapM_@.
-- discarding the results. It's the same as @flip mapM_@.
--
-- @since 0.12.3.0
forM_ :: (PrimMonad m) => MVector (PrimState m) a -> (a -> m b) -> m ()
{-# INLINE forM_ #-}
forM_ = G.forM_

-- | /O(n)/ Apply the monadic action to every element of the vector
-- and its index, discarding the results. It's same as the @flip imapM_@.
-- and its index, discarding the results. It's the same as @flip imapM_@.
--
-- @since 0.12.3.0
iforM_ :: (PrimMonad m) => MVector (PrimState m) a -> (Int -> a -> m b) -> m ()
Expand All@@ -589,14 +596,14 @@ foldl' :: (PrimMonad m) => (b -> a -> b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE foldl' #-}
foldl' = G.foldl'

-- | /O(n)/ Pure left fold (function applied to each element and its index).
-- | /O(n)/ Pure left fold using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldl :: (PrimMonad m) => (b -> Int -> a -> b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE ifoldl #-}
ifoldl = G.ifoldl

-- | /O(n)/ Pure left fold with strict accumulator (function applied to each element and its index).
-- | /O(n)/ Pure left fold with strict accumulator using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldl' :: (PrimMonad m) => (b -> Int -> a -> b) -> b -> MVector (PrimState m) a -> m b
Expand All@@ -617,15 +624,15 @@ foldr' :: (PrimMonad m) => (a -> b -> b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE foldr' #-}
foldr' = G.foldr'

-- | /O(n)/ Pure right fold (function applied to each element and its index).
-- | /O(n)/ Pure right fold using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldr :: (PrimMonad m) => (Int -> a -> b -> b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE ifoldr #-}
ifoldr = G.ifoldr

-- | /O(n)/ Pure right fold with strict accumulator (function applied
-- to each element and its index).
-- | /O(n)/ Pure right fold with strict accumulator using a function applied
-- to each element and its index.
--
-- @since 0.12.3.0
ifoldr' :: (PrimMonad m) => (Int -> a -> b -> b) -> b -> MVector (PrimState m) a -> m b
Expand All@@ -646,14 +653,14 @@ foldM' :: (PrimMonad m) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m
{-# INLINE foldM' #-}
foldM' = G.foldM'

-- | /O(n)/ Monadic fold (action applied to each element and its index).
-- | /O(n)/ Monadic fold using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldM :: (PrimMonad m) => (b -> Int -> a -> m b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE ifoldM #-}
ifoldM = G.ifoldM

-- | /O(n)/ Monadic fold with strict accumulator (action applied to each element and its index).
-- | /O(n)/ Monadic fold with strict accumulator using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldM' :: (PrimMonad m) => (b -> Int -> a -> m b) -> b -> MVector (PrimState m) a -> m b
Expand All@@ -674,15 +681,15 @@ foldrM' :: (PrimMonad m) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m
{-# INLINE foldrM' #-}
foldrM' = G.foldrM'

-- | /O(n)/ Monadic right fold (action applied to each element and its index).
-- | /O(n)/ Monadic right fold using a function applied to each element and its index.
--
-- @since 0.12.3.0
ifoldrM :: (PrimMonad m) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
{-# INLINE ifoldrM #-}
ifoldrM = G.ifoldrM

-- | /O(n)/ Monadic right fold with strict accumulator (action applied
-- to each element and its index).
-- | /O(n)/ Monadic right fold with strict accumulator using a function applied
-- to each element and its index.
--
-- @since 0.12.3.0
ifoldrM' :: (PrimMonad m) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
Expand All@@ -699,7 +706,7 @@ fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (P
{-# INLINE fromMutableArray #-}
fromMutableArray marr =
let size = sizeofMutableArray marr
in MVector 0 size `liftM` cloneMutableArray marr 0 size
in MVector 0 size `liftM` cloneMutableArray marr 0 size

-- | /O(n)/ Make a copy of a mutable vector into a new mutable array.
--
Expand Down
10 changes: 3 additions & 7 deletions vector/src/Data/Vector/Primitive.hs
Original file line numberDiff line numberDiff line change
Expand Up@@ -202,13 +202,9 @@ type role Vector nominal
-- underlying pointer and does not modify the elements.
--
-- This is marginally safer than 'unsafeCast', since this function imposes an
-- extra 'Coercible' constraint. This function is still not safe, however,
-- since it cannot guarantee that the two types have memory-compatible
-- 'Prim' instances.
--
Comment thread
konsumlamm marked this conversation as resolved.
-- Note that this function is unsafe. The @Coercible@ constraint guarantees
-- that the element types are representationally equal. It however cannot
-- guarantee that their respective 'Prim' are compatible.
-- extra 'Coercible' constraint. The constraint guarantees that the element types
-- are representationally equal. It however cannot guarantee
-- that their respective 'Prim' instances are compatible.
unsafeCoerceVector :: Coercible a b => Vector a -> Vector b
unsafeCoerceVector = unsafeCoerce

Expand Down
Loading