content: {-# LANGUAGE Rank2Types, FlexibleContexts #-}
  
  -- |
  -- Module      : Data.Vector.Generic.New
  -- Copyright   : (c) Roman Leshchinskiy 2008-2010
  -- License     : BSD-style
  --
  -- Maintainer  : Roman Leshchinskiy <rl@cse.unsw.edu.au>
  -- Stability   : experimental
  -- Portability : non-portable
  -- 
  -- Purely functional interface to initialisation of mutable vectors
  --
  
  module Data.Vector.Generic.New (
    New(..), create, run, runPrim, apply, modify, modifyWithStream,
    unstream, transform, unstreamR, transformR,
    slice, init, tail, take, drop,
    unsafeSlice, unsafeInit, unsafeTail
  ) where
  
  import qualified Data.Vector.Generic.Mutable as MVector
  import           Data.Vector.Generic.Mutable ( MVector )
  
  import           Data.Vector.Generic.Base ( Vector, Mutable )
  
  import           Data.Vector.Fusion.Stream ( Stream, MStream )
  import qualified Data.Vector.Fusion.Stream as Stream
  
  import Control.Monad.Primitive
  import Control.Monad.ST ( ST )
  import Control.Monad  ( liftM )
  import Prelude hiding ( init, tail, take, drop, reverse, map, filter )
  
  #include "vector.h"
  
  data New v a = New (forall s. ST s (Mutable v s a))
  
  create :: (forall s. ST s (Mutable v s a)) -> New v a
  {-# INLINE create #-}
  create p = New p
  
  run :: New v a -> ST s (Mutable v s a)
  {-# INLINE run #-}
  run (New p) = p
  
  runPrim :: PrimMonad m => New v a -> m (Mutable v (PrimState m) a)
  {-# INLINE runPrim #-}
  runPrim (New p) = primToPrim p
  
  apply :: (forall s. Mutable v s a -> Mutable v s a) -> New v a -> New v a
  {-# INLINE apply #-}
  apply f (New p) = New (liftM f p)
  
  modify :: (forall s. Mutable v s a -> ST s ()) -> New v a -> New v a
  {-# INLINE modify #-}
  modify f (New p) = New (do { v <- p; f v; return v })
  
  modifyWithStream :: (forall s. Mutable v s a -> Stream b -> ST s ())
                   -> New v a -> Stream b -> New v a
  {-# INLINE_STREAM modifyWithStream #-}
  modifyWithStream f (New p) s = s `seq` New (do { v <- p; f v s; return v })
  
  unstream :: Vector v a => Stream a -> New v a
  {-# INLINE_STREAM unstream #-}
  unstream s = s `seq` New (MVector.unstream s)
  
  transform :: Vector v a =>
          (forall m. Monad m => MStream m a -> MStream m a) -> New v a -> New v a
  {-# INLINE_STREAM transform #-}
  transform f (New p) = New (MVector.transform f =<< p)
  
  {-# RULES
  
  "transform/transform [New]"
    forall (f :: forall m. Monad m => MStream m a -> MStream m a)
           (g :: forall m. Monad m => MStream m a -> MStream m a)
           p .
    transform f (transform g p) = transform (f . g) p
  
  "transform/unstream [New]"
    forall (f :: forall m. Monad m => MStream m a -> MStream m a)
           s.
    transform f (unstream s) = unstream (f s)
  
   #-}
  
  
  unstreamR :: Vector v a => Stream a -> New v a
  {-# INLINE_STREAM unstreamR #-}
  unstreamR s = s `seq` New (MVector.unstreamR s)
  
  transformR :: Vector v a =>
          (forall m. Monad m => MStream m a -> MStream m a) -> New v a -> New v a
  {-# INLINE_STREAM transformR #-}
  transformR f (New p) = New (MVector.transformR f =<< p)
  
  {-# RULES
  
  "transformR/transformR [New]"
    forall (f :: forall m. Monad m => MStream m a -> MStream m a)
           (g :: forall m. Monad m => MStream m a -> MStream m a)
           p .
    transformR f (transformR g p) = transformR (f . g) p
  
  "transformR/unstreamR [New]"
    forall (f :: forall m. Monad m => MStream m a -> MStream m a)
           s.
    transformR f (unstreamR s) = unstreamR (f s)
  
   #-}
  
  slice :: Vector v a => Int -> Int -> New v a -> New v a
  {-# INLINE_STREAM slice #-}
  slice i n m = apply (MVector.slice i n) m
  
  init :: Vector v a => New v a -> New v a
  {-# INLINE_STREAM init #-}
  init m = apply MVector.init m
  
  tail :: Vector v a => New v a -> New v a
  {-# INLINE_STREAM tail #-}
  tail m = apply MVector.tail m
  
  take :: Vector v a => Int -> New v a -> New v a
  {-# INLINE_STREAM take #-}
  take n m = apply (MVector.take n) m
  
  drop :: Vector v a => Int -> New v a -> New v a
  {-# INLINE_STREAM drop #-}
  drop n m = apply (MVector.drop n) m
  
  unsafeSlice :: Vector v a => Int -> Int -> New v a -> New v a
  {-# INLINE_STREAM unsafeSlice #-}
  unsafeSlice i n m = apply (MVector.unsafeSlice i n) m
  
  unsafeInit :: Vector v a => New v a -> New v a
  {-# INLINE_STREAM unsafeInit #-}
  unsafeInit m = apply MVector.unsafeInit m
  
  unsafeTail :: Vector v a => New v a -> New v a
  {-# INLINE_STREAM unsafeTail #-}
  unsafeTail m = apply MVector.unsafeTail m
  
  {-# RULES
  
  "slice/unstream [New]" forall i n s.
    slice i n (unstream s) = unstream (Stream.slice i n s)
  
  "init/unstream [New]" forall s.
    init (unstream s) = unstream (Stream.init s)
  
  "tail/unstream [New]" forall s.
    tail (unstream s) = unstream (Stream.tail s)
  
  "take/unstream [New]" forall n s.
    take n (unstream s) = unstream (Stream.take n s)
  
  "drop/unstream [New]" forall n s.
    drop n (unstream s) = unstream (Stream.drop n s)
  
  "unsafeSlice/unstream [New]" forall i n s.
    unsafeSlice i n (unstream s) = unstream (Stream.slice i n s)
  
  "unsafeInit/unstream [New]" forall s.
    unsafeInit (unstream s) = unstream (Stream.init s)
  
  "unsafeTail/unstream [New]" forall s.
    unsafeTail (unstream s) = unstream (Stream.tail s)
  
    #-}
  
  