Fix INLINE pragmas
[darcs-mirrors/vector.git] / Data / Vector / Generic.hs
index c090c38..0d9f6cb 100644 (file)
@@ -85,6 +85,10 @@ module Data.Vector.Generic (
   -- * Conversion to/from lists
   toList, fromList, fromListN,
 
+  -- * Monadic operations
+  replicateM, mapM, mapM_, forM, forM_, zipWithM, zipWithM_, filterM,
+  foldM, foldM', fold1M, fold1M',
+
   -- * Destructive operations
   create, modify, copy, unsafeCopy,
 
@@ -114,6 +118,7 @@ import           Data.Vector.Fusion.Util
 
 import Control.Monad.ST ( ST, runST )
 import Control.Monad.Primitive
+import qualified Control.Monad as Monad
 import Prelude hiding ( length, null,
                         replicate, (++),
                         head, last,
@@ -125,7 +130,8 @@ import Prelude hiding ( length, null,
                         foldl, foldl1, foldr, foldr1,
                         all, any, and, or, sum, product, maximum, minimum,
                         scanl, scanl1, scanr, scanr1,
-                        enumFromTo, enumFromThenTo )
+                        enumFromTo, enumFromThenTo,
+                        mapM, mapM_ )
 
 import Data.Typeable ( Typeable1, gcast1 )
 import Data.Data ( Data, DataType, mkNorepType )
@@ -177,10 +183,6 @@ unstream s = new (New.unstream s)
 "clone/new [Vector]" forall p.
   clone (new p) = p
 
- #-}
-
-{-# RULES
-
 "inplace [Vector]"
   forall (f :: forall m. Monad m => MStream m a -> MStream m a) m.
   New.unstream (inplace f (stream (new m))) = New.transform f m
@@ -217,53 +219,16 @@ unstreamR s = new (New.unstreamR s)
 "New.unstreamR/streamR/new [Vector]" forall p.
   New.unstreamR (streamR (new p)) = p
 
- #-}
-
-{-# RULES
-
-"inplace [Vector]"
+"inplace right [Vector]"
   forall (f :: forall m. Monad m => MStream m a -> MStream m a) m.
   New.unstreamR (inplace f (streamR (new m))) = New.transformR f m
 
-"uninplace [Vector]"
+"uninplace right [Vector]"
   forall (f :: forall m. Monad m => MStream m a -> MStream m a) m.
   streamR (new (New.transformR f m)) = inplace f (streamR (new m))
 
  #-}
 
-
--- Destructive operations
--- ----------------------
-
--- | Destructively initialise a vector.
-create :: Vector v a => (forall s. ST s (Mutable v s a)) -> v a
-{-# INLINE create #-}
-create p = new (New.create p)
-
--- | Apply a destructive operation to a vector. The operation is applied to a
--- copy of the vector unless it can be safely performed in place.
-modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
-{-# INLINE modify #-}
-modify p = new . New.modify p . clone
-
--- | Copy an immutable vector into a mutable one. The two vectors must have
--- the same length. This is not checked.
-unsafeCopy
-  :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
-{-# INLINE unsafeCopy #-}
-unsafeCopy dst src = UNSAFE_CHECK(check) "unsafeCopy" "length mismatch"
-                                         (M.length dst == length src)
-                   $ (dst `seq` src `seq` basicUnsafeCopy dst src)
-           
--- | Copy an immutable vector into a mutable one. The two vectors must have the
--- same length.
-copy
-  :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
-{-# INLINE copy #-}
-copy dst src = BOUNDS_CHECK(check) "copy" "length mismatch"
-                                          (M.length dst == length src)
-             $ unsafeCopy dst src
-
 -- Length
 -- ------
 
@@ -539,7 +504,7 @@ unsafeDrop n v = unsafeSlice n (length v - n) v
 
 unsafeAccum_stream
   :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
-{-# INLINE unsafeAccum_stream #-}
+{-# INLINE_STREAM unsafeAccum_stream #-}
 unsafeAccum_stream f v s = s `seq` modify (\mv -> M.unsafeAccum f mv s) v
 
 unsafeAccum :: Vector v a => (a -> b -> a) -> v a -> [(Int,b)] -> v a
@@ -558,7 +523,7 @@ unsafeAccumulate_ f v is xs
   = unsafeAccum_stream f v (Stream.zipWith (,) (stream is) (stream xs))
 
 accum_stream :: Vector v a => (a -> b -> a) -> v a -> Stream (Int,b) -> v a
-{-# INLINE accum_stream #-}
+{-# INLINE_STREAM accum_stream #-}
 accum_stream f v s = s `seq` modify (\mv -> M.accum f mv s) v
 
 accum :: Vector v a => (a -> b -> a) -> v a -> [(Int,b)] -> v a
@@ -578,7 +543,7 @@ accumulate_ f v is xs = accum_stream f v (Stream.zipWith (,) (stream is)
                                         
 
 unsafeUpdate_stream :: Vector v a => v a -> Stream (Int,a) -> v a
-{-# INLINE unsafeUpdate_stream #-}
+{-# INLINE_STREAM unsafeUpdate_stream #-}
 unsafeUpdate_stream v s = s `seq` modify (\mv -> M.unsafeUpdate mv s) v
 
 unsafeUpd :: Vector v a => v a -> [(Int, a)] -> v a
@@ -595,7 +560,7 @@ unsafeUpdate_ v is w
   = unsafeUpdate_stream v (Stream.zipWith (,) (stream is) (stream w))
 
 update_stream :: Vector v a => v a -> Stream (Int,a) -> v a
-{-# INLINE update_stream #-}
+{-# INLINE_STREAM update_stream #-}
 update_stream v s = s `seq` modify (\mv -> M.update mv s) v
 
 (//) :: Vector v a => v a -> [(Int, a)] -> v a
@@ -1276,6 +1241,116 @@ fromListN :: Vector v a => Int -> [a] -> v a
 {-# INLINE fromListN #-}
 fromListN n = unstream . Stream.fromListN n
 
+unstreamM :: (Vector v a, Monad m) => MStream m a -> m (v a)
+{-# INLINE_STREAM unstreamM #-}
+unstreamM s = do
+                xs <- MStream.toList s
+                return $ unstream $ Stream.unsafeFromList (MStream.size s) xs
+
+-- Monadic operations
+-- ------------------
+
+-- FIXME: specialise various combinators for ST and IO?
+
+-- | Perform the monadic action the given number of times and store the
+-- results in a vector.
+replicateM :: (Monad m, Vector v a) => Int -> m a -> m (v a)
+{-# INLINE replicateM #-}
+replicateM n m = fromListN n `Monad.liftM` Monad.replicateM n m
+
+-- | Apply the monadic action to all elements of the vector, yielding a vector
+-- of results
+mapM :: (Monad m, Vector v a, Vector v b) => (a -> m b) -> v a -> m (v b)
+{-# INLINE mapM #-}
+mapM f = unstreamM . Stream.mapM f . stream
+
+-- | Apply the monadic action to all elements of a vector and ignore the
+-- results
+mapM_ :: (Monad m, Vector v a) => (a -> m b) -> v a -> m ()
+{-# INLINE mapM_ #-}
+mapM_ f = Stream.mapM_ f . stream
+
+-- | Apply the monadic action to all elements of the vector, yielding a vector
+-- of results
+forM :: (Monad m, Vector v a, Vector v b) => v a -> (a -> m b) -> m (v b)
+{-# INLINE forM #-}
+forM as f = mapM f as
+
+-- | Apply the monadic action to all elements of a vector and ignore the
+-- results
+forM_ :: (Monad m, Vector v a) => v a -> (a -> m b) -> m ()
+{-# INLINE forM_ #-}
+forM_ as f = mapM_ f as
+
+-- | Zip the two vectors with the monadic action and yield a vector of results
+zipWithM :: (Monad m, Vector v a, Vector v b, Vector v c)
+         => (a -> b -> m c) -> v a -> v b -> m (v c)
+{-# INLINE zipWithM #-}
+zipWithM f as bs = unstreamM $ Stream.zipWithM f (stream as) (stream bs)
+
+-- | Zip the two vectors with the monadic action and ignore the results
+zipWithM_ :: (Monad m, Vector v a, Vector v b)
+          => (a -> b -> m c) -> v a -> v b -> m ()
+{-# INLINE zipWithM_ #-}
+zipWithM_ f as bs = Stream.zipWithM_ f (stream as) (stream bs)
+
+-- | Drop elements that do not satisfy the monadic predicate
+filterM :: (Monad m, Vector v a) => (a -> m Bool) -> v a -> m (v a)
+{-# INLINE filterM #-}
+filterM f = unstreamM . Stream.filterM f . stream
+
+-- | Monadic fold
+foldM :: (Monad m, Vector v b) => (a -> b -> m a) -> a -> v b -> m a
+{-# INLINE foldM #-}
+foldM m z = Stream.foldM m z . stream
+
+-- | Monadic fold over non-empty vectors
+fold1M :: (Monad m, Vector v a) => (a -> a -> m a) -> v a -> m a
+{-# INLINE fold1M #-}
+fold1M m = Stream.fold1M m . stream
+
+-- | Monadic fold with strict accumulator
+foldM' :: (Monad m, Vector v b) => (a -> b -> m a) -> a -> v b -> m a
+{-# INLINE foldM' #-}
+foldM' m z = Stream.foldM' m z . stream
+
+-- | Monad fold over non-empty vectors with strict accumulator
+fold1M' :: (Monad m, Vector v a) => (a -> a -> m a) -> v a -> m a
+{-# INLINE fold1M' #-}
+fold1M' m = Stream.fold1M' m . stream
+
+-- Destructive operations
+-- ----------------------
+
+-- | Destructively initialise a vector.
+create :: Vector v a => (forall s. ST s (Mutable v s a)) -> v a
+{-# INLINE create #-}
+create p = new (New.create p)
+
+-- | Apply a destructive operation to a vector. The operation modifies a
+-- copy of the vector unless it can be safely performed in place.
+modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a
+{-# INLINE modify #-}
+modify p = new . New.modify p . clone
+
+-- | Copy an immutable vector into a mutable one. The two vectors must have
+-- the same length. This is not checked.
+unsafeCopy
+  :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
+{-# INLINE unsafeCopy #-}
+unsafeCopy dst src = UNSAFE_CHECK(check) "unsafeCopy" "length mismatch"
+                                         (M.length dst == length src)
+                   $ (dst `seq` src `seq` basicUnsafeCopy dst src)
+           
+-- | Copy an immutable vector into a mutable one. The two vectors must have the
+-- same length.
+copy
+  :: (PrimMonad m, Vector v a) => Mutable v (PrimState m) a -> v a -> m ()
+{-# INLINE copy #-}
+copy dst src = BOUNDS_CHECK(check) "copy" "length mismatch"
+                                          (M.length dst == length src)
+             $ unsafeCopy dst src
+
 -- Utilities for defining Data instances
 -- -------------------------------------