    module Data.Array.Repa.Repr.Vector
            ( V, Array (..)
            , computeVectorS,  computeVectorP
            , fromListVector
            , fromVector
            , toVector)
    where
    import Data.Array.Repa.Shape
    import Data.Array.Repa.Base
    import Data.Array.Repa.Eval
    import qualified Data.Vector            as V
    import qualified Data.Vector.Mutable    as VM
    import Control.Monad

    -- | Arrays represented as boxed vectors.
    --
    --   This representation should only be used when your element type doesn't
    --   have an `Unbox` instsance. If it does, then use the Unboxed `U`
    --   representation will be faster.
    data V

    -- | Read elements from a boxed vector array.
    instance Source V a where
     data Array V sh a
            = AVector !sh !(V.Vector a)

     linearIndex (AVector _ vec) ix
            = vec V.! ix
     {-# INLINE linearIndex #-}

     unsafeLinearIndex (AVector _ vec) ix
            = vec `V.unsafeIndex` ix
     {-# INLINE unsafeLinearIndex #-}

     extent (AVector sh _)
            = sh
     {-# INLINE extent #-}

     deepSeqArray (AVector sh vec) x
      = sh `deepSeq` vec `seq` x
     {-# INLINE deepSeqArray #-}

    deriving instance (Show sh, Show e)
            => Show (Array V sh e)

    deriving instance (Read sh, Read e)
            => Read (Array V sh e)

    -- Fill -----------------------------------------------------------------------
    -- | Filling of boxed vector arrays.
    instance Target V e where
     data MVec V e
      = MVector (VM.IOVector e)

     newMVec n
      = liftM MVector (VM.new n)
     {-# INLINE newMVec #-}

     unsafeWriteMVec (MVector v) ix
      = VM.unsafeWrite v ix
     {-# INLINE unsafeWriteMVec #-}

     unsafeFreezeMVec sh (MVector mvec)
      = do  vec     <- V.unsafeFreeze mvec
            return  $  AVector sh vec
     {-# INLINE unsafeFreezeMVec #-}

     deepSeqMVec !_vec x
      = x
     {-# INLINE deepSeqMVec #-}

     touchMVec _
      = return ()
     {-# INLINE touchMVec #-}

    -- Conversions ----------------------------------------------------------------
    -- | Sequential computation of array elements.
    --
    --   * This is an alias for `compute` with a more specific type.
    --
    computeVectorS
            :: (Shape sh, Load r1 sh e)
            => Array r1 sh e -> Array V sh e
    computeVectorS   = computeS
    {-# INLINE computeVectorS #-}

    -- | Parallel computation of array elements.
    computeVectorP
            :: (Shape sh, Load r1 sh e, Monad m)
            => Array r1 sh e -> m (Array V sh e)
    computeVectorP   = computeP
    {-# INLINE computeVectorP #-}

    -- | O(n). Convert a list to a boxed vector array.
    --
    --   * This is an alias for `fromList` with a more specific type.
    --
    fromListVector :: Shape sh => sh -> [a] -> Array V sh a
    fromListVector  = fromList
    {-# INLINE fromListVector #-}

    -- | O(1). Wrap a boxed vector as an array.
    fromVector
            :: Shape sh
            => sh -> V.Vector e -> Array V sh e
    fromVector sh vec
            = AVector sh vec
    {-# INLINE fromVector #-}

    -- | O(1). Unpack a boxed vector from an array.
    toVector :: Array V sh e -> V.Vector e
    toVector (AVector _ vec)
            = vec
    {-# INLINE toVector #-}