summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlehins <>2021-04-06 19:54:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2021-04-06 19:54:00 (GMT)
commit3406684e53da48c14b760f9e04a95ac6ead32f0c (patch)
tree610e552f0b2861cad2af66f255fad4669b9e00fd
parent20de90be67e0c2800840c6dc9ff3cea52077e243 (diff)
version 0.12.3.0HEAD0.12.3.0master
-rw-r--r--Data/Vector/Generic/Mutable.hs234
-rw-r--r--Data/Vector/Mutable.hs205
-rw-r--r--Data/Vector/Primitive/Mutable.hs205
-rw-r--r--Data/Vector/Storable.hs6
-rw-r--r--Data/Vector/Storable/Internal.hs18
-rw-r--r--Data/Vector/Storable/Mutable.hs231
-rw-r--r--Data/Vector/Unboxed/Mutable.hs207
-rw-r--r--changelog.md12
-rw-r--r--tests/Tests/Vector/Property.hs122
-rw-r--r--tests/Utilities.hs15
-rw-r--r--vector.cabal2
11 files changed, 1218 insertions, 39 deletions
diff --git a/Data/Vector/Generic/Mutable.hs b/Data/Vector/Generic/Mutable.hs
index f9eedd8..c878064 100644
--- a/Data/Vector/Generic/Mutable.hs
+++ b/Data/Vector/Generic/Mutable.hs
@@ -30,7 +30,7 @@ module Data.Vector.Generic.Mutable (
-- * Construction
-- ** Initialisation
- new, unsafeNew, replicate, replicateM, clone,
+ new, unsafeNew, replicate, replicateM, generate, generateM, clone,
-- ** Growing
grow, unsafeGrow,
@@ -40,8 +40,15 @@ module Data.Vector.Generic.Mutable (
clear,
-- * Accessing individual elements
- read, write, modify, swap, exchange,
- unsafeRead, unsafeWrite, unsafeModify, unsafeSwap, unsafeExchange,
+ read, 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,
@@ -71,10 +78,10 @@ import qualified Data.Vector.Fusion.Stream.Monadic as Stream
import Data.Vector.Fusion.Bundle.Size
import Data.Vector.Fusion.Util ( delay_inline )
-import Control.Monad.Primitive ( PrimMonad, PrimState )
+import Control.Monad.Primitive ( PrimMonad, PrimState, stToPrim )
import Prelude hiding ( length, null, replicate, reverse, map, read,
- take, drop, splitAt, init, tail )
+ take, drop, splitAt, init, tail, mapM_, foldr, foldl )
#include "vector.h"
@@ -616,6 +623,30 @@ replicateM :: (PrimMonad m, MVector v a) => Int -> m a -> m (v (PrimState m) a)
{-# INLINE replicateM #-}
replicateM n m = munstream (MBundle.replicateM n m)
+-- | /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.
+--
+-- @since 0.12.3.0
+generate :: (PrimMonad m, MVector v a) => Int -> (Int -> a) -> m (v (PrimState m) a)
+{-# INLINE generate #-}
+generate n f = stToPrim $ generateM n (return . f)
+
+-- | /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, MVector v a) => Int -> (Int -> m a) -> m (v (PrimState m) a)
+{-# INLINE generateM #-}
+generateM n f
+ | n <= 0 = new 0
+ | otherwise = do
+ vec <- new n
+ let loop i | i >= n = return vec
+ | otherwise = do unsafeWrite vec i =<< f i
+ loop (i + 1)
+ loop 0
+
-- | Create a copy of a mutable vector.
clone :: (PrimMonad m, MVector v a) => v (PrimState m) a -> m (v (PrimState m) a)
{-# INLINE clone #-}
@@ -755,6 +786,14 @@ modify :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> a) -> Int ->
modify v f i = BOUNDS_CHECK(checkIndex) "modify" i (length v)
$ unsafeModify v f i
+-- | Modify the element at the given position using a monadic function.
+--
+-- @since 0.12.3.0
+modifyM :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> m a) -> Int -> m ()
+{-# INLINE modifyM #-}
+modifyM v f i = BOUNDS_CHECK(checkIndex) "modifyM" i (length v)
+ $ unsafeModifyM v f i
+
-- | Swap the elements at the given positions.
swap :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Int -> Int -> m ()
{-# INLINE swap #-}
@@ -788,6 +827,15 @@ unsafeModify v f i = UNSAFE_CHECK(checkIndex) "unsafeModify" i (length v)
$ basicUnsafeRead v i >>= \x ->
basicUnsafeWrite v i (f x)
+-- | 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 v a) => v (PrimState m) a -> (a -> m a) -> Int -> m ()
+{-# INLINE unsafeModifyM #-}
+unsafeModifyM v f i = UNSAFE_CHECK(checkIndex) "unsafeModifyM" i (length v)
+ $ stToPrim . basicUnsafeWrite v i =<< f =<< stToPrim (basicUnsafeRead v i)
+
-- | Swap the elements at the given positions. No bounds checks are performed.
unsafeSwap :: (PrimMonad m, MVector v a)
=> v (PrimState m) a -> Int -> Int -> m ()
@@ -811,6 +859,182 @@ unsafeExchange v i x = UNSAFE_CHECK(checkIndex) "unsafeExchange" i (length v)
unsafeWrite v i x
return y
+-- Folds
+-- -----
+
+forI_ :: (Monad m, MVector v a) => v (PrimState m) a -> (Int -> m b) -> m ()
+{-# INLINE forI_ #-}
+forI_ v f = loop 0
+ where
+ loop i | i >= n = return ()
+ | otherwise = f i >> loop (i + 1)
+ n = length v
+
+-- | /O(n)/ Apply the monadic action to every element of the vector, discarding the results.
+--
+-- @since 0.12.3.0
+mapM_ :: (PrimMonad m, MVector v a) => (a -> m b) -> v (PrimState m) a -> m ()
+{-# INLINE mapM_ #-}
+mapM_ f v = forI_ v $ \i -> f =<< unsafeRead v i
+
+-- | /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, MVector v a) => (Int -> a -> m b) -> v (PrimState m) a -> m ()
+{-# INLINE imapM_ #-}
+imapM_ f v = forI_ v $ \i -> f i =<< unsafeRead v i
+
+-- | /O(n)/ Apply the monadic action to every element of the vector,
+-- discarding the results. It's same as the @flip mapM_@.
+--
+-- @since 0.12.3.0
+forM_ :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> m b) -> m ()
+{-# INLINE forM_ #-}
+forM_ = flip mapM_
+
+-- | /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_@.
+--
+-- @since 0.12.3.0
+iforM_ :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (Int -> a -> m b) -> m ()
+{-# INLINE iforM_ #-}
+iforM_ = flip imapM_
+
+-- | /O(n)/ Pure left fold.
+--
+-- @since 0.12.3.0
+foldl :: (PrimMonad m, MVector v a) => (b -> a -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldl #-}
+foldl f = ifoldl (\b _ -> f b)
+
+-- | /O(n)/ Pure left fold with strict accumulator.
+--
+-- @since 0.12.3.0
+foldl' :: (PrimMonad m, MVector v a) => (b -> a -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldl' #-}
+foldl' f = ifoldl' (\b _ -> f b)
+
+-- | /O(n)/ Pure left fold (function applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldl :: (PrimMonad m, MVector v a) => (b -> Int -> a -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldl #-}
+ifoldl f b0 v = stToPrim $ ifoldM (\b i a -> return $ f b i a) b0 v
+
+-- | /O(n)/ Pure left fold with strict accumulator (function applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldl' :: (PrimMonad m, MVector v a) => (b -> Int -> a -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldl' #-}
+ifoldl' f b0 v = stToPrim $ ifoldM' (\b i a -> return $ f b i a) b0 v
+
+-- | /O(n)/ Pure right fold.
+--
+-- @since 0.12.3.0
+foldr :: (PrimMonad m, MVector v a) => (a -> b -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldr #-}
+foldr f = ifoldr (const f)
+
+-- | /O(n)/ Pure right fold with strict accumulator.
+--
+-- @since 0.12.3.0
+foldr' :: (PrimMonad m, MVector v a) => (a -> b -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldr' #-}
+foldr' f = ifoldr' (const f)
+
+-- | /O(n)/ Pure right fold (function applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldr :: (PrimMonad m, MVector v a) => (Int -> a -> b -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldr #-}
+ifoldr f b0 v = stToPrim $ ifoldrM (\i a b -> return $ f i a b) b0 v
+
+-- | /O(n)/ Pure right fold with strict accumulator (function applied
+-- to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldr' :: (PrimMonad m, MVector v a) => (Int -> a -> b -> b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldr' #-}
+ifoldr' f b0 v = stToPrim $ ifoldrM' (\i a b -> return $ f i a b) b0 v
+
+-- | /O(n)/ Monadic fold.
+--
+-- @since 0.12.3.0
+foldM :: (PrimMonad m, MVector v a) => (b -> a -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldM #-}
+foldM f = ifoldM (\x _ -> f x)
+
+-- | /O(n)/ Monadic fold with strict accumulator.
+--
+-- @since 0.12.3.0
+foldM' :: (PrimMonad m, MVector v a) => (b -> a -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldM' #-}
+foldM' f = ifoldM' (\x _ -> f x)
+
+-- | /O(n)/ Monadic fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldM :: (PrimMonad m, MVector v a) => (b -> Int -> a -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldM #-}
+ifoldM f b0 v = loop 0 b0
+ where
+ loop i b | i >= n = return b
+ | otherwise = do a <- unsafeRead v i
+ loop (i + 1) =<< f b i a
+ n = length v
+
+-- | /O(n)/ Monadic fold with strict accumulator (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldM' :: (PrimMonad m, MVector v a) => (b -> Int -> a -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldM' #-}
+ifoldM' f b0 v = loop 0 b0
+ where
+ loop i !b | i >= n = return b
+ | otherwise = do a <- unsafeRead v i
+ loop (i + 1) =<< f b i a
+ n = length v
+
+-- | /O(n)/ Monadic right fold.
+--
+-- @since 0.12.3.0
+foldrM :: (PrimMonad m, MVector v a) => (a -> b -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldrM #-}
+foldrM f = ifoldrM (const f)
+
+-- | /O(n)/ Monadic right fold with strict accumulator.
+--
+-- @since 0.12.3.0
+foldrM' :: (PrimMonad m, MVector v a) => (a -> b -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE foldrM' #-}
+foldrM' f = ifoldrM' (const f)
+
+-- | /O(n)/ Monadic right fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldrM :: (PrimMonad m, MVector v a) => (Int -> a -> b -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldrM #-}
+ifoldrM f b0 v = loop (n-1) b0
+ where
+ loop i b | i < 0 = return b
+ | otherwise = do a <- unsafeRead v i
+ loop (i - 1) =<< f i a b
+ n = length v
+
+-- | /O(n)/ Monadic right fold with strict accumulator (action applied
+-- to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldrM' :: (PrimMonad m, MVector v a) => (Int -> a -> b -> m b) -> b -> v (PrimState m) a -> m b
+{-# INLINE ifoldrM' #-}
+ifoldrM' f b0 v = loop (n-1) b0
+ where
+ loop i !b | i < 0 = return b
+ | otherwise = do a <- unsafeRead v i
+ loop (i - 1) =<< f i a b
+ n = length v
+
+
-- Filling and copying
-- -------------------
diff --git a/Data/Vector/Mutable.hs b/Data/Vector/Mutable.hs
index 9069ce2..e99f7ef 100644
--- a/Data/Vector/Mutable.hs
+++ b/Data/Vector/Mutable.hs
@@ -31,7 +31,7 @@ module Data.Vector.Mutable (
-- * Construction
-- ** Initialisation
- new, unsafeNew, replicate, replicateM, clone,
+ new, unsafeNew, replicate, replicateM, generate, generateM, clone,
-- ** Growing
grow, unsafeGrow,
@@ -40,8 +40,15 @@ module Data.Vector.Mutable (
clear,
-- * Accessing individual elements
- read, write, modify, swap,
- unsafeRead, unsafeWrite, unsafeModify, unsafeSwap,
+ read, 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,
@@ -60,7 +67,7 @@ import Data.Primitive.Array
import Control.Monad.Primitive
import Prelude hiding ( length, null, replicate, reverse, read,
- take, drop, splitAt, init, tail )
+ take, drop, splitAt, init, tail, foldr, foldl, mapM_ )
import Data.Typeable ( Typeable )
@@ -299,6 +306,23 @@ 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.
+--
+-- @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 #-}
@@ -382,11 +406,22 @@ 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
@@ -403,11 +438,25 @@ 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
-- -------------------
@@ -464,6 +513,154 @@ 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 same as the @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_@.
+--
+-- @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 (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).
+--
+-- @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 (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).
+--
+-- @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 (action 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).
+--
+-- @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 (action 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).
+--
+-- @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
-- -----------------------------
diff --git a/Data/Vector/Primitive/Mutable.hs b/Data/Vector/Primitive/Mutable.hs
index fd2768b..c161264 100644
--- a/Data/Vector/Primitive/Mutable.hs
+++ b/Data/Vector/Primitive/Mutable.hs
@@ -31,7 +31,7 @@ module Data.Vector.Primitive.Mutable (
-- * Construction
-- ** Initialisation
- new, unsafeNew, replicate, replicateM, clone,
+ new, unsafeNew, replicate, replicateM, generate, generateM, clone,
-- ** Growing
grow, unsafeGrow,
@@ -40,8 +40,15 @@ module Data.Vector.Primitive.Mutable (
clear,
-- * Accessing individual elements
- read, write, modify, swap,
- unsafeRead, unsafeWrite, unsafeModify, unsafeSwap,
+ read, 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,
@@ -64,7 +71,7 @@ import Control.DeepSeq ( NFData(rnf)
)
import Prelude hiding ( length, null, replicate, reverse, map, read,
- take, drop, splitAt, init, tail )
+ take, drop, splitAt, init, tail, foldr, foldl, mapM_ )
import Data.Typeable ( Typeable )
@@ -247,6 +254,23 @@ replicateM :: (PrimMonad m, Prim a) => 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.
+--
+-- @since 0.12.3.0
+generate :: (PrimMonad m, Prim a) => 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, Prim a) => Int -> (Int -> m a) -> m (MVector (PrimState m) a)
+{-# INLINE generateM #-}
+generateM = G.generateM
+
-- | Create a copy of a mutable vector.
clone :: (PrimMonad m, Prim a)
=> MVector (PrimState m) a -> m (MVector (PrimState m) a)
@@ -332,11 +356,22 @@ modify :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> (a -> a) -> Int ->
{-# INLINE modify #-}
modify = G.modify
+-- | Modify the element at the given position using a monadic function.
+--
+-- @since 0.12.3.0
+modifyM :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> (a -> m a) -> Int -> m ()
+{-# INLINE modifyM #-}
+modifyM = G.modifyM
+
-- | Swap the elements at the given positions.
swap :: (PrimMonad m, Prim a) => 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, Prim a) => 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, Prim a) => MVector (PrimState m) a -> Int -> m a
@@ -354,12 +389,26 @@ unsafeModify :: (PrimMonad m, Prim a) => MVector (PrimState m) a -> (a -> a) ->
{-# 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, Prim a) => 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, Prim a) => 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, Prim a) => MVector (PrimState m) a -> Int -> a -> m a
+{-# INLINE unsafeExchange #-}
+unsafeExchange = G.unsafeExchange
+
-- Filling and copying
-- -------------------
@@ -419,3 +468,151 @@ unsafeMove = G.unsafeMove
nextPermutation :: (PrimMonad m,Ord e,Prim 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, Prim a) => (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, Prim a) => (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 same as the @flip mapM_@.
+--
+-- @since 0.12.3.0
+forM_ :: (PrimMonad m, Prim a) => 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_@.
+--
+-- @since 0.12.3.0
+iforM_ :: (PrimMonad m, Prim a) => 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, Prim a) => (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, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl :: (PrimMonad m, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl' :: (PrimMonad m, Prim a) => (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, Prim a) => (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, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr :: (PrimMonad m, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr' :: (PrimMonad m, Prim a) => (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, Prim a) => (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, Prim a) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldM' #-}
+foldM' = G.foldM'
+
+-- | /O(n)/ Monadic fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldM :: (PrimMonad m, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldM' :: (PrimMonad m, Prim a) => (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, Prim a) => (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, Prim a) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldrM' #-}
+foldrM' = G.foldrM'
+
+-- | /O(n)/ Monadic right fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldrM :: (PrimMonad m, Prim a) => (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).
+--
+-- @since 0.12.3.0
+ifoldrM' :: (PrimMonad m, Prim a) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE ifoldrM' #-}
+ifoldrM' = G.ifoldrM'
diff --git a/Data/Vector/Storable.hs b/Data/Vector/Storable.hs
index bf464c0..e58de40 100644
--- a/Data/Vector/Storable.hs
+++ b/Data/Vector/Storable.hs
@@ -255,14 +255,14 @@ instance Storable a => G.Vector Vector a where
{-# INLINE basicUnsafeIndexM #-}
basicUnsafeIndexM (Vector _ fp) i = return
. unsafeInlineIO
- $ withForeignPtr fp $ \p ->
+ $ unsafeWithForeignPtr fp $ \p ->
peekElemOff p i
{-# INLINE basicUnsafeCopy #-}
basicUnsafeCopy (MVector n fp) (Vector _ fq)
= unsafePrimToPrim
- $ withForeignPtr fp $ \p ->
- withForeignPtr fq $ \q ->
+ $ unsafeWithForeignPtr fp $ \p ->
+ unsafeWithForeignPtr fq $ \q ->
copyArray p q n
{-# INLINE elemseq #-}
diff --git a/Data/Vector/Storable/Internal.hs b/Data/Vector/Storable/Internal.hs
index 0ed2188..eafc70d 100644
--- a/Data/Vector/Storable/Internal.hs
+++ b/Data/Vector/Storable/Internal.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
-- |
-- Module : Data.Vector.Storable.Internal
-- Copyright : (c) Roman Leshchinskiy 2009-2010
@@ -11,12 +13,17 @@
--
module Data.Vector.Storable.Internal (
- getPtr, setPtr, updPtr
+ getPtr, setPtr, updPtr, unsafeWithForeignPtr
) where
import Foreign.ForeignPtr ()
import Foreign.Ptr ()
import GHC.ForeignPtr ( ForeignPtr(..) )
+#if MIN_VERSION_base(4,15,0)
+import GHC.ForeignPtr ( unsafeWithForeignPtr )
+#else
+import Foreign.ForeignPtr ( withForeignPtr )
+#endif
import GHC.Ptr ( Ptr(..) )
getPtr :: ForeignPtr a -> Ptr a
@@ -31,3 +38,12 @@ updPtr :: (Ptr a -> Ptr a) -> ForeignPtr a -> ForeignPtr a
{-# INLINE updPtr #-}
updPtr f (ForeignPtr p c) = case f (Ptr p) of { Ptr q -> ForeignPtr q c }
+#if !MIN_VERSION_base(4,15,0)
+-- | A compatibility wrapper for 'GHC.ForeignPtr.unsafeWithForeignPtr' provided
+-- by GHC 9.0.1 and later.
+--
+-- Only to be used when the continuation is known not to
+-- unconditionally diverge lest unsoundness can result.
+unsafeWithForeignPtr :: ForeignPtr a -> (Ptr a -> IO b) -> IO b
+unsafeWithForeignPtr = withForeignPtr
+#endif
diff --git a/Data/Vector/Storable/Mutable.hs b/Data/Vector/Storable/Mutable.hs
index 75ff781..01f3e44 100644
--- a/Data/Vector/Storable/Mutable.hs
+++ b/Data/Vector/Storable/Mutable.hs
@@ -33,7 +33,7 @@ module Data.Vector.Storable.Mutable(
-- * Construction
-- ** Initialisation
- new, unsafeNew, replicate, replicateM, clone,
+ new, unsafeNew, replicate, replicateM, generate, generateM, clone,
-- ** Growing
grow, unsafeGrow,
@@ -42,10 +42,18 @@ module Data.Vector.Storable.Mutable(
clear,
-- * Accessing individual elements
- read, write, modify, swap,
- unsafeRead, unsafeWrite, unsafeModify, unsafeSwap,
+ read, 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,
@@ -94,7 +102,7 @@ import GHC.Word (Word8, Word16, Word32, Word64)
import GHC.Ptr (Ptr(..))
import Prelude hiding ( length, null, replicate, reverse, map, read,
- take, drop, splitAt, init, tail )
+ take, drop, splitAt, init, tail, foldr, foldl, mapM_ )
import Data.Typeable ( Typeable )
@@ -154,12 +162,12 @@ instance Storable a => G.MVector MVector a where
{-# INLINE basicUnsafeRead #-}
basicUnsafeRead (MVector _ fp) i
= unsafePrimToPrim
- $ withForeignPtr fp (`peekElemOff` i)
+ $ unsafeWithForeignPtr fp (`peekElemOff` i)
{-# INLINE basicUnsafeWrite #-}
basicUnsafeWrite (MVector _ fp) i x
= unsafePrimToPrim
- $ withForeignPtr fp $ \p -> pokeElemOff p i x
+ $ unsafeWithForeignPtr fp $ \p -> pokeElemOff p i x
{-# INLINE basicSet #-}
basicSet = storableSet
@@ -167,20 +175,20 @@ instance Storable a => G.MVector MVector a where
{-# INLINE basicUnsafeCopy #-}
basicUnsafeCopy (MVector n fp) (MVector _ fq)
= unsafePrimToPrim
- $ withForeignPtr fp $ \p ->
- withForeignPtr fq $ \q ->
+ $ unsafeWithForeignPtr fp $ \p ->
+ unsafeWithForeignPtr fq $ \q ->
copyArray p q n
{-# INLINE basicUnsafeMove #-}
basicUnsafeMove (MVector n fp) (MVector _ fq)
= unsafePrimToPrim
- $ withForeignPtr fp $ \p ->
- withForeignPtr fq $ \q ->
+ $ unsafeWithForeignPtr fp $ \p ->
+ unsafeWithForeignPtr fq $ \q ->
moveArray p q n
storableZero :: forall a m. (Storable a, PrimMonad m) => MVector (PrimState m) a -> m ()
{-# INLINE storableZero #-}
-storableZero (MVector n fp) = unsafePrimToPrim . withForeignPtr fp $ \ptr-> do
+storableZero (MVector n fp) = unsafePrimToPrim . unsafeWithForeignPtr fp $ \ptr-> do
memsetPrimPtr_vector (castPtr ptr) byteSize (0 :: Word8)
where
x :: a
@@ -198,7 +206,7 @@ storableSet (MVector n fp) x
2 -> storableSetAsPrim n fp x (undefined :: Word16)
4 -> storableSetAsPrim n fp x (undefined :: Word32)
8 -> storableSetAsPrim n fp x (undefined :: Word64)
- _ -> withForeignPtr fp $ \p -> do
+ _ -> unsafeWithForeignPtr fp $ \p -> do
poke p x
let do_set i
@@ -212,7 +220,7 @@ storableSet (MVector n fp) x
storableSetAsPrim
:: forall a b . (Storable a, Prim b) => Int -> ForeignPtr a -> a -> b -> IO ()
{-# INLINE [0] storableSetAsPrim #-}
-storableSetAsPrim n fp x _y = withForeignPtr fp $ \ ptr -> do
+storableSetAsPrim n fp x _y = unsafeWithForeignPtr fp $ \ ptr -> do
poke ptr x
-- we dont equate storable and prim reps, so we need to write to a slot
-- in storable
@@ -375,6 +383,23 @@ replicateM :: (PrimMonad m, Storable a) => Int -> m a -> m (MVector (PrimState m
{-# 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.
+--
+-- @since 0.12.3.0
+generate :: (PrimMonad m, Storable a) => 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, Storable a) => Int -> (Int -> m a) -> m (MVector (PrimState m) a)
+{-# INLINE generateM #-}
+generateM = G.generateM
+
-- | Create a copy of a mutable vector.
clone :: (PrimMonad m, Storable a)
=> MVector (PrimState m) a -> m (MVector (PrimState m) a)
@@ -461,12 +486,23 @@ modify :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> (a -> a) -> In
{-# INLINE modify #-}
modify = G.modify
+-- | Modify the element at the given position using a monadic function.
+--
+-- @since 0.12.3.0
+modifyM :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> (a -> m a) -> Int -> m ()
+{-# INLINE modifyM #-}
+modifyM = G.modifyM
+
-- | Swap the elements at the given positions.
swap
:: (PrimMonad m, Storable a) => 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, Storable a) => 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, Storable a) => MVector (PrimState m) a -> Int -> m a
@@ -484,12 +520,26 @@ unsafeModify :: (PrimMonad m, Storable a) => MVector (PrimState m) a -> (a -> a)
{-# 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, Storable a) => 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, Storable a) => 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, Storable a) => MVector (PrimState m) a -> Int -> a -> m a
+{-# INLINE unsafeExchange #-}
+unsafeExchange = G.unsafeExchange
+
-- Filling and copying
-- -------------------
@@ -544,6 +594,161 @@ unsafeMove :: (PrimMonad m, Storable a)
{-# 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, Storable e, 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, Storable a) => (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, Storable a) => (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 same as the @flip mapM_@.
+--
+-- @since 0.12.3.0
+forM_ :: (PrimMonad m, Storable a) => 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_@.
+--
+-- @since 0.12.3.0
+iforM_ :: (PrimMonad m, Storable a) => 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, Storable a) => (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, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl :: (PrimMonad m, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl' :: (PrimMonad m, Storable a) => (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, Storable a) => (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, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr :: (PrimMonad m, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr' :: (PrimMonad m, Storable a) => (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, Storable a) => (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, Storable a) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldM' #-}
+foldM' = G.foldM'
+
+-- | /O(n)/ Monadic fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldM :: (PrimMonad m, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldM' :: (PrimMonad m, Storable a) => (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, Storable a) => (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, Storable a) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldrM' #-}
+foldrM' = G.foldrM'
+
+-- | /O(n)/ Monadic right fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldrM :: (PrimMonad m, Storable a) => (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).
+--
+-- @since 0.12.3.0
+ifoldrM' :: (PrimMonad m, Storable a) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE ifoldrM' #-}
+ifoldrM' = G.ifoldrM'
+
+
-- Unsafe conversions
-- ------------------
diff --git a/Data/Vector/Unboxed/Mutable.hs b/Data/Vector/Unboxed/Mutable.hs
index 90b5301..2ecfe2c 100644
--- a/Data/Vector/Unboxed/Mutable.hs
+++ b/Data/Vector/Unboxed/Mutable.hs
@@ -31,7 +31,7 @@ module Data.Vector.Unboxed.Mutable (
-- * Construction
-- ** Initialisation
- new, unsafeNew, replicate, replicateM, clone,
+ new, unsafeNew, replicate, replicateM, generate, generateM, clone,
-- ** Growing
grow, unsafeGrow,
@@ -44,8 +44,15 @@ module Data.Vector.Unboxed.Mutable (
unzip, unzip3, unzip4, unzip5, unzip6,
-- * Accessing individual elements
- read, write, modify, swap,
- unsafeRead, unsafeWrite, unsafeModify, unsafeSwap,
+ read, 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,
@@ -61,7 +68,7 @@ import Control.Monad.Primitive
import Prelude hiding ( length, null, replicate, reverse, map, read,
take, drop, splitAt, init, tail,
- zip, zip3, unzip, unzip3 )
+ zip, zip3, unzip, unzip3, foldr, foldl, mapM_ )
-- don't import an unused Data.Vector.Internal.Check
#define NOT_VECTOR_MODULE
@@ -176,6 +183,23 @@ replicateM :: (PrimMonad m, Unbox a) => 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.
+--
+-- @since 0.12.3.0
+generate :: (PrimMonad m, Unbox a) => 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, Unbox a) => Int -> (Int -> m a) -> m (MVector (PrimState m) a)
+{-# INLINE generateM #-}
+generateM = G.generateM
+
-- | Create a copy of a mutable vector.
clone :: (PrimMonad m, Unbox a)
=> MVector (PrimState m) a -> m (MVector (PrimState m) a)
@@ -261,11 +285,22 @@ modify :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> (a -> a) -> Int -
{-# INLINE modify #-}
modify = G.modify
+-- | Modify the element at the given position using a monadic function.
+--
+-- @since 0.12.3.0
+modifyM :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> (a -> m a) -> Int -> m ()
+{-# INLINE modifyM #-}
+modifyM = G.modifyM
+
-- | Swap the elements at the given positions.
swap :: (PrimMonad m, Unbox a) => 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, Unbox a) => 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, Unbox a) => MVector (PrimState m) a -> Int -> m a
@@ -283,12 +318,26 @@ unsafeModify :: (PrimMonad m, Unbox a) => MVector (PrimState m) a -> (a -> a) ->
{-# 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, Unbox a) => 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, Unbox a) => 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, Unbox a) => MVector (PrimState m) a -> Int -> a -> m a
+{-# INLINE unsafeExchange #-}
+unsafeExchange = G.unsafeExchange
+
-- Filling and copying
-- -------------------
@@ -349,5 +398,155 @@ nextPermutation :: (PrimMonad m,Ord e,Unbox e) => MVector (PrimState m) e -> m B
{-# 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, Unbox a) => (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, Unbox a) => (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 same as the @flip mapM_@.
+--
+-- @since 0.12.3.0
+forM_ :: (PrimMonad m, Unbox a) => 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_@.
+--
+-- @since 0.12.3.0
+iforM_ :: (PrimMonad m, Unbox a) => 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, Unbox a) => (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, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl :: (PrimMonad m, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldl' :: (PrimMonad m, Unbox a) => (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, Unbox a) => (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, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr :: (PrimMonad m, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldr' :: (PrimMonad m, Unbox a) => (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, Unbox a) => (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, Unbox a) => (b -> a -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldM' #-}
+foldM' = G.foldM'
+
+-- | /O(n)/ Monadic fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldM :: (PrimMonad m, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldM' :: (PrimMonad m, Unbox a) => (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, Unbox a) => (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, Unbox a) => (a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE foldrM' #-}
+foldrM' = G.foldrM'
+
+-- | /O(n)/ Monadic right fold (action applied to each element and its index).
+--
+-- @since 0.12.3.0
+ifoldrM :: (PrimMonad m, Unbox a) => (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).
+--
+-- @since 0.12.3.0
+ifoldrM' :: (PrimMonad m, Unbox a) => (Int -> a -> b -> m b) -> b -> MVector (PrimState m) a -> m b
+{-# INLINE ifoldrM' #-}
+ifoldrM' = G.ifoldrM'
+
+
#define DEFINE_MUTABLE
#include "unbox-tuple-instances"
diff --git a/changelog.md b/changelog.md
index 03b667e..9868044 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,15 @@
+# Changes in version 0.12.3.0
+
+ * Fix performance regression due to introduction of `keepAlive#` primop in ghc-9.0: [#372](https://github.com/haskell/vector/pull/372)
+
+ * Add monadic functions for mutable vectors: [#338](https://github.com/haskell/vector/pull/338)
+
+ * Added folds for monadic functions: `mapM_`, `imapM_`, `forM_`, `iforM_`,
+ `foldl`, `foldl'`, `foldM`, `foldM'`, `ifoldl`, `ifoldl'`, `ifoldM`,
+ `ifoldM'`
+ * Added `modifyM` and `unsafeModifyM` for mutable vectors
+ * Added `generate` and `generateM` for mutable vectors
+
# Changes in version 0.12.2.0
* Add `MINIMAL` pragma to `Vector` & `MVector` type classes: [#11](https://github.com/haskell/vector/issues/11)
diff --git a/tests/Tests/Vector/Property.hs b/tests/Tests/Vector/Property.hs
index 3022db8..5910abc 100644
--- a/tests/Tests/Vector/Property.hs
+++ b/tests/Tests/Vector/Property.hs
@@ -28,12 +28,14 @@ import Boilerplater
import Utilities as Util hiding (limitUnfolds)
import Control.Monad
-import Data.Functor.Identity
+import Control.Monad.ST
import qualified Data.Traversable as T (Traversable(..))
import Data.Foldable (Foldable(foldMap))
+import Data.Functor.Identity
import Data.Orphans ()
-
+import Data.Foldable (foldrM)
import qualified Data.Vector.Generic as V
+import qualified Data.Vector.Generic.Mutable as MV
import qualified Data.Vector.Fusion.Bundle as S
import Test.QuickCheck
@@ -196,7 +198,17 @@ testPolymorphicFunctions _ = $(testProperties [
'prop_prescanr, 'prop_prescanr',
'prop_postscanr, 'prop_postscanr',
'prop_scanr, 'prop_scanr', 'prop_scanr1, 'prop_scanr1',
- 'prop_iscanr, 'prop_iscanr'
+ 'prop_iscanr, 'prop_iscanr',
+
+ -- Mutable API
+ 'prop_mut_read, 'prop_mut_write, 'prop_mut_modify,
+
+ 'prop_mut_generate, 'prop_mut_generateM,
+ 'prop_mut_mapM_, 'prop_mut_imapM_, 'prop_mut_forM_, 'prop_mut_iforM_,
+ 'prop_mut_foldr, 'prop_mut_foldr', 'prop_mut_foldl, 'prop_mut_foldl',
+ 'prop_mut_ifoldr, 'prop_mut_ifoldr', 'prop_mut_ifoldl, 'prop_mut_ifoldl',
+ 'prop_mut_foldM, 'prop_mut_foldM', 'prop_mut_foldrM, 'prop_mut_foldrM',
+ 'prop_mut_ifoldM, 'prop_mut_ifoldM', 'prop_mut_ifoldrM, 'prop_mut_ifoldrM'
])
where
-- Prelude
@@ -474,6 +486,110 @@ testPolymorphicFunctions _ = $(testProperties [
constructrN xs 0 _ = xs
constructrN xs n f = constructrN (f xs : xs) (n-1) f
+ prop_mut_foldr :: P ((a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.foldr f z =<< V.thaw v) `eq` foldr
+ prop_mut_foldr' :: P ((a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.foldr' f z =<< V.thaw v) `eq` foldr
+ prop_mut_foldl :: P ((a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.foldl f z =<< V.thaw v) `eq` foldl
+ prop_mut_foldl' :: P ((a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.foldl' f z =<< V.thaw v) `eq` foldl'
+ prop_mut_ifoldr :: P ((Int -> a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.ifoldr f z =<< V.thaw v) `eq` ifoldr
+ prop_mut_ifoldr' :: P ((Int -> a -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.ifoldr' f z =<< V.thaw v) `eq` ifoldr
+ prop_mut_ifoldl :: P ((a -> Int -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.ifoldl f z =<< V.thaw v) `eq` ifoldl
+ prop_mut_ifoldl' :: P ((a -> Int -> a -> a) -> a -> v a -> a) =
+ (\f z v -> runST $ MV.ifoldl' f z =<< V.thaw v) `eq` ifoldl
+
+ prop_mut_foldM :: P ((a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.foldM (\b -> pure . runIdentity . f b) z =<< V.thaw v)
+ `eq` foldM
+ prop_mut_foldM' :: P ((a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.foldM' (\b -> pure . runIdentity . f b) z =<< V.thaw v)
+ `eq` foldM
+ prop_mut_foldrM :: P ((a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.foldrM (\a -> pure . runIdentity . f a) z =<< V.thaw v)
+ `eq`
+ foldrM
+ prop_mut_foldrM' :: P ((a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.foldrM' (\a b -> pure $ runIdentity $ f a b) z =<< V.thaw v)
+ `eq`
+ foldrM
+
+ prop_mut_read = \xs ->
+ not (V.null xs) ==>
+ forAll (choose (0, V.length xs-1)) $ \i ->
+ unP prop xs i
+ where
+ prop :: P (v a -> Int -> a) = (\v i -> runST $ do mv <- V.thaw v
+ MV.read mv i
+ ) `eq` (!!)
+ prop_mut_write = \xs ->
+ not (V.null xs) ==>
+ forAll (choose (0, V.length xs-1)) $ \i ->
+ unP prop xs i
+ where
+ prop :: P (v a -> Int -> a -> v a) = (\v i a -> runST $ do mv <- V.thaw v
+ MV.write mv i a
+ V.freeze mv
+ ) `eq` writeList
+ prop_mut_modify = \xs f ->
+ not (V.null xs) ==>
+ forAll (choose (0, V.length xs-1)) $ \i ->
+ unP prop xs f i
+ where
+ prop :: P (v a -> (a -> a) -> Int -> v a)
+ = (\v f i -> runST $ do mv <- V.thaw v
+ MV.modify mv f i
+ V.freeze mv
+ ) `eq` modifyList
+
+
+
+ prop_mut_generate :: P (Int -> (Int -> a) -> v a)
+ = (\n _ -> n < 1000) ===> (\n f -> runST $ V.freeze =<< MV.generate n f)
+ `eq` Util.generate
+ prop_mut_generateM :: P (Int -> (Int -> Writer [a] a) -> Writer [a] (v a))
+ = (\n _ -> n < 1000) ===> (\n f -> liftRunST $ V.freeze =<< MV.generateM n (hoistST . f))
+ `eq` Util.generateM
+
+ prop_mut_ifoldM :: P ((a -> Int -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.ifoldM (\b i -> pure . runIdentity . f b i) z =<< V.thaw v)
+ `eq` ifoldM
+ prop_mut_ifoldM' :: P ((a -> Int -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.ifoldM' (\b i -> pure . runIdentity . f b i) z =<< V.thaw v)
+ `eq` ifoldM
+ prop_mut_ifoldrM :: P ((Int -> a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.ifoldrM (\i b -> pure . runIdentity . f i b) z =<< V.thaw v)
+ `eq`
+ ifoldrM
+ prop_mut_ifoldrM' :: P ((Int -> a -> a -> Identity a) -> a -> v a -> Identity a)
+ = (\f z v -> Identity $ runST $ MV.ifoldrM' (\i b -> pure . runIdentity . f i b) z =<< V.thaw v)
+ `eq`
+ ifoldrM
+
+ prop_mut_forM_ :: P (v a -> (a -> Writer [a] ()) -> Writer [a] ())
+ = (\v f -> liftRunST $ do mv <- V.thaw v
+ MV.forM_ mv (hoistST . f))
+ `eq` flip mapM_
+ prop_mut_iforM_ :: P (v a -> (Int -> a -> Writer [a] ()) -> Writer [a] ())
+ = (\v f -> liftRunST $ do mv <- V.thaw v
+ MV.iforM_ mv (\i x -> hoistST $ f i x))
+ `eq` flip imapM_
+ prop_mut_mapM_ :: P ((a -> Writer [a] ()) -> v a -> Writer [a] ())
+ = (\f v -> liftRunST $ MV.mapM_ (hoistST . f) =<< V.thaw v) `eq` mapM_
+ prop_mut_imapM_ :: P ((Int -> a -> Writer [a] ()) -> v a -> Writer [a] ())
+ = (\f v -> liftRunST $ MV.imapM_ (\i x -> hoistST $ f i x) =<< V.thaw v) `eq` imapM_
+
+
+liftRunST :: (forall s. WriterT w (ST s) a) -> Writer w a
+liftRunST m = WriterT $ Identity $ runST $ runWriterT m
+
+hoistST :: Writer w a -> WriterT w (ST s) a
+hoistST = WriterT . pure . runWriter
+
-- copied from GHC source code
partitionWith :: (a -> Either b c) -> [a] -> ([b], [c])
partitionWith _ [] = ([],[])
diff --git a/tests/Utilities.hs b/tests/Utilities.hs
index 0e411f5..d33b095 100644
--- a/tests/Utilities.hs
+++ b/tests/Utilities.hs
@@ -3,6 +3,7 @@ module Utilities where
import Test.QuickCheck
+import Data.Foldable
import qualified Data.Vector as DV
import qualified Data.Vector.Generic as DVG
import qualified Data.Vector.Primitive as DVP
@@ -278,6 +279,15 @@ xs // ps = go xs ps' 0
withIndexFirst m f = m (uncurry f) . zip [0..]
+modifyList :: [a] -> (a -> a) -> Int -> [a]
+modifyList xs f i = zipWith merge xs (replicate i Nothing ++ [Just f] ++ repeat Nothing)
+ where
+ merge x Nothing = x
+ merge x (Just g) = g x
+
+writeList :: [a] -> Int -> a -> [a]
+writeList xs i a = modifyList xs (const a) i
+
imap :: (Int -> a -> a) -> [a] -> [a]
imap = withIndexFirst map
@@ -322,9 +332,12 @@ iscanr f z = scanr (uncurry f) z . zip [0..]
ifoldr :: (Int -> a -> b -> b) -> b -> [a] -> b
ifoldr f z = foldr (uncurry f) z . zip [0..]
-ifoldM :: Monad m => (a -> Int -> a -> m a) -> a -> [a] -> m a
+ifoldM :: Monad m => (b -> Int -> a -> m b) -> b -> [a] -> m b
ifoldM = indexedLeftFold foldM
+ifoldrM :: Monad m => (Int -> a -> b -> m b) -> b -> [a] -> m b
+ifoldrM f z xs = foldrM (\(i,a) b -> f i a b) z ([0..] `zip` xs)
+
ifoldM_ :: Monad m => (b -> Int -> a -> m b) -> b -> [a] -> m ()
ifoldM_ = indexedLeftFold foldM_
diff --git a/vector.cabal b/vector.cabal
index 3ba4baf..a883166 100644
--- a/vector.cabal
+++ b/vector.cabal
@@ -1,5 +1,5 @@
Name: vector
-Version: 0.12.2.0
+Version: 0.12.3.0
-- don't forget to update the changelog file!
License: BSD3
License-File: LICENSE