Add 'indexed' function
[darcs-mirrors/vector.git] / Data / Vector.hs
index cb67f39..48a0e7f 100644 (file)
@@ -32,7 +32,7 @@ module Data.Vector (
   length, null,
 
   -- ** Indexing
-  (!), head, last,
+  (!), (!?), head, last,
   unsafeIndex, unsafeHead, unsafeLast,
 
   -- ** Monadic indexing
@@ -40,7 +40,7 @@ module Data.Vector (
   unsafeIndexM, unsafeHeadM, unsafeLastM,
 
   -- ** Extracting subvectors (slicing)
-  slice, init, tail, take, drop,
+  slice, init, tail, take, drop, splitAt,
   unsafeSlice, unsafeInit, unsafeTail, unsafeTake, unsafeDrop,
 
   -- * Construction
@@ -81,6 +81,9 @@ module Data.Vector (
 
   -- * Elementwise operations
 
+  -- ** Indexing
+  indexed,
+
   -- ** Mapping
   map, imap, concatMap,
 
@@ -140,7 +143,7 @@ module Data.Vector (
   G.convert,
 
   -- ** Mutable vectors
-  thaw, thawMany, copy, unsafeCopy
+  freeze, thaw, copy, unsafeFreeze, unsafeThaw, unsafeCopy
 ) where
 
 import qualified Data.Vector.Generic as G
@@ -155,7 +158,7 @@ import Control.Monad.Primitive
 import Prelude hiding ( length, null,
                         replicate, (++), concat,
                         head, last,
-                        init, tail, take, drop, reverse,
+                        init, tail, take, drop, splitAt, reverse,
                         map, concatMap,
                         zipWith, zipWith3, zip, zip3, unzip, unzip3,
                         filter, takeWhile, dropWhile, span, break,
@@ -171,6 +174,8 @@ import qualified Prelude
 import Data.Typeable ( Typeable )
 import Data.Data     ( Data(..) )
 
+import Data.Monoid   ( Monoid(..) )
+
 -- | Boxed vectors, supporting efficient slicing.
 data Vector a = Vector {-# UNPACK #-} !Int
                        {-# UNPACK #-} !Int
@@ -190,10 +195,14 @@ instance Data a => Data (Vector a) where
 type instance G.Mutable Vector = MVector
 
 instance G.Vector Vector a where
-  {-# INLINE unsafeFreeze #-}
-  unsafeFreeze (MVector i n marr)
+  {-# INLINE basicUnsafeFreeze #-}
+  basicUnsafeFreeze (MVector i n marr)
     = Vector i n `liftM` unsafeFreezeArray marr
 
+  {-# INLINE basicUnsafeThaw #-}
+  basicUnsafeThaw (Vector i n arr)
+    = MVector i n `liftM` unsafeThawArray arr
+
   {-# INLINE basicLength #-}
   basicLength (Vector _ n _) = n
 
@@ -228,6 +237,16 @@ instance Ord a => Ord (Vector a) where
   {-# INLINE (>=) #-}
   xs >= ys = Stream.cmp (G.stream xs) (G.stream ys) /= LT
 
+instance Monoid (Vector a) where
+  {-# INLINE mempty #-}
+  mempty = empty
+
+  {-# INLINE mappend #-}
+  mappend = (++)
+
+  {-# INLINE mconcat #-}
+  mconcat = concat
+
 -- Length information
 -- ------------------
 
@@ -249,6 +268,11 @@ null = G.null
 {-# INLINE (!) #-}
 (!) = (G.!)
 
+-- | O(1) Safe indexing
+(!?) :: Vector a -> Int -> Maybe a
+{-# INLINE (!?) #-}
+(!?) = (G.!?)
+
 -- | /O(1)/ First element
 head :: Vector a -> a
 {-# INLINE head #-}
@@ -366,6 +390,14 @@ drop :: Int -> Vector a -> Vector a
 {-# INLINE drop #-}
 drop = G.drop
 
+-- | /O(1)/ Yield the first @n@ elements paired with the remainder without copying.
+--
+-- Note that @'splitAt' n v@ is equivalent to @('take' n v, 'drop' n v)@
+-- but slightly more efficient.
+{-# INLINE splitAt #-}
+splitAt :: Int -> Vector a -> (Vector a, Vector a)
+splitAt = G.splitAt
+
 -- | /O(1)/ Yield a slice of the vector without copying. The vector must
 -- contain at least @i+n@ elements but this is not checked.
 unsafeSlice :: Int   -- ^ @i@ starting index
@@ -520,7 +552,8 @@ replicateM = G.replicateM
 -- @
 create :: (forall s. ST s (MVector s a)) -> Vector a
 {-# INLINE create #-}
-create = G.create
+-- NOTE: eta-expanded due to http://hackage.haskell.org/trac/ghc/ticket/4120
+create p = G.create p
 
 
 
@@ -696,7 +729,15 @@ unsafeBackpermute = G.unsafeBackpermute
 -- @
 modify :: (forall s. MVector s a -> ST s ()) -> Vector a -> Vector a
 {-# INLINE modify #-}
-modify = G.modify
+modify p = G.modify p
+
+-- Indexing
+-- --------
+
+-- | /O(n)/ Pair each element in a vector with its index
+indexed :: Vector a -> Vector (Int,a)
+{-# INLINE indexed #-}
+indexed = G.indexed
 
 -- Mapping
 -- -------
@@ -1285,25 +1326,36 @@ fromListN = G.fromListN
 -- Conversions - Mutable vectors
 -- -----------------------------
 
+-- | /O(1)/ Unsafe convert a mutable vector to an immutable one without
+-- copying. The mutable vector may not be used after this operation.
+unsafeFreeze :: PrimMonad m => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE unsafeFreeze #-}
+unsafeFreeze = G.unsafeFreeze
+
+-- | /O(1)/ Unsafely convert an immutable vector to a mutable one without
+-- copying. The immutable vector may not be used after this operation.
+unsafeThaw :: PrimMonad m => Vector a -> m (MVector (PrimState m) a)
+{-# INLINE unsafeThaw #-}
+unsafeThaw = G.unsafeThaw
+
 -- | /O(n)/ Yield a mutable copy of the immutable vector.
 thaw :: PrimMonad m => Vector a -> m (MVector (PrimState m) a)
 {-# INLINE thaw #-}
 thaw = G.thaw
 
--- | /O(n)/ Yield a mutable vector containing copies of each vector in the
--- list.
-thawMany :: PrimMonad m => [Vector a] -> m (MVector (PrimState m) a)
-{-# INLINE thawMany #-}
-thawMany = G.thawMany
+-- | /O(n)/ Yield an immutable copy of the mutable vector.
+freeze :: PrimMonad m => MVector (PrimState m) a -> m (Vector a)
+{-# INLINE freeze #-}
+freeze = G.freeze
 
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length.
+-- have the same length. This is not checked.
 unsafeCopy :: PrimMonad m => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE unsafeCopy #-}
 unsafeCopy = G.unsafeCopy
            
 -- | /O(n)/ Copy an immutable vector into a mutable one. The two vectors must
--- have the same length. This is not checked.
+-- have the same length.
 copy :: PrimMonad m => MVector (PrimState m) a -> Vector a -> m ()
 {-# INLINE copy #-}
 copy = G.copy