{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RoleAnnotations #-} {-# LANGUAGE TypeFamilies #-} -- | -- Module : Data.Vector.Mutable -- Copyright : (c) Roman Leshchinskiy 2008-2010 -- Alexey Kuleshevich 2020-2022 -- Aleksey Khudyakov 2020-2022 -- Andrew Lelechenko 2020-2022 -- License : BSD-style -- -- Maintainer : Haskell Libraries Team -- Stability : experimental -- Portability : non-portable -- -- Mutable boxed vectors. module Data.Vector.Mutable ( -- * Mutable boxed vectors MVector(MVector), IOVector, STVector, -- * Accessors -- ** Length information length, null, -- ** Extracting subvectors slice, init, tail, take, drop, splitAt, unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop, -- ** Overlapping overlaps, -- * Construction -- ** Initialisation new, unsafeNew, replicate, replicateM, generate, generateM, clone, -- ** Growing grow, unsafeGrow, -- ** Restricting memory usage clear, -- * Accessing individual elements read, readMaybe, write, modify, modifyM, swap, exchange, unsafeRead, unsafeWrite, unsafeModify, unsafeModifyM, unsafeSwap, unsafeExchange, -- * Folds mapM_, imapM_, forM_, iforM_, foldl, foldl', foldM, foldM', foldr, foldr', foldrM, foldrM', ifoldl, ifoldl', ifoldM, ifoldM', ifoldr, ifoldr', ifoldrM, ifoldrM', -- * Modifying vectors nextPermutation, -- ** Filling and copying set, copy, move, unsafeCopy, unsafeMove, -- ** Arrays fromMutableArray, toMutableArray, -- * Re-exports PrimMonad, PrimState, RealWorld ) where import Control.Monad (when, liftM) import qualified Data.Vector.Generic.Mutable as G import Data.Vector.Internal.Check import Data.Primitive.Array import Control.Monad.Primitive import Prelude hiding ( length, null, replicate, reverse, read, take, drop, splitAt, init, tail, foldr, foldl, mapM_ ) import Data.Typeable ( Typeable ) #include "vector.h" type role MVector nominal representational -- | Mutable boxed vectors keyed on the monad they live in ('IO' or @'ST' s@). data MVector s a = MVector { _offset :: {-# UNPACK #-} !Int -- ^ Offset in underlying array , _size :: {-# UNPACK #-} !Int -- ^ Size of slice , _array :: {-# UNPACK #-} !(MutableArray s a) -- ^ Underlying array } deriving ( Typeable ) type IOVector = MVector RealWorld type STVector s = MVector s -- NOTE: This seems unsafe, see http://trac.haskell.org/vector/ticket/54 {- instance NFData a => NFData (MVector s a) where rnf (MVector i n arr) = unsafeInlineST $ force i where force !ix | ix < n = do x <- readArray arr ix rnf x `seq` force (ix+1) | otherwise = return () -} instance G.MVector MVector a where {-# INLINE basicLength #-} basicLength (MVector _ n _) = n {-# INLINE basicUnsafeSlice #-} basicUnsafeSlice j m (MVector i _ arr) = MVector (i+j) m arr {-# INLINE basicOverlaps #-} basicOverlaps (MVector i m arr1) (MVector j n arr2) = sameMutableArray arr1 arr2 && (between i j (j+n) || between j i (i+m)) where between x y z = x >= y && x < z {-# INLINE basicUnsafeNew #-} basicUnsafeNew n = do arr <- newArray n uninitialised return (MVector 0 n arr) {-# INLINE basicInitialize #-} -- initialization is unnecessary for boxed vectors basicInitialize _ = return () {-# INLINE basicUnsafeReplicate #-} basicUnsafeReplicate n x = do arr <- newArray n x return (MVector 0 n arr) {-# INLINE basicUnsafeRead #-} basicUnsafeRead (MVector i _ arr) j = readArray arr (i+j) {-# INLINE basicUnsafeWrite #-} basicUnsafeWrite (MVector i _ arr) j x = writeArray arr (i+j) x {-# INLINE basicUnsafeCopy #-} basicUnsafeCopy (MVector i n dst) (MVector j _ src) = copyMutableArray dst i src j n basicUnsafeMove dst@(MVector iDst n arrDst) src@(MVector iSrc _ arrSrc) = case n of 0 -> return () 1 -> readArray arrSrc iSrc >>= writeArray arrDst iDst 2 -> do x <- readArray arrSrc iSrc y <- readArray arrSrc (iSrc + 1) writeArray arrDst iDst x writeArray arrDst (iDst + 1) y _ | overlaps dst src -> case compare iDst iSrc of LT -> moveBackwards arrDst iDst iSrc n EQ -> return () GT | (iDst - iSrc) * 2 < n -> moveForwardsLargeOverlap arrDst iDst iSrc n | otherwise -> moveForwardsSmallOverlap arrDst iDst iSrc n | otherwise -> G.basicUnsafeCopy dst src {-# INLINE basicClear #-} basicClear v = G.set v uninitialised {-# INLINE moveBackwards #-} moveBackwards :: PrimMonad m => MutableArray (PrimState m) a -> Int -> Int -> Int -> m () moveBackwards !arr !dstOff !srcOff !len = check Internal "not a backwards move" (dstOff < srcOff) $ loopM len $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) {-# INLINE moveForwardsSmallOverlap #-} -- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is small. moveForwardsSmallOverlap :: PrimMonad m => MutableArray (PrimState m) a -> Int -> Int -> Int -> m () moveForwardsSmallOverlap !arr !dstOff !srcOff !len = check Internal "not a forward move" (dstOff > srcOff) $ do tmp <- newArray overlap uninitialised loopM overlap $ \ i -> readArray arr (dstOff + i) >>= writeArray tmp i loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray arr (dstOff + i) loopM overlap $ \ i -> readArray tmp i >>= writeArray arr (dstOff + nonOverlap + i) where nonOverlap = dstOff - srcOff; overlap = len - nonOverlap -- Performs a move when dstOff > srcOff, optimized for when the overlap of the intervals is large. moveForwardsLargeOverlap :: PrimMonad m => MutableArray (PrimState m) a -> Int -> Int -> Int -> m () moveForwardsLargeOverlap !arr !dstOff !srcOff !len = check Internal "not a forward move" (dstOff > srcOff) $ do queue <- newArray nonOverlap uninitialised loopM nonOverlap $ \ i -> readArray arr (srcOff + i) >>= writeArray queue i let mov !i !qTop = when (i < dstOff + len) $ do x <- readArray arr i y <- readArray queue qTop writeArray arr i y writeArray queue qTop x mov (i+1) (if qTop + 1 >= nonOverlap then 0 else qTop + 1) mov dstOff 0 where nonOverlap = dstOff - srcOff {-# INLINE loopM #-} loopM :: Monad m => Int -> (Int -> m a) -> m () loopM !n k = let go i = when (i < n) (k i >> go (i+1)) in go 0 uninitialised :: a uninitialised = error "Data.Vector.Mutable: uninitialised element. If you are trying to compact a vector, use the 'Data.Vector.force' function to remove uninitialised elements from the underlying array." -- Length information -- ------------------ -- | Length of the mutable vector. length :: MVector s a -> Int {-# INLINE length #-} length = G.length -- | Check whether the vector is empty. null :: MVector s a -> Bool {-# INLINE null #-} null = G.null -- Extracting subvectors -- --------------------- -- | Yield a part of the mutable vector without copying it. The vector must -- contain at least @i+n@ elements. slice :: Int -- ^ @i@ starting index -> Int -- ^ @n@ length -> MVector s a -> MVector s a {-# INLINE slice #-} slice = G.slice -- | 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 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 -- | /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 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 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 -- | Yield a part of the mutable vector without copying it. No bounds checks -- are performed. unsafeSlice :: Int -- ^ starting index -> Int -- ^ length of the slice -> MVector s a -> MVector s a {-# INLINE unsafeSlice #-} unsafeSlice = G.unsafeSlice -- | 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 @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. unsafeInit :: MVector s a -> MVector s a {-# INLINE unsafeInit #-} unsafeInit = G.unsafeInit -- | Same as 'tail', but doesn't do range checks. unsafeTail :: MVector s a -> MVector s a {-# INLINE unsafeTail #-} unsafeTail = G.unsafeTail -- Overlapping -- ----------- -- | Check whether two vectors overlap. overlaps :: MVector s a -> MVector s a -> Bool {-# INLINE overlaps #-} overlaps = G.overlaps -- Initialisation -- -------------- -- | Create a mutable vector of the given length. new :: PrimMonad m => Int -> m (MVector (PrimState m) a) {-# INLINE new #-} 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. -- -- @since 0.5 unsafeNew :: PrimMonad m => Int -> m (MVector (PrimState m) a) {-# INLINE unsafeNew #-} unsafeNew = G.unsafeNew -- | Create a mutable vector of the given length (0 if the length is negative) -- and fill it with an initial value. replicate :: PrimMonad m => Int -> a -> m (MVector (PrimState m) a) {-# INLINE replicate #-} replicate = G.replicate -- | Create a mutable vector of the given length (0 if the length is negative) -- and fill it with values produced by repeatedly executing the monadic action. replicateM :: PrimMonad m => Int -> m a -> m (MVector (PrimState m) a) {-# INLINE replicateM #-} 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) {-# INLINE generate #-} generate = G.generate -- | /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 monadic function to each -- index. Iteration starts at index 0. -- -- @since 0.12.3.0 generateM :: (PrimMonad m) => Int -> (Int -> m a) -> m (MVector (PrimState m) a) {-# INLINE generateM #-} generateM = G.generateM -- | Create a copy of a mutable vector. clone :: PrimMonad m => MVector (PrimState m) a -> m (MVector (PrimState m) a) {-# INLINE clone #-} clone = G.clone -- Growing -- ------- -- | Grow a boxed vector by the given number of elements. The number must be -- 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 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 the values themselves are of a mutable type, e.g. -- 'Data.IORef.IORef' or another mutable vector. -- -- ==== __Examples__ -- -- >>> import qualified Data.Vector as V -- >>> import qualified Data.Vector.Mutable as MV -- >>> mv <- V.thaw $ V.fromList ([10, 20, 30] :: [Integer]) -- >>> mv' <- MV.grow mv 2 -- -- The two extra elements at the end of the newly allocated vector will be -- uninitialized and will result in an error if evaluated, so me must overwrite -- them with new values first: -- -- >>> MV.write mv' 3 999 -- >>> MV.write mv' 4 777 -- >>> V.freeze mv' -- [10,20,30,999,777] -- -- It is important to note that the source mutable vector is not affected when -- the newly allocated one is mutated. -- -- >>> MV.write mv' 2 888 -- >>> V.freeze mv' -- [10,20,888,999,777] -- >>> V.freeze mv -- [10,20,30] -- -- @since 0.5 grow :: PrimMonad m => 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. 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) {-# INLINE unsafeGrow #-} unsafeGrow = G.unsafeGrow -- Restricting memory usage -- ------------------------ -- | Reset all elements of the vector to some undefined value, clearing all -- references to external objects. clear :: PrimMonad m => MVector (PrimState m) a -> m () {-# INLINE clear #-} clear = G.clear -- Accessing individual elements -- ----------------------------- -- | Yield the element at the given position. Will throw an exception if -- the index is out of range. -- -- ==== __Examples__ -- -- >>> import qualified Data.Vector.Mutable as MV -- >>> v <- MV.generate 10 (\x -> x*x) -- >>> MV.read v 3 -- 9 read :: PrimMonad m => MVector (PrimState m) a -> Int -> m a {-# INLINE read #-} read = G.read -- | Yield the element at the given position. Returns 'Nothing' if -- the index is out of range. -- -- @since 0.13 -- -- ==== __Examples__ -- -- >>> import qualified Data.Vector.Mutable as MV -- >>> v <- MV.generate 10 (\x -> x*x) -- >>> MV.readMaybe v 3 -- Just 9 -- >>> MV.readMaybe v 13 -- Nothing readMaybe :: (PrimMonad m) => MVector (PrimState m) a -> Int -> m (Maybe a) {-# INLINE readMaybe #-} readMaybe = G.readMaybe -- | Replace the element at the given position. write :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m () {-# INLINE write #-} write = G.write -- | Modify the element at the given position. modify :: PrimMonad m => MVector (PrimState m) a -> (a -> a) -> Int -> m () {-# INLINE modify #-} modify = G.modify -- | Modify the element at the given position using a monadic function. -- -- @since 0.12.3.0 modifyM :: (PrimMonad m) => MVector (PrimState m) a -> (a -> m a) -> Int -> m () {-# INLINE modifyM #-} modifyM = G.modifyM -- | Swap the elements at the given positions. swap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m () {-# INLINE swap #-} swap = G.swap -- | Replace the element at the given position and return the old element. exchange :: (PrimMonad m) => MVector (PrimState m) a -> Int -> a -> m a {-# INLINE exchange #-} exchange = G.exchange -- | Yield the element at the given position. No bounds checks are performed. unsafeRead :: PrimMonad m => MVector (PrimState m) a -> Int -> m a {-# INLINE unsafeRead #-} unsafeRead = G.unsafeRead -- | Replace the element at the given position. No bounds checks are performed. unsafeWrite :: PrimMonad m => MVector (PrimState m) a -> Int -> a -> m () {-# INLINE unsafeWrite #-} unsafeWrite = G.unsafeWrite -- | Modify the element at the given position. No bounds checks are performed. unsafeModify :: PrimMonad m => MVector (PrimState m) a -> (a -> a) -> Int -> m () {-# INLINE unsafeModify #-} unsafeModify = G.unsafeModify -- | Modify the element at the given position using a monadic -- function. No bounds checks are performed. -- -- @since 0.12.3.0 unsafeModifyM :: (PrimMonad m) => MVector (PrimState m) a -> (a -> m a) -> Int -> m () {-# INLINE unsafeModifyM #-} unsafeModifyM = G.unsafeModifyM -- | Swap the elements at the given positions. No bounds checks are performed. unsafeSwap :: PrimMonad m => MVector (PrimState m) a -> Int -> Int -> m () {-# INLINE unsafeSwap #-} unsafeSwap = G.unsafeSwap -- | Replace the element at the given position and return the old element. No -- bounds checks are performed. unsafeExchange :: (PrimMonad m) => MVector (PrimState m) a -> Int -> a -> m a {-# INLINE unsafeExchange #-} unsafeExchange = G.unsafeExchange -- Filling and copying -- ------------------- -- | Set all elements of the vector to the given value. set :: PrimMonad m => MVector (PrimState m) a -> a -> m () {-# INLINE set #-} set = G.set -- | Copy a vector. The two vectors must have the same length and may not -- overlap. copy :: PrimMonad m => MVector (PrimState m) a -- ^ target -> MVector (PrimState m) a -- ^ source -> m () {-# INLINE copy #-} copy = G.copy -- | Copy a vector. The two vectors must have the same length and may not -- overlap, but this is not checked. unsafeCopy :: PrimMonad m => MVector (PrimState m) a -- ^ target -> MVector (PrimState m) a -- ^ source -> m () {-# INLINE unsafeCopy #-} unsafeCopy = G.unsafeCopy -- | Move the contents of a vector. The two vectors must have the same -- length. -- -- If the vectors do not overlap, then this is equivalent to 'copy'. -- Otherwise, the copying is performed as if the source vector were -- copied to a temporary vector and then the temporary vector was copied -- to the target vector. move :: PrimMonad m => MVector (PrimState m) a -- ^ target -> MVector (PrimState m) a -- ^ source -> m () {-# INLINE move #-} move = G.move -- | Move the contents of a vector. The two vectors must have the same -- length, but this is not checked. -- -- If the vectors do not overlap, then this is equivalent to 'unsafeCopy'. -- Otherwise, the copying is performed as if the source vector were -- copied to a temporary vector and then the temporary vector was copied -- to the target vector. unsafeMove :: PrimMonad m => MVector (PrimState m) a -- ^ target -> MVector (PrimState m) a -- ^ source -> m () {-# INLINE unsafeMove #-} unsafeMove = G.unsafeMove -- 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 -- ----- -- | /O(n)/ Apply the monadic action to every element of the vector, discarding the results. -- -- @since 0.12.3.0 mapM_ :: (PrimMonad m) => (a -> m b) -> MVector (PrimState m) a -> m () {-# INLINE mapM_ #-} mapM_ = G.mapM_ -- | /O(n)/ Apply the monadic action to every element of the vector and its index, discarding the results. -- -- @since 0.12.3.0 imapM_ :: (PrimMonad m) => (Int -> a -> m b) -> MVector (PrimState m) a -> m () {-# INLINE imapM_ #-} imapM_ = G.imapM_ -- | /O(n)/ Apply the monadic action to every element of the vector, -- 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 the same as @flip imapM_@. -- -- @since 0.12.3.0 iforM_ :: (PrimMonad m) => MVector (PrimState m) a -> (Int -> a -> m b) -> m () {-# INLINE iforM_ #-} iforM_ = G.iforM_ -- | /O(n)/ Pure left fold. -- -- @since 0.12.3.0 foldl :: (PrimMonad m) => (b -> a -> b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldl #-} foldl = G.foldl -- | /O(n)/ Pure left fold with strict accumulator. -- -- @since 0.12.3.0 foldl' :: (PrimMonad m) => (b -> a -> b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldl' #-} foldl' = G.foldl' -- | /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 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 right fold. -- -- @since 0.12.3.0 foldr :: (PrimMonad m) => (a -> b -> b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldr #-} foldr = G.foldr -- | /O(n)/ Pure right fold with strict accumulator. -- -- @since 0.12.3.0 foldr' :: (PrimMonad m) => (a -> b -> b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldr' #-} foldr' = G.foldr' -- | /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 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)/ Monadic fold. -- -- @since 0.12.3.0 foldM :: (PrimMonad m) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldM #-} foldM = G.foldM -- | /O(n)/ Monadic fold with strict accumulator. -- -- @since 0.12.3.0 foldM' :: (PrimMonad m) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldM' #-} foldM' = G.foldM' -- | /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 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 right fold. -- -- @since 0.12.3.0 foldrM :: (PrimMonad m) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldrM #-} foldrM = G.foldrM -- | /O(n)/ Monadic right fold with strict accumulator. -- -- @since 0.12.3.0 foldrM' :: (PrimMonad m) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m b {-# INLINE foldrM' #-} foldrM' = G.foldrM' -- | /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 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' -- Conversions - Arrays -- ----------------------------- -- | /O(n)/ Make a copy of a mutable array to a new mutable vector. -- -- @since 0.12.2.0 fromMutableArray :: PrimMonad m => MutableArray (PrimState m) a -> m (MVector (PrimState m) a) {-# INLINE fromMutableArray #-} fromMutableArray marr = let size = sizeofMutableArray marr in MVector 0 size `liftM` cloneMutableArray marr 0 size -- | /O(n)/ Make a copy of a mutable vector into a new mutable array. -- -- @since 0.12.2.0 toMutableArray :: PrimMonad m => MVector (PrimState m) a -> m (MutableArray (PrimState m) a) {-# INLINE toMutableArray #-} toMutableArray (MVector offset size marr) = cloneMutableArray marr offset size