Haddock comments
[darcs-mirrors/vector.git] / Data / Vector / IVector.hs
index ee5d655..7b072f3 100644 (file)
@@ -1,9 +1,52 @@
-{-# LANGUAGE Rank2Types, MultiParamTypeClasses, BangPatterns, CPP #-}
+{-# LANGUAGE Rank2Types, MultiParamTypeClasses #-}
+-- |
+-- Module      : Data.Vector.IVector
+-- Copyright   : (c) Roman Leshchinskiy 2008
+-- License     : BSD-style
+--
+-- Maintainer  : rl@cse.unsw.edu.au
+-- Stability   : experimental
+-- Portability : non-portable
+-- 
+-- Generic interface to pure vectors
+--
 
 #include "phases.h"
 
-module Data.Vector.IVector
-where
+module Data.Vector.IVector (
+  -- * Immutable vectors
+  IVector,
+
+  -- * Length information
+  length,
+
+  -- * Construction
+  empty, singleton, cons, snoc, replicate, (++),
+
+  -- * Subvectors
+  take, drop,
+
+  -- * Mapping and zipping
+  map, zipWith,
+
+  -- * Filtering
+  filter, takeWhile, dropWhile,
+
+  -- * Folding
+ foldl, foldl1, foldl', foldl1', foldr, foldr1,
+
+  -- * Conversion to/from lists
+  toList, fromList,
+
+  -- * Conversion to/from Streams
+  stream, unstream,
+
+  -- * MVector-based initialisation
+  create,
+
+  -- * Unsafe functions
+  unsafeSlice, unsafeIndex
+) where
 
 import qualified Data.Vector.MVector as MVector
 import           Data.Vector.MVector ( MVector )
@@ -20,17 +63,44 @@ import Prelude hiding ( length,
                         filter, takeWhile, dropWhile,
                         foldl, foldl1, foldr, foldr1 )
 
+-- | Class of immutable vectors. Just like with 'MVector', the type of the
+-- elements can be restricted by using GADTs.
+--
 class IVector v a where
+  -- | Construct a pure vector from a monadic initialiser.
   create       :: (forall mv m. MVector mv m a => m (mv m a)) -> v a
 
+  -- | Length of the vector
   length       :: v a -> Int
+
+  -- | Yield a part of the vector without copying it. No range checks!
   unsafeSlice  :: v a -> Int -> Int -> v a
 
+  -- | Apply the given function to the element at the given position. This
+  -- interface prevents us from being too lazy. Suppose we had
+  --
+  -- > unsafeIndex' :: v a -> Int -> a
+  --
+  -- instead. Now, if we wanted to copy a vector, we'd do something like
+  --
+  -- > copy mv v ... = ... unsafeWrite mv i (unsafeIndex' v i) ...
+  --
+  -- For lazy vectors, the indexing would not be evaluated which means that we
+  -- would retain a reference to the original vector in each element we write.
+  -- This would be bad!
+  --
+  -- With 'unsafeIndex', we can do
+  --
+  -- > copy mv v ... = ... unsafeIndex v i (unsafeWrite mv i) ...
+  --
+  -- which does not have this problem.
+  --
   unsafeIndex  :: v a -> Int -> (a -> b) -> b
 
+-- | Convert a vector to a 'Stream'
 stream :: IVector v a => v a -> Stream a
 {-# INLINE_STREAM stream #-}
-stream !v = Stream.unfold get 0 `Stream.sized` Exact n
+stream v = v `seq` (Stream.unfold get 0 `Stream.sized` Exact n)
   where
     n = length v
 
@@ -38,6 +108,7 @@ stream !v = Stream.unfold get 0 `Stream.sized` Exact n
     get i | i < n     = unsafeIndex v i $ \x -> Just (x, i+1)
           | otherwise = Nothing
 
+-- | Create a vector from a 'Stream'
 unstream :: IVector v a => Stream a -> v a
 {-# INLINE_STREAM unstream #-}
 unstream s = create (MVector.unstream s)
@@ -52,27 +123,33 @@ unstream s = create (MVector.unstream s)
 -- Construction
 -- ------------
 
+-- | Empty vector
 empty :: IVector v a => v a
 {-# INLINE empty #-}
 empty = unstream Stream.empty
 
+-- | Vector with exaclty one element
 singleton :: IVector v a => a -> v a
 {-# INLINE singleton #-}
 singleton x = unstream (Stream.singleton x)
 
+-- | Vector of the given length with the given value in each position
 replicate :: IVector v a => Int -> a -> v a
 {-# INLINE replicate #-}
 replicate n = unstream . Stream.replicate n
 
+-- | Prepend an element
 cons :: IVector v a => a -> v a -> v a
 {-# INLINE cons #-}
 cons x = unstream . Stream.cons x . stream
 
+-- | Append an element
 snoc :: IVector v a => v a -> a -> v a
 {-# INLINE snoc #-}
 snoc v = unstream . Stream.snoc (stream v)
 
 infixr 5 ++
+-- | Concatenate two vectors
 (++) :: IVector v a => v a -> v a -> v a
 {-# INLINE (++) #-}
 v ++ w = unstream (stream v Stream.++ stream w)
@@ -80,10 +157,12 @@ v ++ w = unstream (stream v Stream.++ stream w)
 -- Subarrays
 -- ---------
 
+-- | Copy the first @n@ elements to a new vector.
 take :: IVector v a => Int -> v a -> v a
 {-# INLINE take #-}
 take n = unstream . Stream.take n . stream
 
+-- | Copy all but the first @n@ elements to a new vectors.
 drop :: IVector v a => Int -> v a -> v a
 {-# INLINE drop #-}
 drop n = unstream . Stream.drop n . stream
@@ -91,10 +170,12 @@ drop n = unstream . Stream.drop n . stream
 -- Mapping/zipping
 -- ---------------
 
+-- | Map a function over a vector
 map :: (IVector v a, IVector v b) => (a -> b) -> v a -> v b
 {-# INLINE map #-}
 map f = unstream . Stream.map f . stream
 
+-- | Zip two vectors with the given function.
 zipWith :: (IVector v a, IVector v b, IVector v c) => (a -> b -> c) -> v a -> v b -> v c
 {-# INLINE zipWith #-}
 zipWith f xs ys = unstream (Stream.zipWith f (stream xs) (stream ys))
@@ -102,14 +183,19 @@ zipWith f xs ys = unstream (Stream.zipWith f (stream xs) (stream ys))
 -- Filtering
 -- ---------
 
+-- | Drop elements which do not satisfy the predicate
 filter :: IVector v a => (a -> Bool) -> v a -> v a
 {-# INLINE filter #-}
 filter f = unstream . Stream.filter f . stream
 
+-- | Copy the longest prefix of elements satisfying the predicate to a new
+-- vector
 takeWhile :: IVector v a => (a -> Bool) -> v a -> v a
 {-# INLINE takeWhile #-}
 takeWhile f = unstream . Stream.takeWhile f . stream
 
+-- | Drop the longest prefix of elements that satisfy the predicate and copy
+-- the rest to a new vector.
 dropWhile :: IVector v a => (a -> Bool) -> v a -> v a
 {-# INLINE dropWhile #-}
 dropWhile f = unstream . Stream.dropWhile f . stream
@@ -117,34 +203,42 @@ dropWhile f = unstream . Stream.dropWhile f . stream
 -- Folding
 -- -------
 
+-- | Left fold
 foldl :: IVector v b => (a -> b -> a) -> a -> v b -> a
 {-# INLINE foldl #-}
 foldl f z = Stream.foldl f z . stream
 
+-- | Lefgt fold on non-empty vectors
 foldl1 :: IVector v a => (a -> a -> a) -> v a -> a
 {-# INLINE foldl1 #-}
 foldl1 f = Stream.foldl1 f . stream
 
+-- | Left fold with strict accumulator
 foldl' :: IVector v b => (a -> b -> a) -> a -> v b -> a
 {-# INLINE foldl' #-}
 foldl' f z = Stream.foldl' f z . stream
 
+-- | Left fold on non-empty vectors with strict accumulator
 foldl1' :: IVector v a => (a -> a -> a) -> v a -> a
 {-# INLINE foldl1' #-}
 foldl1' f = Stream.foldl1' f . stream
 
+-- | Right fold
 foldr :: IVector v a => (a -> b -> b) -> b -> v a -> b
 {-# INLINE foldr #-}
 foldr f z = Stream.foldr f z . stream
 
+-- | Right fold on non-empty vectors
 foldr1 :: IVector v a => (a -> a -> a) -> v a -> a
 {-# INLINE foldr1 #-}
 foldr1 f = Stream.foldr1 f . stream
 
+-- | Convert a vector to a list
 toList :: IVector v a => v a -> [a]
 {-# INLINE toList #-}
 toList = Stream.toList . stream
 
+-- | Convert a list to a vector
 fromList :: IVector v a => [a] -> v a
 {-# INLINE fromList #-}
 fromList = unstream . Stream.fromList