diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,37 @@
+# 0.5.0
+
+* Remove `Show` instance from `Value`.
+* Addition of `unsafeCreateArray`, `unsafeCreateArray_` and `unsafeCreateArrayS`
+* Remove `Comp` argument from functions that ignore it and set it to `Seq`:
+  * `createArrayS_`, `createArrayS`, `createArrayST_`, `createArrayST`
+  * `unfoldrPrimM_`, `iunfoldrPrimM_`, `unfoldrPrimM`, `iunfoldrPrimM`
+  * `unfoldlPrimM_`, `iunfoldlPrimM_`, `unfoldlPrimM`, `iunfoldlPrimM`
+* Addition of `fromStorableVector` and `fromStorableMVector`
+* Modify `toMutableByteArray` to produce a copy if dealing with slice.
+* Addition of `toByteArrayM`, `toMutableByteArrayM`
+* Change `replicate` to produce delayed load array `DL`
+* Export unsafe stencil functions from `Data.Array.Massiv.Unsafe`, rather than from
+  `Data.Massiv.Array.Stencil.Unsafe`.
+* Implement `unsafeMapStencil` and deprecate `mapStencilUnsafe` and `forStencilUnsafe`
+* Addition of `castToBuilder`
+* Addition of conversion functions:
+  * `unwrapNormalForm` and `evalNormalForm`
+  * `toBoxedVector`, `toBoxedMVector`, `evalBoxedVector` and `evalBoxedMVector`
+  * `unwrapByteArray` and `unwrapMutableByteArray`
+  * `toPrimitiveVector`, `toPrimitiveMVector`, `fromPrimitiveVector` and
+  `fromPrimitiveMVector`
+  * `toStorableVector`, `toStorableMVector`, `fromStorableVector` and `fromStorableMVector`
+  * `fromUnboxedVector` and `fromUnboxedMVector`
+  * `unsafeBoxedArray`, `unsafeNormalBoxedArray`, `unsafeFromBoxedVector`
+* Removed deprecated `traverseAR`, `itraverseAR`, `traversePrimR` and `itraversePrimR`
+* Removed: `imapMR`, `imapMR`, `iforMR`, and `iforMR`
+* Renamed:
+  * `withMArray` to `withMArray_`,
+  * `withMArrayS` to `withMArrayS_` and
+  * `withMArrayST` to `withMArrayST_`
+* Added versions that keep the artifact of mutable action: `withMArray`, `withMArrayS`,
+  `withMArrayST`.
+
 # 0.4.5
 
 * Addition of `computeIO` and `computePrimM`
@@ -26,7 +60,6 @@
 * Fix incorrect loading of `DW` arrays of dimension higher than 3
 * Addition of `foldOuterSlice`, `ifoldOuterSlice`, `foldInnerSlice` and
   `ifoldInnerSlice`. Fix for [#56](https://github.com/lehins/massiv/issues/56)
-
 
 # 0.4.2
 
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Alexey Kuleshevich (c) 2017-2019
+Copyright Alexey Kuleshevich (c) 2017-2020
 
 All rights reserved.
 
diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.4.5.0
+version:             0.5.0.0
 synopsis:            Massiv (Массив) is an Array Library.
 description:         Multi-dimensional Arrays with fusion, stencils and parallel computation.
 homepage:            https://github.com/lehins/massiv
@@ -7,7 +7,7 @@
 license-file:        LICENSE
 author:              Alexey Kuleshevich
 maintainer:          alexey@kuleshevi.ch
-copyright:           2018-2019 Alexey Kuleshevich
+copyright:           2018-2020 Alexey Kuleshevich
 category:            Data, Data Structures, Parallelism
 build-type:          Custom
 extra-source-files:  README.md
@@ -38,19 +38,19 @@
                      , Data.Massiv.Array.Delayed
                      , Data.Massiv.Array.Manifest
                      , Data.Massiv.Array.Manifest.Vector
-                     , Data.Massiv.Array.Manifest.Vector.Stream
                      , Data.Massiv.Array.Mutable
                      , Data.Massiv.Array.Mutable.Algorithms
                      , Data.Massiv.Array.Mutable.Atomic
                      , Data.Massiv.Array.Numeric
                      , Data.Massiv.Array.Numeric.Integral
                      , Data.Massiv.Array.Stencil
-                     , Data.Massiv.Array.Stencil.Unsafe
                      , Data.Massiv.Array.Unsafe
                      , Data.Massiv.Core
                      , Data.Massiv.Core.Index
                      , Data.Massiv.Core.List
                      , Data.Massiv.Core.Operations
+                     , Data.Massiv.Vector
+                     , Data.Massiv.Vector.Stream
 
   other-modules:       Data.Massiv.Array.Delayed.Interleaved
                      , Data.Massiv.Array.Delayed.Pull
@@ -63,6 +63,7 @@
                      , Data.Massiv.Array.Manifest.Primitive
                      , Data.Massiv.Array.Manifest.Storable
                      , Data.Massiv.Array.Manifest.Unboxed
+                     , Data.Massiv.Array.Mutable.Internal
                      , Data.Massiv.Array.Ops.Construct
                      , Data.Massiv.Array.Ops.Fold
                      , Data.Massiv.Array.Ops.Fold.Internal
@@ -72,6 +73,7 @@
                      , Data.Massiv.Array.Ops.Transform
                      , Data.Massiv.Array.Stencil.Convolution
                      , Data.Massiv.Array.Stencil.Internal
+                     , Data.Massiv.Array.Stencil.Unsafe
                      , Data.Massiv.Core.Common
                      , Data.Massiv.Core.Exception
                      , Data.Massiv.Core.Index.Internal
@@ -79,6 +81,7 @@
                      , Data.Massiv.Core.Index.Stride
                      , Data.Massiv.Core.Index.Tuple
                      , Data.Massiv.Core.Iterator
+                     , Data.Massiv.Vector.Unsafe
   build-depends:       base >= 4.9 && < 5
                      , bytestring
                      , data-default-class
diff --git a/src/Data/Massiv/Array.hs b/src/Data/Massiv/Array.hs
--- a/src/Data/Massiv/Array.hs
+++ b/src/Data/Massiv/Array.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_GHC -fno-warn-duplicate-exports #-}
 -- |
 -- Module      : Data.Massiv.Array
 -- Copyright   : (c) Alexey Kuleshevich 2018-2019
@@ -97,6 +98,8 @@
   , convertProxy
   , fromRaggedArrayM
   , fromRaggedArray'
+  -- * Vector
+  , module Data.Massiv.Vector
   -- * Size
   , size
   , elemsCount
@@ -114,17 +117,6 @@
   , evaluate'
   -- * Mapping
   , module Data.Massiv.Array.Ops.Map
-  -- * Filtering
-  -- ** Maybe
-  , mapMaybeS
-  , imapMaybeS
-  , mapMaybeM
-  , imapMaybeM
-  -- ** Predicate
-  , filterS
-  , ifilterS
-  , filterM
-  , ifilterM
   -- * Folding
 
   -- $folding
@@ -155,6 +147,7 @@
   , module Data.Massiv.Array.Numeric
   ) where
 
+import Data.Massiv.Vector
 import Data.Massiv.Array.Delayed
 import Data.Massiv.Array.Delayed.Stream
 import Data.Massiv.Array.Manifest
@@ -174,50 +167,6 @@
 import Prelude as P hiding (all, and, any, enumFromTo, foldl, foldr, mapM,
                             mapM_, maximum, minimum, or, product, replicate, splitAt,
                             sum, zip)
-
-
--- | Similar to `mapMaybeM`, but map with an index aware function.
---
--- @since 0.4.1
-imapMaybeS :: Source r ix a => (ix -> a -> Maybe b) -> Array r ix a -> Array DS Ix1 b
-imapMaybeS f arr =
-  mapMaybeS (uncurry f) $ makeArrayR D (getComp arr) (size arr) $ \ ix -> (ix, unsafeIndex arr ix)
-{-# INLINE imapMaybeS #-}
-
--- | Similar to `mapMaybeM`, but map with an index aware function.
---
--- @since 0.4.1
-imapMaybeM ::
-     (Source r ix a, Applicative f) => (ix -> a -> f (Maybe b)) -> Array r ix a -> f (Array DS Ix1 b)
-imapMaybeM f arr =
-  mapMaybeM (uncurry f) $ makeArrayR D (getComp arr) (size arr) $ \ ix -> (ix, unsafeIndex arr ix)
-{-# INLINE imapMaybeM #-}
-
--- | Similar to `filterS`, but map with an index aware function.
---
--- @since 0.4.1
-ifilterS :: Source r ix a => (ix -> a -> Bool) -> Array r ix a -> Array DS Ix1 a
-ifilterS f =
-  imapMaybeS $ \ix e ->
-    if f ix e
-      then Just e
-      else Nothing
-{-# INLINE ifilterS #-}
-
-
--- | Similar to `filterM`, but map with an index aware function.
---
--- @since 0.4.1
-ifilterM ::
-     (Source r ix a, Applicative f) => (ix -> a -> f Bool) -> Array r ix a -> f (Array DS Ix1 a)
-ifilterM f =
-  imapMaybeM $ \ix e ->
-    (\p ->
-       if p
-         then Just e
-         else Nothing) <$>
-    f ix e
-{-# INLINE ifilterM #-}
 
 
 {- $folding
diff --git a/src/Data/Massiv/Array/Delayed/Pull.hs b/src/Data/Massiv/Array/Delayed/Pull.hs
--- a/src/Data/Massiv/Array/Delayed/Pull.hs
+++ b/src/Data/Massiv/Array/Delayed/Pull.hs
@@ -21,11 +21,12 @@
   , delay
   , eq
   , ord
+  , imap
   ) where
 
 import qualified Data.Foldable as F
 import Data.Massiv.Array.Ops.Fold.Internal as A
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
+import Data.Massiv.Vector.Stream as S (steps)
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.Operations
 import Data.Massiv.Core.List (L, showArrayList, showsArrayPrec)
@@ -69,8 +70,9 @@
 instance Index ix => Source D ix e where
   unsafeIndex = INDEX_CHECK("(Source D ix e).unsafeIndex", size, dIndex)
   {-# INLINE unsafeIndex #-}
-  -- unsafeLinearSlice ix sz arr = unsafeExtract ix sz (unsafeResize sz arr)
-  -- {-# INLINE unsafeLinearSlice #-}
+  unsafeLinearSlice !o !sz arr =
+    DArray (dComp arr) sz $ \ !i -> unsafeIndex arr (fromLinearIndex (size arr) (i + o))
+  {-# INLINE unsafeLinearSlice #-}
 
 
 instance ( Index ix
@@ -155,7 +157,13 @@
 instance Index ix => Stream D ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.steps . imap (,)
+  {-# INLINE toStreamIx #-}
 
+-- | Map an index aware function over an array
+imap :: Source r ix e' => (ix -> e' -> e) -> Array r ix e' -> Array D ix e
+imap f !arr = DArray (getComp arr) (size arr) (\ !ix -> f ix (unsafeIndex arr ix))
+{-# INLINE imap #-}
 
 instance (Index ix, Num e) => Num (Array D ix e) where
   (+)         = unsafeLiftArray2 (+)
diff --git a/src/Data/Massiv/Array/Delayed/Push.hs b/src/Data/Massiv/Array/Delayed/Push.hs
--- a/src/Data/Massiv/Array/Delayed/Push.hs
+++ b/src/Data/Massiv/Array/Delayed/Push.hs
@@ -150,7 +150,7 @@
     {-# INLINE load #-}
 {-# INLINE appendOuterM #-}
 
--- | Concat arrays together along the most most dimension. Inner dimensions must agree
+-- | Concat arrays together along the outer most dimension. Inner dimensions must agree
 -- for all arrays in the list, otherwise `SizeMismatchException`.
 --
 -- @since 0.4.4
diff --git a/src/Data/Massiv/Array/Delayed/Stream.hs b/src/Data/Massiv/Array/Delayed/Stream.hs
--- a/src/Data/Massiv/Array/Delayed/Stream.hs
+++ b/src/Data/Massiv/Array/Delayed/Stream.hs
@@ -15,63 +15,64 @@
   ( DS(..)
   , Array (..)
   , toStreamArray
+  , toStreamM
+  , toStreamIxM
   , toSteps
   , fromSteps
-  , takeS
-  , dropS
-  , filterS
-  , filterM
-  , mapMaybeS
-  , mapMaybeM
-  , catMaybesS
-  , traverseS
-  , unfoldr
-  , unfoldrN
+  , fromStepsM
   ) where
 
 import Control.Applicative
 import Control.Monad (void)
 import Data.Coerce
+import Data.Foldable
 import Data.Massiv.Array.Delayed.Pull
-import qualified Data.Massiv.Array.Manifest.Vector.Stream as S
+import qualified Data.Massiv.Vector.Stream as S
 import Data.Massiv.Core.Common
 import GHC.Exts
 import Prelude hiding (take, drop)
 import Data.Vector.Fusion.Bundle.Size (upperBound)
 
--- | Delayed array that will be loaded in an interleaved fashion during parallel
--- computation.
+-- | Delayed stream array that represents a sequence of values that can be loaded
+-- sequentially. Important distinction from other arrays is that its size might no be
+-- known until it is computed.
 data DS = DS
 
 newtype instance Array DS Ix1 e = DSArray
   { dsArray :: S.Steps S.Id e
   }
 
--- | /O(1)/ - Convert delayed stream arrray into `Steps`.
+-- | /O(1)/ - Convert delayed stream array into `Steps`.
 --
 -- @since 0.4.1
 toSteps :: Array DS Ix1 e -> Steps Id e
 toSteps = coerce
 {-# INLINE toSteps #-}
 
--- | /O(1)/ - Convert `Steps` into delayed stream arrray
+-- | /O(1)/ - Convert `Steps` into delayed stream array
 --
 -- @since 0.4.1
 fromSteps :: Steps Id e -> Array DS Ix1 e
 fromSteps = coerce
 {-# INLINE fromSteps #-}
 
+-- | /O(1)/ - Convert monadic `Steps` into delayed stream array
+--
+-- @since 0.5.0
+fromStepsM :: Monad m => Steps m e -> m (Array DS Ix1 e)
+fromStepsM = fmap DSArray . S.transSteps
+{-# INLINE fromStepsM #-}
 
-instance Functor (Array DS Ix1) where
 
-  fmap f = coerce . fmap f . dsArray
+instance Functor (Array DS Ix1) where
+  fmap f = coerce . S.map f . dsArray
   {-# INLINE fmap #-}
+  (<$) e = coerce . (e <$) . dsArray
+  {-# INLINE (<$) #-}
 
 instance Applicative (Array DS Ix1) where
-
   pure = fromSteps . S.singleton
   {-# INLINE pure #-}
-
   (<*>) a1 a2 = fromSteps (S.zipWith ($) (coerce a1) (coerce a2))
   {-# INLINE (<*>) #-}
 
@@ -81,48 +82,57 @@
 #endif
 
 instance Monad (Array DS Ix1) where
-
   return = fromSteps . S.singleton
   {-# INLINE return #-}
-
   (>>=) arr f = coerce (S.concatMap (coerce . f) (dsArray arr))
   {-# INLINE (>>=) #-}
 
 
 instance Foldable (Array DS Ix1) where
-
-  foldr f acc = S.foldr f acc . toSteps
+  foldr f acc = S.unId . S.foldrLazy f acc . toSteps
   {-# INLINE foldr #-}
-
-  length = S.length . coerce
+  foldl f acc = S.unId . S.foldlLazy f acc . toSteps
+  {-# INLINE foldl #-}
+  foldl' f acc = S.unId . S.foldl f acc . toSteps
+  {-# INLINE foldl' #-}
+  foldr1 f = S.unId . S.foldr1Lazy f . toSteps
+  {-# INLINE foldr1 #-}
+  foldl1 f = S.unId . S.foldl1Lazy f . toSteps
+  {-# INLINE foldl1 #-}
+  toList = S.toList . coerce
+  {-# INLINE toList #-}
+  length = S.unId . S.length . coerce
   {-# INLINE length #-}
+  null = S.unId . S.null . coerce
+  {-# INLINE null #-}
+  sum = S.unId . S.foldl (+) 0 . toSteps
+  {-# INLINE sum #-}
+  product = S.unId . S.foldl (*) 1 . toSteps
+  {-# INLINE product #-}
+  maximum = S.unId . S.foldl1 max . toSteps
+  {-# INLINE maximum #-}
+  minimum = S.unId . S.foldl1 min . toSteps
+  {-# INLINE minimum #-}
 
-  -- TODO: add more
 
 
 instance Semigroup (Array DS Ix1 e) where
-
   (<>) a1 a2 = fromSteps (coerce a1 `S.append` coerce a2)
   {-# INLINE (<>) #-}
 
 
 instance Monoid (Array DS Ix1 e) where
-
   mempty = DSArray S.empty
   {-# INLINE mempty #-}
-
   mappend = (<>)
   {-# INLINE mappend #-}
 
 instance IsList (Array DS Ix1 e) where
   type Item (Array DS Ix1 e) = e
-
   fromList = fromSteps . S.fromList
   {-# INLINE fromList #-}
-
   fromListN n = fromSteps . S.fromListN n
   {-# INLINE fromListN #-}
-
   toList = S.toList . coerce
   {-# INLINE toList #-}
 
@@ -130,6 +140,8 @@
 instance S.Stream DS Ix1 e where
   toStream = coerce
   {-# INLINE toStream #-}
+  toStreamIx = S.indexed . coerce
+  {-# INLINE toStreamIx #-}
 
 
 -- | Flatten an array into a stream of values.
@@ -139,6 +151,21 @@
 toStreamArray = DSArray . S.steps
 {-# INLINE toStreamArray #-}
 
+-- | /O(1)/ - Convert an array into monadic `Steps`
+--
+-- @since 0.5.0
+toStreamM :: (Stream r ix e, Monad m) => Array r ix e -> Steps m e
+toStreamM = S.transStepsId . toStream
+{-# INLINE toStreamM #-}
+
+-- | /O(1)/ - Convert an array into monadic `Steps`
+--
+-- @since 0.5.0
+toStreamIxM :: (Stream r ix e, Monad m) => Array r ix e -> Steps m (ix, e)
+toStreamIxM = S.transStepsId . toStreamIx
+{-# INLINE toStreamIxM #-}
+
+
 instance Construct DS Ix1 e where
   setComp _ arr = arr
   {-# INLINE setComp #-}
@@ -153,7 +180,7 @@
 
 -- | /O(n)/ - `size` implementation.
 instance Load DS Ix1 e where
-  size = coerce . S.length . coerce
+  size = coerce . S.unId . S.length . coerce
   {-# INLINE size #-}
 
   maxSize = coerce . upperBound . stepsSize . dsArray
@@ -202,147 +229,3 @@
 --   {-# INLINE loadArrayWithStrideM #-}
 
 
--- | Right unfolding function. Useful when we do not have any idea ahead of time on how
--- many elements the vector will have.
---
--- ====__Example__
---
--- >>> import Data.Massiv.Array as A
--- >>> unfoldr (\i -> if i < 9 then Just (i*i, i + 1) else Nothing) (0 :: Int)
--- Array DS Seq (Sz1 9)
---   [ 0, 1, 4, 9, 16, 25, 36, 49, 64 ]
--- >>> unfoldr (\i -> if sqrt i < 3 then Just (i * i, i + 1) else Nothing) (0 :: Double)
--- Array DS Seq (Sz1 9)
---   [ 0.0, 1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0, 64.0 ]
---
--- @since 0.4.1
-unfoldr :: (s -> Maybe (e, s)) -> s -> Array DS Ix1 e
-unfoldr f = DSArray . S.unfoldr f
-{-# INLINE unfoldr #-}
-
-
--- | Right unfolding function with limited number of elements.
---
--- ==== __Example__
---
--- >>> import Data.Massiv.Array as A
--- >>> unfoldrN 9 (\i -> Just (i*i, i + 1)) (0 :: Int)
--- Array DS Seq (Sz1 9)
---   [ 0, 1, 4, 9, 16, 25, 36, 49, 64 ]
---
--- @since 0.4.1
-unfoldrN ::
-     Sz1
-  -- ^ Maximum number of elements that the vector can have
-  -> (s -> Maybe (e, s))
-  -- ^ Unfolding function. Stops when `Nothing` is reaturned or maximum number of elements
-  -- is reached.
-  -> s -- ^ Inititial element.
-  -> Array DS Ix1 e
-unfoldrN n f = DSArray . S.unfoldrN n f
-{-# INLINE unfoldrN #-}
-
--- | Sequentially filter out elements from the array according to the supplied predicate.
---
--- ==== __Example__
---
--- >>> import Data.Massiv.Array as A
--- >>> arr = makeArrayR D Seq (Sz2 3 4) fromIx2
--- >>> arr
--- Array D Seq (Sz (3 :. 4))
---   [ [ (0,0), (0,1), (0,2), (0,3) ]
---   , [ (1,0), (1,1), (1,2), (1,3) ]
---   , [ (2,0), (2,1), (2,2), (2,3) ]
---   ]
--- >>> filterS (even . fst) arr
--- Array DS Seq (Sz1 8)
---   [ (0,0), (0,1), (0,2), (0,3), (2,0), (2,1), (2,2), (2,3) ]
---
--- @since 0.4.1
-filterS :: S.Stream r ix e => (e -> Bool) -> Array r ix e -> Array DS Ix1 e
-filterS f = DSArray . S.filter f . S.toStream
-{-# INLINE filterS #-}
-
--- | Sequentially filter out elements from the array according to the supplied applicative predicate.
---
--- ==== __Example__
---
--- >>> import Data.Massiv.Array as A
--- >>> arr = makeArrayR D Seq (Sz2 3 4) fromIx2
--- >>> arr
--- Array D Seq (Sz (3 :. 4))
---   [ [ (0,0), (0,1), (0,2), (0,3) ]
---   , [ (1,0), (1,1), (1,2), (1,3) ]
---   , [ (2,0), (2,1), (2,2), (2,3) ]
---   ]
--- >>> filterM (Just . odd . fst) arr
--- Just (Array DS Seq (Sz1 4)
---   [ (1,0), (1,1), (1,2), (1,3) ]
--- )
--- >>> filterM (\ix@(_, j) -> print ix >> return (even j)) arr
--- (0,0)
--- (0,1)
--- (0,2)
--- (0,3)
--- (1,0)
--- (1,1)
--- (1,2)
--- (1,3)
--- (2,0)
--- (2,1)
--- (2,2)
--- (2,3)
--- Array DS Seq (Sz1 6)
---   [ (0,0), (0,2), (1,0), (1,2), (2,0), (2,2) ]
---
--- @since 0.4.1
-filterM :: (S.Stream r ix e, Applicative f) => (e -> f Bool) -> Array r ix e -> f (Array DS Ix1 e)
-filterM f arr = DSArray <$> S.filterA f (S.toStream arr)
-{-# INLINE filterM #-}
-
-
--- | Apply a function to each element of the array, while discarding `Nothing` and
--- keeping the `Maybe` result.
---
--- @since 0.4.1
-mapMaybeS :: S.Stream r ix a => (a -> Maybe b) -> Array r ix a -> Array DS Ix1 b
-mapMaybeS f = DSArray . S.mapMaybe f . S.toStream
-{-# INLINE mapMaybeS #-}
-
--- | Keep all `Maybe`s and discard the `Nothing`s.
---
--- @since 0.4.4
-catMaybesS :: S.Stream r ix (Maybe a) => Array r ix (Maybe a) -> Array DS Ix1 a
-catMaybesS = mapMaybeS id
-{-# INLINE catMaybesS #-}
-
-
--- | Similar to `mapMaybeS`, but with the use of `Applicative`
---
--- @since 0.4.1
-mapMaybeM ::
-     (S.Stream r ix a, Applicative f) => (a -> f (Maybe b)) -> Array r ix a -> f (Array DS Ix1 b)
-mapMaybeM f arr = DSArray <$> S.mapMaybeA f (S.toStream arr)
-{-# INLINE mapMaybeM #-}
-
--- | Extract first @n@ elements from the stream vector
---
--- @since 0.4.1
-takeS :: Stream r ix e => Sz1 -> Array r ix e -> Array DS Ix1 e
-takeS n = fromSteps . S.take (unSz n) . S.toStream
-{-# INLINE takeS #-}
-
--- | Keep all but first @n@ elements from the stream vector.
---
--- @since 0.4.1
-dropS :: Stream r ix e => Sz1 -> Array r ix e -> Array DS Ix1 e
-dropS n = fromSteps . S.drop (unSz n) . S.toStream
-{-# INLINE dropS #-}
-
-
--- | Traverse a stream with an applicative action.
---
--- @since 0.4.5
-traverseS :: (S.Stream r ix a, Applicative f) => (a -> f b) -> Array r ix a -> f (Array DS Ix1 b)
-traverseS f = fmap fromSteps . S.traverse f . S.toStream
-{-# INLINE traverseS #-}
diff --git a/src/Data/Massiv/Array/Manifest.hs b/src/Data/Massiv/Array/Manifest.hs
--- a/src/Data/Massiv/Array/Manifest.hs
+++ b/src/Data/Massiv/Array/Manifest.hs
@@ -25,6 +25,9 @@
   , Uninitialized(..)
   -- ** Conversion
   -- $boxed_conversion_note
+  , unwrapNormalForm
+  , evalNormalForm
+  -- *** Primitive Boxed Array
   , unwrapArray
   , evalArray
   , unwrapMutableArray
@@ -33,23 +36,40 @@
   , evalNormalFormArray
   , unwrapNormalFormMutableArray
   , evalNormalFormMutableArray
+  -- *** Boxed Vector
+  , toBoxedVector
+  , toBoxedMVector
+  , evalBoxedVector
+  , evalBoxedMVector
   -- * Primitive
   , P(..)
   , Prim
   -- ** Conversion
+  -- *** Primitive ByteArray
   , toByteArray
+  , toByteArrayM
+  , unwrapByteArray
   , fromByteArray
   , fromByteArrayM
   , toMutableByteArray
+  , unwrapMutableByteArray
   , fromMutableByteArray
   , fromMutableByteArrayM
+  -- *** Primitive Vector
+  , toPrimitiveVector
+  , toPrimitiveMVector
+  , fromPrimitiveVector
+  , fromPrimitiveMVector
   -- * Storable
   , S(..)
   , Storable
   -- ** Conversion
+  -- *** Primitive Vector
   , toStorableVector
   , toStorableMVector
-  -- ** Direct Pointer Access
+  , fromStorableVector
+  , fromStorableMVector
+  -- *** Direct Pointer Access
   , withPtr
   -- * Unboxed
   , U(..)
@@ -57,12 +77,15 @@
   -- ** Conversion
   , toUnboxedVector
   , toUnboxedMVector
+  , fromUnboxedVector
+  , fromUnboxedMVector
   -- * ByteString Conversion
   , fromByteString
   , castFromByteString
   , toByteString
   , castToByteString
   , toBuilder
+  , castToBuilder
   ) where
 
 import Data.ByteString as S
@@ -106,15 +129,21 @@
 #else
   compute
 #endif
-  --fst $ unfoldrN (totalElem (size arr)) (\ !i -> Just (unsafeLinearIndex arr i, i + 1)) 0
 {-# INLINE toByteString #-}
 
--- | /O(n)/ - Conversion of array monoidally into a ByteString Builder.
+-- | /O(n)/ - Conversion of array monoidally into a ByteString `Builder`.
 --
 -- @since 0.2.1
 toBuilder :: Source r ix e => (e -> Builder) -> Array r ix e -> Builder
 toBuilder = foldMono
 {-# INLINE toBuilder #-}
+
+-- | /O(1)/ - Cast a storable array of `Word8` to ByteString `Builder`.
+--
+-- @since 0.5.0
+castToBuilder :: Array S ix Word8 -> Builder
+castToBuilder = byteString . castToByteString
+{-# INLINE castToBuilder #-}
 
 -- | /O(1)/ - Cast a `S`torable array into a strict `ByteString`
 --
diff --git a/src/Data/Massiv/Array/Manifest/Boxed.hs b/src/Data/Massiv/Array/Manifest/Boxed.hs
--- a/src/Data/Massiv/Array/Manifest/Boxed.hs
+++ b/src/Data/Massiv/Array/Manifest/Boxed.hs
@@ -10,7 +10,7 @@
 {-# LANGUAGE UndecidableInstances #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest.Boxed
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -20,6 +20,8 @@
   ( B(..)
   , N(..)
   , Array(..)
+  , unwrapNormalForm
+  , evalNormalForm
   , unwrapArray
   , evalArray
   , unwrapMutableArray
@@ -28,8 +30,15 @@
   , evalNormalFormArray
   , unwrapNormalFormMutableArray
   , evalNormalFormMutableArray
-  , castArrayToVector
-  , castVectorToArray
+  , toBoxedVector
+  , toBoxedMVector
+  , evalBoxedVector
+  , evalBoxedMVector
+  , evalNormalBoxedVector
+  , evalNormalBoxedMVector
+  , unsafeBoxedArray
+  , unsafeNormalBoxedArray
+  , unsafeFromBoxedVector
   , seqArray
   , deepseqArray
   ) where
@@ -45,7 +54,7 @@
 import Data.Massiv.Array.Delayed.Stream (DS)
 import Data.Massiv.Array.Manifest.Internal (M, computeAs, toManifest)
 import Data.Massiv.Array.Manifest.List as L
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
+import Data.Massiv.Vector.Stream as S (steps, isteps)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Array.Ops.Fold
 import Data.Massiv.Array.Ops.Fold.Internal
@@ -54,7 +63,7 @@
 import Data.Massiv.Core.List
 import qualified Data.Primitive.Array as A
 import qualified Data.Vector as VB
-import qualified Data.Vector.Mutable as VB
+import qualified Data.Vector.Mutable as MVB
 import GHC.Base (build)
 import GHC.Exts as GHC
 import Prelude hiding (mapM)
@@ -80,9 +89,10 @@
 -- spine strict, but elements are strict to Weak Head Normal Form (WHNF) only.
 data B = B deriving Show
 
-data instance Array B ix e = BArray { bComp :: !Comp
-                                    , bSize :: !(Sz ix)
-                                    , bData :: {-# UNPACK #-} !(A.Array e)
+data instance Array B ix e = BArray { bComp   :: !Comp
+                                    , bSize   :: !(Sz ix)
+                                    , bOffset :: {-# UNPACK #-} !Int
+                                    , bData   :: {-# UNPACK #-} !(A.Array e)
                                     }
 
 instance (Ragged L ix e, Show e) => Show (Array B ix e) where
@@ -114,15 +124,19 @@
   setComp c arr = arr { bComp = c }
   {-# INLINE setComp #-}
 
-  makeArray !comp !sz f = unsafePerformIO $ generateArray comp sz (\ !ix -> return $! f ix)
-  {-# INLINE makeArray #-}
+  makeArrayLinear !comp !sz f = unsafePerformIO $ generateArrayLinear comp sz (\ !i -> return $! f i)
+  {-# INLINE makeArrayLinear #-}
 
 instance Index ix => Source B ix e where
-  unsafeLinearIndex (BArray _ _ a) =
-    INDEX_CHECK("(Source B ix e).unsafeLinearIndex", Sz . sizeofArray, A.indexArray) a
+  unsafeLinearIndex (BArray _ _sz o a) i =
+    INDEX_CHECK("(Source B ix e).unsafeLinearIndex",
+                SafeSz . sizeofArray, A.indexArray) a (i + o)
   {-# INLINE unsafeLinearIndex #-}
 
+  unsafeLinearSlice i k (BArray c _ o a) = BArray c k (o + i) a
+  {-# INLINE unsafeLinearSlice #-}
 
+
 instance Index ix => Resize B ix where
   unsafeResize !sz !arr = arr { bSize = sz }
   {-# INLINE unsafeResize #-}
@@ -157,35 +171,38 @@
 
 instance Index ix => Manifest B ix e where
 
-  unsafeLinearIndexM (BArray _ _ a) =
-    INDEX_CHECK("(Manifest B ix e).unsafeLinearIndexM", Sz . sizeofArray, A.indexArray) a
+  unsafeLinearIndexM (BArray _ _sz o a) i =
+    INDEX_CHECK("(Manifest B ix e).unsafeLinearIndexM",
+                SafeSz . sizeofArray, A.indexArray) a (i + o)
   {-# INLINE unsafeLinearIndexM #-}
 
 
 instance Index ix => Mutable B ix e where
-  data MArray s B ix e = MBArray !(Sz ix) {-# UNPACK #-} !(A.MutableArray s e)
+  data MArray s B ix e = MBArray !(Sz ix) {-# UNPACK #-} !Int {-# UNPACK #-} !(A.MutableArray s e)
 
-  msize (MBArray sz _) = sz
+  msize (MBArray sz _ _) = sz
   {-# INLINE msize #-}
 
-  unsafeThaw (BArray _ sz a) = MBArray sz <$> A.unsafeThawArray a
+  unsafeThaw (BArray _ sz o a) = MBArray sz o <$> A.unsafeThawArray a
   {-# INLINE unsafeThaw #-}
 
-  unsafeFreeze comp (MBArray sz ma) = BArray comp sz <$> A.unsafeFreezeArray ma
+  unsafeFreeze comp (MBArray sz o ma) = BArray comp sz o <$> A.unsafeFreezeArray ma
   {-# INLINE unsafeFreeze #-}
 
-  unsafeNew sz = MBArray sz <$> A.newArray (totalElem sz) uninitialized
+  unsafeNew sz = MBArray sz 0 <$> A.newArray (totalElem sz) uninitialized
   {-# INLINE unsafeNew #-}
 
   initialize _ = return ()
   {-# INLINE initialize #-}
 
-  unsafeLinearRead (MBArray _ ma) =
-    INDEX_CHECK("(Mutable B ix e).unsafeLinearRead", Sz . sizeofMutableArray, A.readArray) ma
+  unsafeLinearRead (MBArray _ o ma) i =
+    INDEX_CHECK("(Mutable B ix e).unsafeLinearRead",
+                SafeSz . sizeofMutableArray, A.readArray) ma (i + o)
   {-# INLINE unsafeLinearRead #-}
 
-  unsafeLinearWrite (MBArray _ ma) i e = e `seq`
-    INDEX_CHECK("(Mutable B ix e).unsafeLinearWrite", Sz . sizeofMutableArray, A.writeArray) ma i e
+  unsafeLinearWrite (MBArray _sz o ma) i e = e `seq`
+    INDEX_CHECK("(Mutable B ix e).unsafeLinearWrite",
+                SafeSz . sizeofMutableArray, A.writeArray) ma (i + o) e
   {-# INLINE unsafeLinearWrite #-}
 
 instance Index ix => Load B ix e where
@@ -202,6 +219,8 @@
 instance Index ix => Stream B ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.isteps
+  {-# INLINE toStreamIx #-}
 
 
 -- | Row-major sequential folding over a Boxed array.
@@ -218,7 +237,7 @@
   {-# INLINE foldr #-}
   foldr' = foldrS
   {-# INLINE foldr' #-}
-  null (BArray _ sz _) = totalElem sz == 0
+  null (BArray _ sz _ _) = totalElem sz == 0
   {-# INLINE null #-}
   length = totalElem . size
   {-# INLINE length #-}
@@ -288,9 +307,10 @@
   {-# INLINE makeArray #-}
 
 instance (Index ix, NFData e) => Source N ix e where
-  unsafeLinearIndex (NArray arr) =
-    INDEX_CHECK("(Source N ix e).unsafeLinearIndex", Sz . totalElem . size, unsafeLinearIndex) arr
+  unsafeLinearIndex (NArray arr) = unsafeLinearIndex arr
   {-# INLINE unsafeLinearIndex #-}
+  unsafeLinearSlice i k (NArray a) = NArray $ unsafeLinearSlice i k a
+  {-# INLINE unsafeLinearSlice #-}
 
 
 instance Index ix => Resize N ix where
@@ -329,8 +349,7 @@
 
 instance (Index ix, NFData e) => Manifest N ix e where
 
-  unsafeLinearIndexM (NArray arr) =
-    INDEX_CHECK("(Manifest N ix e).unsafeLinearIndexM", Sz . totalElem . size, unsafeLinearIndexM) arr
+  unsafeLinearIndexM (NArray arr) = unsafeLinearIndexM arr
   {-# INLINE unsafeLinearIndexM #-}
 
 
@@ -352,12 +371,10 @@
   initialize _ = return ()
   {-# INLINE initialize #-}
 
-  unsafeLinearRead (MNArray ma) =
-    INDEX_CHECK("(Mutable N ix e).unsafeLinearRead", Sz . totalElem . msize, unsafeLinearRead) ma
+  unsafeLinearRead (MNArray ma) = unsafeLinearRead ma
   {-# INLINE unsafeLinearRead #-}
 
-  unsafeLinearWrite (MNArray ma) i e = e `deepseq`
-    INDEX_CHECK("(Mutable N ix e).unsafeLinearWrite", Sz . totalElem . msize, unsafeLinearWrite) ma i e
+  unsafeLinearWrite (MNArray ma) i e = e `deepseq` unsafeLinearWrite ma i e
   {-# INLINE unsafeLinearWrite #-}
 
 instance (Index ix, NFData e) => Load N ix e where
@@ -371,9 +388,11 @@
 
 instance (Index ix, NFData e) => StrideLoad N ix e
 
-instance Index ix => Stream N ix e where
+instance (Index ix, NFData e) => Stream N ix e where
   toStream = toStream . coerce
   {-# INLINE toStream #-}
+  toStreamIx = toStreamIx . coerce
+  {-# INLINE toStreamIx #-}
 
 
 instance ( NFData e
@@ -397,26 +416,12 @@
 uninitialized :: a
 uninitialized = throw Uninitialized
 
-
--- -- | /O(1)/ - Unwrap a fully evaluated boxed array.
--- --
--- -- @since 0.2.1
--- unwrapNormalFormArray :: Array N ix e -> Array B ix e
--- unwrapNormalFormArray = bArray
--- {-# INLINE unwrapNormalFormArray #-}
-
--- -- | /O(1)/ - Unwrap a fully evaluated mutable boxed array.
--- --
--- -- @since 0.2.1
--- unwrapNormalFormMutableArray :: MArray s N ix e -> MArray s B ix e
--- unwrapNormalFormMutableArray (MNArray marr) = marr
--- {-# INLINE unwrapNormalFormMutableArray #-}
-
 ---------------------
 -- WHNF conversion --
 ---------------------
 
--- | /O(1)/ - Unwrap boxed array.
+-- | /O(1)/ - Unwrap boxed array. This will discard any possible slicing that has been
+-- applied to the array.
 --
 -- @since 0.2.1
 unwrapArray :: Array B ix e -> A.Array e
@@ -433,11 +438,13 @@
 evalArray = fromArraySeq (\a -> a `seqArray` a)
 {-# INLINE evalArray #-}
 
--- | /O(1)/ - Unwrap mutable boxed array.
+
+-- | /O(1)/ - Unwrap mutable boxed array. This will discard any possible slicing that has been
+-- applied to the array.
 --
 -- @since 0.2.1
 unwrapMutableArray :: MArray s B ix e -> A.MutableArray s e
-unwrapMutableArray (MBArray _ marr) = marr
+unwrapMutableArray (MBArray _ _ marr) = marr
 {-# INLINE unwrapMutableArray #-}
 
 
@@ -455,7 +462,8 @@
 -- NF conversion --
 -------------------
 
--- | /O(1)/ - Unwrap a fully evaluated boxed array.
+-- | /O(1)/ - Unwrap a fully evaluated boxed array. This will discard any possible slicing
+-- that has been applied to the array.
 --
 -- @since 0.2.1
 unwrapNormalFormArray :: Array N ix e -> A.Array e
@@ -474,11 +482,12 @@
 {-# INLINE evalNormalFormArray #-}
 
 
--- | /O(1)/ - Unwrap a fully evaluated mutable boxed array.
+-- | /O(1)/ - Unwrap a fully evaluated mutable boxed array. This will discard any possible
+-- slicing that has been applied to the array.
 --
 -- @since 0.2.1
 unwrapNormalFormMutableArray :: MArray s N ix e -> A.MutableArray s e
-unwrapNormalFormMutableArray (MNArray (MBArray _ marr)) = marr
+unwrapNormalFormMutableArray (MNArray marr) = unwrapMutableArray marr
 {-# INLINE unwrapNormalFormMutableArray #-}
 
 
@@ -502,10 +511,10 @@
   => (e -> m () -> m a)
   -> A.MutableArray (PrimState m) e
   -> m (MArray (PrimState m) B Ix1 e)
-fromMutableArraySeq with mbarr = do
-  let !sz = sizeofMutableArray mbarr
-  loopM_ 0 (< sz) (+ 1) (A.readArray mbarr >=> (`with` return ()))
-  return $! MBArray (Sz sz) mbarr
+fromMutableArraySeq with ma = do
+  let !sz = sizeofMutableArray ma
+  loopM_ 0 (< sz) (+ 1) (A.readArray ma >=> (`with` return ()))
+  return $! MBArray (SafeSz sz) 0 ma
 {-# INLINE fromMutableArraySeq #-}
 
 fromArraySeq ::
@@ -513,7 +522,7 @@
   -> Comp
   -> A.Array e
   -> a
-fromArraySeq with comp barr = with (BArray comp (Sz (sizeofArray barr)) barr)
+fromArraySeq with comp barr = with (BArray comp (SafeSz (sizeofArray barr)) 0 barr)
 {-# INLINE fromArraySeq #-}
 
 
@@ -527,21 +536,106 @@
 {-# INLINE deepseqArray #-}
 
 
--- | Helper function that converts a boxed `A.Array` into a `VB.Vector`. Supplied total number of
--- elements is assumed to be the same in the array as provided by the size.
-castArrayToVector :: A.Array a -> VB.Vector a
-castArrayToVector arr = runST $ do
-  marr <- A.unsafeThawArray arr
-  VB.unsafeFreeze $ VB.MVector 0 (sizeofArray arr) marr
-{-# INLINE castArrayToVector #-}
+-- | /O(n)/ - Compute all elements of a boxed array to NF (normal form)
+--
+-- @since 0.5.0
+unwrapNormalForm :: Array N ix e -> Array B ix e
+unwrapNormalForm = coerce
+{-# INLINE unwrapNormalForm #-}
 
+-- | /O(n)/ - Compute all elements of a boxed array to NF (normal form)
+--
+-- @since 0.5.0
+evalNormalForm :: (Index ix, NFData e) => Array B ix e -> Array N ix e
+evalNormalForm arr = arr `deepseqArray` NArray arr
+{-# INLINE evalNormalForm #-}
 
--- | Cast a Boxed Vector into an Array, but only if it wasn't previously sliced.
-castVectorToArray :: VB.Vector a -> Maybe (A.Array a)
-castVectorToArray v =
+-- | /O(1)/ - Converts a boxed `Array` into a `VB.Vector`.
+--
+-- @since 0.5.0
+toBoxedVector :: Index ix => Array B ix a -> VB.Vector a
+toBoxedVector arr = runST $ VB.unsafeFreeze . toBoxedMVector =<< unsafeThaw arr
+{-# INLINE toBoxedVector #-}
+
+-- | /O(1)/ - Converts a boxed `MArray` into a `VMB.MVector`.
+--
+-- @since 0.5.0
+toBoxedMVector :: Index ix => MArray s B ix a -> MVB.MVector s a
+toBoxedMVector (MBArray sz o marr) = MVB.MVector o (totalElem sz) marr
+{-# INLINE toBoxedMVector #-}
+
+-- | /O(n)/ - Convert a boxed vector and evaluate all elements to WHNF. Computation
+-- strategy will be respected during evaluation
+--
+-- @since 0.5.0
+evalBoxedVector :: Comp -> VB.Vector a -> Array B Ix1 a
+evalBoxedVector comp v = arr `seqArray` arr
+  where
+    arr = setComp comp $ unsafeFromBoxedVector v
+{-# INLINE evalBoxedVector #-}
+
+
+-- | /O(n)/ - Convert mutable boxed vector and evaluate all elements to WHNF
+-- sequentially. Both keep pointing to the same memory
+--
+-- @since 0.5.0
+evalBoxedMVector :: PrimMonad m => MVB.MVector (PrimState m) a -> m (MArray (PrimState m) B Ix1 a)
+evalBoxedMVector (MVB.MVector o k ma) = do
+  let marr = MBArray (SafeSz k) o ma
+  loopM_ o (< k) (+ 1) (A.readArray ma >=> (`seq` pure ()))
+  pure marr
+{-# INLINE evalBoxedMVector #-}
+
+
+-- | /O(n)/ - Cast a boxed vector without touching any elements. It is unsafe because it
+-- violates the invariant that all elements of `B` array are in WHNF.
+--
+-- @since 0.5.0
+unsafeFromBoxedVector :: VB.Vector a -> Array B Ix1 a
+unsafeFromBoxedVector v =
   runST $ do
-    VB.MVector start end marr <- VB.unsafeThaw v
-    if start == 0 && end == sizeofMutableArray marr
-      then Just <$> A.unsafeFreezeArray marr
-      else return Nothing
-{-# INLINE castVectorToArray #-}
+    MVB.MVector o k ma <- VB.unsafeThaw v
+    unsafeFreeze Seq $ MBArray (SafeSz k) o ma
+{-# INLINE unsafeFromBoxedVector #-}
+
+-- | /O(n)/ - Cast a boxed array. It is unsafe because it violates the invariant that all
+-- elements of `N` array are in NF.
+--
+-- @since 0.5.0
+unsafeBoxedArray :: A.Array e -> Array B Ix1 e
+unsafeBoxedArray = fromArraySeq id Seq
+{-# INLINE unsafeBoxedArray #-}
+
+
+-- | /O(n)/ - Cast a boxed array. It is unsafe because it violates the invariant that all
+-- elements of `N` array are in NF.
+--
+-- @since 0.5.0
+unsafeNormalBoxedArray :: Array B ix e -> Array N ix e
+unsafeNormalBoxedArray = coerce
+{-# INLINE unsafeNormalBoxedArray #-}
+
+-- | /O(n)/ - Convert mutable boxed vector and evaluate all elements to WHNF
+-- sequentially. Both keep pointing to the same memory
+--
+-- @since 0.5.0
+evalNormalBoxedMVector ::
+     (NFData a, PrimMonad m) => MVB.MVector (PrimState m) a -> m (MArray (PrimState m) N Ix1 a)
+evalNormalBoxedMVector (MVB.MVector o k ma) = do
+  let marr = MNArray (MBArray (SafeSz k) o ma)
+  loopM_ o (< k) (+ 1) (A.readArray ma >=> (`deepseq` pure ()))
+  pure marr
+{-# INLINE evalNormalBoxedMVector #-}
+
+-- | /O(n)/ - Convert a boxed vector and evaluate all elements to WHNF. Computation
+-- strategy will be respected during evaluation
+--
+-- @since 0.5.0
+evalNormalBoxedVector :: NFData a => Comp -> VB.Vector a -> Array N Ix1 a
+evalNormalBoxedVector comp v =
+  runST $ do
+    MVB.MVector o k ma <- VB.unsafeThaw v
+    arr <- unsafeFreeze comp $ MBArray (SafeSz k) o ma
+    arr `deepseqArray` pure (NArray arr)
+{-# INLINE evalNormalBoxedVector #-}
+
diff --git a/src/Data/Massiv/Array/Manifest/Internal.hs b/src/Data/Massiv/Array/Manifest/Internal.hs
--- a/src/Data/Massiv/Array/Manifest/Internal.hs
+++ b/src/Data/Massiv/Array/Manifest/Internal.hs
@@ -10,7 +10,7 @@
 {-# LANGUAGE UndecidableInstances #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest.Internal
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -50,7 +50,8 @@
 import Data.Massiv.Array.Delayed.Pull
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Array.Ops.Fold.Internal
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
+import Data.Massiv.Array.Mutable.Internal (unsafeCreateArray_)
+import Data.Massiv.Vector.Stream as S (steps, isteps)
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.List
 import Data.Maybe (fromMaybe)
@@ -128,6 +129,8 @@
 instance Index ix => Source M ix e where
   unsafeLinearIndex = mLinearIndex
   {-# INLINE unsafeLinearIndex #-}
+  unsafeLinearSlice ix sz arr = unsafeExtract ix sz (unsafeResize sz arr)
+  {-# INLINE unsafeLinearSlice #-}
 
 
 instance Index ix => Manifest M ix e where
@@ -198,6 +201,8 @@
 instance Index ix => Stream M ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.isteps
+  {-# INLINE toStreamIx #-}
 
 
 -- | Ensure that Array is computed, i.e. represented with concrete elements in memory, hence is the
@@ -373,7 +378,7 @@
 computeWithStride stride !arr =
   unsafePerformIO $ do
     let !sz = strideSize stride (size arr)
-    createArray_ (getComp arr) sz $ \scheduler marr ->
+    unsafeCreateArray_ (getComp arr) sz $ \scheduler marr ->
       loadArrayWithStrideM scheduler stride sz arr (unsafeLinearWrite marr)
 {-# INLINE computeWithStride #-}
 
@@ -513,3 +518,5 @@
           nextMArr <- unsafeThaw arr
           go (n + 1) arr' (iteration (n + 1) arr') nextMArr
 {-# INLINE iterateLoop #-}
+
+
diff --git a/src/Data/Massiv/Array/Manifest/Primitive.hs b/src/Data/Massiv/Array/Manifest/Primitive.hs
--- a/src/Data/Massiv/Array/Manifest/Primitive.hs
+++ b/src/Data/Massiv/Array/Manifest/Primitive.hs
@@ -4,13 +4,14 @@
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MagicHash #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE NamedFieldPuns #-}
 {-# LANGUAGE ScopedTypeVariables #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE UnboxedTuples #-}
 {-# LANGUAGE UndecidableInstances #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest.Primitive
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -20,10 +21,18 @@
   ( P(..)
   , Array(..)
   , Prim
+  , toPrimitiveVector
+  , toPrimitiveMVector
+  , fromPrimitiveVector
+  , fromPrimitiveMVector
   , toByteArray
-  , fromByteArrayM
+  , toByteArrayM
+  , unwrapByteArray
+  , unwrapMutableByteArray
   , fromByteArray
+  , fromByteArrayM
   , toMutableByteArray
+  , toMutableByteArrayM
   , fromMutableByteArrayM
   , fromMutableByteArray
   , shrinkMutableByteArray
@@ -44,13 +53,16 @@
 import Data.Massiv.Array.Delayed.Pull (eq, ord)
 import Data.Massiv.Array.Manifest.Internal
 import Data.Massiv.Array.Manifest.List as A
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.List
+import Data.Massiv.Vector.Stream as S (steps, isteps)
+import Data.Maybe (fromMaybe)
 import Data.Primitive (sizeOf)
 import Data.Primitive.ByteArray
 import Data.Primitive.Types
+import qualified Data.Vector.Primitive as VP
+import qualified Data.Vector.Primitive.Mutable as MVP
 import GHC.Base (Int(..))
 import GHC.Exts as GHC
 import Prelude hiding (mapM)
@@ -61,9 +73,10 @@
 -- | Representation for `Prim`itive elements
 data P = P deriving Show
 
-data instance Array P ix e = PArray { pComp :: !Comp
-                                    , pSize :: !(Sz ix)
-                                    , pData :: {-# UNPACK #-} !ByteArray
+data instance Array P ix e = PArray { pComp   :: !Comp
+                                    , pSize   :: !(Sz ix)
+                                    , pOffset :: {-# UNPACK #-} !Int
+                                    , pData   :: {-# UNPACK #-} !ByteArray
                                     }
 
 instance (Ragged L ix e, Show e, Prim e) => Show (Array P ix e) where
@@ -71,7 +84,7 @@
   showList = showArrayList
 
 instance Index ix => NFData (Array P ix e) where
-  rnf (PArray c sz a) = c `deepseq` sz `deepseq` a `seq` ()
+  rnf (PArray c sz o a) = c `deepseq` sz `deepseq` o `seq` a `seq` ()
   {-# INLINE rnf #-}
 
 instance (Prim e, Eq e, Index ix) => Eq (Array P ix e) where
@@ -90,12 +103,15 @@
   {-# INLINE makeArray #-}
 
 instance (Prim e, Index ix) => Source P ix e where
-  unsafeLinearIndex _pa@(PArray _ _ a) =
+  unsafeLinearIndex _arr@(PArray _ _ o a) i =
     INDEX_CHECK("(Source P ix e).unsafeLinearIndex",
-                Sz . elemsBA _pa, indexByteArray) a
+                SafeSz . elemsBA _arr, indexByteArray) a (i + o)
   {-# INLINE unsafeLinearIndex #-}
 
+  unsafeLinearSlice i k (PArray c _ o a) = PArray c k (i + o) a
+  {-# INLINE unsafeLinearSlice #-}
 
+
 instance Index ix => Resize P ix where
   unsafeResize !sz !arr = arr { pSize = sz }
   {-# INLINE unsafeResize #-}
@@ -151,65 +167,65 @@
 
 instance (Index ix, Prim e) => Manifest P ix e where
 
-  unsafeLinearIndexM _pa@(PArray _ _ a) =
+  unsafeLinearIndexM _pa@(PArray _ _sz o a) i =
     INDEX_CHECK("(Manifest P ix e).unsafeLinearIndexM",
-                Sz . elemsBA _pa, indexByteArray) a
+                const (Sz (totalElem _sz)), indexByteArray) a (i + o)
   {-# INLINE unsafeLinearIndexM #-}
 
 
 instance (Index ix, Prim e) => Mutable P ix e where
-  data MArray s P ix e = MPArray !(Sz ix) {-# UNPACK #-} !(MutableByteArray s)
+  data MArray s P ix e = MPArray !(Sz ix) {-# UNPACK #-} !Int {-# UNPACK #-} !(MutableByteArray s)
 
-  msize (MPArray sz _) = sz
+  msize (MPArray sz _ _) = sz
   {-# INLINE msize #-}
 
-  unsafeThaw (PArray _ sz a) = MPArray sz <$> unsafeThawByteArray a
+  unsafeThaw (PArray _ sz o a) = MPArray sz o <$> unsafeThawByteArray a
   {-# INLINE unsafeThaw #-}
 
-  unsafeFreeze comp (MPArray sz a) = PArray comp sz <$> unsafeFreezeByteArray a
+  unsafeFreeze comp (MPArray sz o a) = PArray comp sz o <$> unsafeFreezeByteArray a
   {-# INLINE unsafeFreeze #-}
 
   unsafeNew sz
-    | n <= (maxBound :: Int) `div` eSize = MPArray sz <$> newByteArray (n * eSize)
+    | n <= (maxBound :: Int) `div` eSize = MPArray sz 0 <$> newByteArray (n * eSize)
     | otherwise = error $ "Array size is too big: " ++ show sz
     where !n = totalElem sz
           !eSize = sizeOf (undefined :: e)
   {-# INLINE unsafeNew #-}
 
-  initialize (MPArray sz mba) =
-    fillByteArray mba 0 (totalElem sz * sizeOf (undefined :: e)) 0
+  initialize (MPArray sz o mba) =
+    fillByteArray mba o (totalElem sz * sizeOf (undefined :: e)) 0
   {-# INLINE initialize #-}
 
-  unsafeLinearRead _mpa@(MPArray _ ma) =
+  unsafeLinearRead _mpa@(MPArray _sz o ma) i =
     INDEX_CHECK("(Mutable P ix e).unsafeLinearRead",
-                Sz . elemsMBA _mpa, readByteArray) ma
+                const (Sz (totalElem _sz)), readByteArray) ma (i + o)
   {-# INLINE unsafeLinearRead #-}
 
-  unsafeLinearWrite _mpa@(MPArray _ ma) =
+  unsafeLinearWrite _mpa@(MPArray _sz o ma) i =
     INDEX_CHECK("(Mutable P ix e).unsafeLinearWrite",
-                Sz . elemsMBA _mpa, writeByteArray) ma
+                const (Sz (totalElem _sz)), writeByteArray) ma (i + o)
   {-# INLINE unsafeLinearWrite #-}
 
-  unsafeLinearSet (MPArray _ ma) offset (SafeSz sz) = setByteArray ma offset sz
+  unsafeLinearSet (MPArray _ o ma) offset (SafeSz sz) = setByteArray ma (offset + o) sz
   {-# INLINE unsafeLinearSet #-}
 
-  unsafeLinearCopy (MPArray _ maFrom) iFrom (MPArray _ maTo) iTo (Sz k) =
-    copyMutableByteArray maTo (iTo * esz) maFrom (iFrom * esz) (k * esz)
+  unsafeLinearCopy (MPArray _ oFrom maFrom) iFrom (MPArray _ oTo maTo) iTo (Sz k) =
+    copyMutableByteArray maTo ((oTo + iTo) * esz) maFrom ((oFrom + iFrom) * esz) (k * esz)
     where esz = sizeOf (undefined :: e)
   {-# INLINE unsafeLinearCopy #-}
 
-  unsafeArrayLinearCopy (PArray _ _ aFrom) iFrom (MPArray _ maTo) iTo (Sz k) =
-    copyByteArray maTo (iTo * esz) aFrom (iFrom * esz) (k * esz)
+  unsafeArrayLinearCopy (PArray _ _ oFrom aFrom) iFrom (MPArray _ oTo maTo) iTo (Sz k) =
+    copyByteArray maTo ((oTo + iTo) * esz) aFrom ((oFrom + iFrom) * esz) (k * esz)
     where esz = sizeOf (undefined :: e)
   {-# INLINE unsafeArrayLinearCopy #-}
 
-  unsafeLinearShrink (MPArray _ ma) sz = do
-    shrinkMutableByteArray ma (totalElem sz * sizeOf (undefined :: e))
-    pure $ MPArray sz ma
+  unsafeLinearShrink (MPArray _ o ma) sz = do
+    shrinkMutableByteArray ma ((o + totalElem sz) * sizeOf (undefined :: e))
+    pure $ MPArray sz o ma
   {-# INLINE unsafeLinearShrink #-}
 
-  unsafeLinearGrow (MPArray _ ma) sz =
-    MPArray sz <$> resizeMutableByteArrayCompat ma (totalElem sz * sizeOf (undefined :: e))
+  unsafeLinearGrow (MPArray _ o ma) sz =
+    MPArray sz o <$> resizeMutableByteArrayCompat ma ((o + totalElem sz) * sizeOf (undefined :: e))
   {-# INLINE unsafeLinearGrow #-}
 
 
@@ -228,6 +244,8 @@
 instance (Prim e, Index ix) => Stream P ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.isteps
+  {-# INLINE toStreamIx #-}
 
 instance ( Prim e
          , IsList (Array L ix e)
@@ -253,14 +271,33 @@
 {-# INLINE elemsMBA #-}
 
 
--- | /O(1)/ - Extract the internal `ByteArray`.
+-- | /O(n)/ - Ensure that the size matches the internal `ByteArray`. If not make a copy of
+-- the slice and return it as `ByteArray`
 --
 -- @since 0.2.1
-toByteArray :: Array P ix e -> ByteArray
-toByteArray = pData
+toByteArray :: (Index ix, Prim e) => Array P ix e -> ByteArray
+toByteArray arr = fromMaybe (unwrapByteArray $ compute arr) $ toByteArrayM arr
 {-# INLINE toByteArray #-}
 
+-- | /O(1)/ - Extract the internal `ByteArray`. This will discard any possible slicing that has been
+-- applied to the array. Use `toByteArray` in order to preserve slicing.
+--
+-- @since 0.5.0
+unwrapByteArray :: Array P ix e -> ByteArray
+unwrapByteArray = pData
+{-# INLINE unwrapByteArray #-}
 
+
+-- | /O(1)/ - Unwrap Ensure that the size matches the internal `ByteArray`.
+--
+-- @since 0.5.0
+toByteArrayM :: (Prim e, Index ix, MonadThrow m) => Array P ix e -> m ByteArray
+toByteArrayM arr@PArray {pSize, pData} = do
+  guardNumberOfElements pSize (Sz (elemsBA arr pData))
+  pure pData
+{-# INLINE toByteArrayM #-}
+
+
 -- | /O(1)/ - Construct a primitive array from the `ByteArray`. Will return `Nothing` if number of
 -- elements doesn't match.
 --
@@ -269,23 +306,53 @@
 fromByteArrayM comp sz ba =
   guardNumberOfElements sz (Sz (elemsBA arr ba)) >> pure arr
   where
-    arr = PArray comp sz ba
+    arr = PArray comp sz 0 ba
 {-# INLINE fromByteArrayM #-}
 
 -- | /O(1)/ - Construct a flat Array from `ByteArray`
 --
 -- @since 0.4.0
 fromByteArray :: forall e . Prim e => Comp -> ByteArray -> Array P Ix1 e
-fromByteArray comp ba = PArray comp (SafeSz (elemsBA (Proxy :: Proxy e) ba)) ba
+fromByteArray comp ba = PArray comp (SafeSz (elemsBA (Proxy :: Proxy e) ba)) 0 ba
 {-# INLINE fromByteArray #-}
 
 
+-- | /O(1)/ - Extract the internal `MutableByteArray`. This will discard any possible
+-- slicing that has been applied to the array.
+--
+-- @since 0.5.0
+unwrapMutableByteArray :: MArray s P ix e -> MutableByteArray s
+unwrapMutableByteArray (MPArray _ _ mba) = mba
+{-# INLINE unwrapMutableByteArray #-}
+
+-- | /O(n)/ - Try to cast a mutable array to `MutableByteArray`, if sizes do not match make
+-- a copy. Returns `True` if an array was converted without a copy, in which case it means
+-- tha the source at the resulting array are still pointing to the same location in memory.
+--
+-- @since 0.5.0
+toMutableByteArray ::
+     forall ix e m. (Prim e, Index ix, PrimMonad m)
+  => MArray (PrimState m) P ix e
+  -> m (Bool, MutableByteArray (PrimState m))
+toMutableByteArray marr@(MPArray sz offset mbas) =
+  case toMutableByteArrayM marr of
+    Just mba -> pure (True, mba)
+    Nothing -> do
+      let eSize = sizeOf (undefined :: e)
+          szBytes = totalElem sz * eSize
+      mbad <- newPinnedByteArray szBytes
+      copyMutableByteArray mbad 0 mbas (offset * eSize) szBytes
+      pure (False, mbad)
+{-# INLINE toMutableByteArray #-}
+
+
 -- | /O(1)/ - Extract the internal `MutableByteArray`.
 --
 -- @since 0.2.1
-toMutableByteArray :: MArray s P ix e -> MutableByteArray s
-toMutableByteArray (MPArray _ mba) = mba
-{-# INLINE toMutableByteArray #-}
+toMutableByteArrayM :: (Index ix, Prim e, MonadThrow m) => MArray s P ix e -> m (MutableByteArray s)
+toMutableByteArrayM marr@(MPArray sz _ mba) =
+  mba <$ guardNumberOfElements sz (Sz (elemsMBA marr mba))
+{-# INLINE toMutableByteArrayM #-}
 
 
 -- | /O(1)/ - Construct a primitive mutable array from the `MutableByteArray`. Will throw
@@ -295,33 +362,66 @@
 fromMutableByteArrayM ::
      (MonadThrow m, Index ix, Prim e) => Sz ix -> MutableByteArray s -> m (MArray s P ix e)
 fromMutableByteArrayM sz mba =
-  guardNumberOfElements sz (Sz (elemsMBA marr mba)) >> pure marr
+  marr <$ guardNumberOfElements sz (Sz (elemsMBA marr mba))
   where
-    marr = MPArray sz mba
+    marr = MPArray sz 0 mba
 {-# INLINE fromMutableByteArrayM #-}
 
 -- | /O(1)/ - Construct a flat Array from `MutableByteArray`
 --
 -- @since 0.4.0
 fromMutableByteArray :: forall e s . Prim e => MutableByteArray s -> MArray s P Ix1 e
-fromMutableByteArray mba = MPArray (SafeSz (elemsMBA (Proxy :: Proxy e) mba)) mba
+fromMutableByteArray mba = MPArray (SafeSz (elemsMBA (Proxy :: Proxy e) mba)) 0 mba
 {-# INLINE fromMutableByteArray #-}
 
 
+
+
+-- | /O(1)/ - Cast a primitive array to a primitive vector.
+--
+-- @since 0.5.0
+toPrimitiveVector :: Index ix => Array P ix e -> VP.Vector e
+toPrimitiveVector PArray {pSize, pOffset, pData} = VP.Vector pOffset (totalElem pSize) pData
+{-# INLINE toPrimitiveVector #-}
+
+
+-- | /O(1)/ - Cast a mutable primitive array to a mutable primitive vector.
+--
+-- @since 0.5.0
+toPrimitiveMVector :: Index ix => MArray s P ix e -> MVP.MVector s e
+toPrimitiveMVector (MPArray sz offset mba) = MVP.MVector offset (totalElem sz) mba
+{-# INLINE toPrimitiveMVector #-}
+
+
+-- | /O(1)/ - Cast a primitive vector to a primitive array.
+--
+-- @since 0.5.0
+fromPrimitiveVector :: VP.Vector e -> Array P Ix1 e
+fromPrimitiveVector (VP.Vector offset len ba) =
+  PArray {pComp = Seq, pSize = SafeSz len, pOffset = offset, pData = ba}
+{-# INLINE fromPrimitiveVector #-}
+
+-- | /O(1)/ - Cast a mutable primitive vector to a mutable primitive array.
+--
+-- @since 0.5.0
+fromPrimitiveMVector :: MVP.MVector s e -> MArray s P Ix1 e
+fromPrimitiveMVector (MVP.MVector offset len mba) = MPArray (SafeSz len) offset mba
+{-# INLINE fromPrimitiveMVector #-}
+
 -- | Atomically read an `Int` element from the array
 --
 -- @since 0.3.0
 unsafeAtomicReadIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> m Int
-unsafeAtomicReadIntArray _mpa@(MPArray sz mba) ix =
+unsafeAtomicReadIntArray _mpa@(MPArray sz o mba) ix =
   INDEX_CHECK( "unsafeAtomicReadIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case atomicReadIntArray# mba# i# s# of
                    (# s'#, e# #) -> (# s'#, I# e# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicReadIntArray #-}
 
 -- | Atomically write an `Int` element int the array
@@ -329,13 +429,13 @@
 -- @since 0.3.0
 unsafeAtomicWriteIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m ()
-unsafeAtomicWriteIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicWriteIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicWriteIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive_ (atomicWriteIntArray# mba# i# e#))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicWriteIntArray #-}
 
 -- | Atomically CAS an `Int` in the array. Returns the old value.
@@ -343,15 +443,15 @@
 -- @since 0.3.0
 unsafeCasIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> Int -> m Int
-unsafeCasIntArray _mpa@(MPArray sz mba) ix (I# e#) (I# n#) =
+unsafeCasIntArray _mpa@(MPArray sz o mba) ix (I# e#) (I# n#) =
   INDEX_CHECK( "unsafeCasIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case casIntArray# mba# i# e# n# s# of
                    (# s'#, o# #) -> (# s'#, I# o# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeCasIntArray #-}
 
 
@@ -360,10 +460,10 @@
 -- @since 0.3.0
 unsafeAtomicModifyIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> (Int -> Int) -> m Int
-unsafeAtomicModifyIntArray _mpa@(MPArray sz mba) ix f =
-  INDEX_CHECK("unsafeAtomicModifyIntArray", Sz . elemsMBA _mpa, atomicModify)
+unsafeAtomicModifyIntArray _mpa@(MPArray sz o mba) ix f =
+  INDEX_CHECK("unsafeAtomicModifyIntArray", SafeSz . elemsMBA _mpa, atomicModify)
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
   where
     atomicModify (MutableByteArray mba#) (I# i#) =
       let go s# o# =
@@ -385,15 +485,15 @@
 -- @since 0.3.0
 unsafeAtomicAddIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicAddIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicAddIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicAddIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchAddIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicAddIntArray #-}
 
 
@@ -402,15 +502,15 @@
 -- @since 0.3.0
 unsafeAtomicSubIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicSubIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicSubIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicSubIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchSubIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicSubIntArray #-}
 
 
@@ -419,15 +519,15 @@
 -- @since 0.3.0
 unsafeAtomicAndIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicAndIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicAndIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicAndIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchAndIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicAndIntArray #-}
 
 
@@ -436,15 +536,15 @@
 -- @since 0.3.0
 unsafeAtomicNandIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicNandIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicNandIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicNandIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchNandIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicNandIntArray #-}
 
 
@@ -453,15 +553,15 @@
 -- @since 0.3.0
 unsafeAtomicOrIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicOrIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicOrIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicOrIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchOrIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicOrIntArray #-}
 
 
@@ -470,15 +570,15 @@
 -- @since 0.3.0
 unsafeAtomicXorIntArray ::
      (Index ix, PrimMonad m) => MArray (PrimState m) P ix Int -> ix -> Int -> m Int
-unsafeAtomicXorIntArray _mpa@(MPArray sz mba) ix (I# e#) =
+unsafeAtomicXorIntArray _mpa@(MPArray sz o mba) ix (I# e#) =
   INDEX_CHECK( "unsafeAtomicXorIntArray"
-             , Sz . elemsMBA _mpa
+             , SafeSz . elemsMBA _mpa
              , \(MutableByteArray mba#) (I# i#) ->
                  primitive $ \s# ->
                  case fetchXorIntArray# mba# i# e# s# of
                    (# s'#, p# #) -> (# s'#, I# p# #))
   mba
-  (toLinearIndex sz ix)
+  (o + toLinearIndex sz ix)
 {-# INLINE unsafeAtomicXorIntArray #-}
 
 
diff --git a/src/Data/Massiv/Array/Manifest/Storable.hs b/src/Data/Massiv/Array/Manifest/Storable.hs
--- a/src/Data/Massiv/Array/Manifest/Storable.hs
+++ b/src/Data/Massiv/Array/Manifest/Storable.hs
@@ -9,7 +9,7 @@
 {-# LANGUAGE UndecidableInstances #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest.Storable
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -21,6 +21,8 @@
   , VS.Storable
   , toStorableVector
   , toStorableMVector
+  , fromStorableVector
+  , fromStorableMVector
   , withPtr
   , unsafeWithPtr
   , unsafeArrayToForeignPtr
@@ -39,7 +41,7 @@
 import Data.Massiv.Array.Manifest.Primitive (shrinkMutableByteArray)
 import Data.Primitive.ByteArray (MutableByteArray(..))
 import Data.Massiv.Array.Manifest.List as A
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
+import Data.Massiv.Vector.Stream as S (steps, isteps)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.List
@@ -93,6 +95,8 @@
   unsafeLinearIndex (SArray _ _ v) =
     INDEX_CHECK("(Source S ix e).unsafeLinearIndex", Sz . VS.length, VS.unsafeIndex) v
   {-# INLINE unsafeLinearIndex #-}
+  unsafeLinearSlice i k (SArray c _ v) = SArray c k $ VS.unsafeSlice i (unSz k) v
+  {-# INLINE unsafeLinearSlice #-}
 
 instance Index ix => Resize S ix where
   unsafeResize !sz !arr = arr { sSize = sz }
@@ -214,6 +218,8 @@
 instance (Index ix, VS.Storable e) => Stream S ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.isteps
+  {-# INLINE toStreamIx #-}
 
 
 instance ( VS.Storable e
@@ -260,6 +266,20 @@
 toStorableMVector :: MArray s S ix e -> VS.MVector s e
 toStorableMVector (MSArray _ mv) = mv
 {-# INLINE toStorableMVector #-}
+
+-- | /O(1)/ - Cast a storable vector to a storable array.
+--
+-- @since 0.5.0
+fromStorableVector :: Storable e => Comp -> VS.Vector e -> Array S Ix1 e
+fromStorableVector comp v = SArray {sComp = comp, sSize = SafeSz (VS.length v), sData = v}
+{-# INLINE fromStorableVector #-}
+
+-- | /O(1)/ - Cast a mutable storable vector to a mutable storable array.
+--
+-- @since 0.5.0
+fromStorableMVector :: MVS.MVector s e -> MArray s S Ix1 e
+fromStorableMVector mv@(MVS.MVector len _) = MSArray (SafeSz len) mv
+{-# INLINE fromStorableMVector #-}
 
 
 -- | /O(1)/ - Yield the underlying `ForeignPtr` together with its length.
diff --git a/src/Data/Massiv/Array/Manifest/Unboxed.hs b/src/Data/Massiv/Array/Manifest/Unboxed.hs
--- a/src/Data/Massiv/Array/Manifest/Unboxed.hs
+++ b/src/Data/Massiv/Array/Manifest/Unboxed.hs
@@ -21,13 +21,15 @@
   , Array(..)
   , toUnboxedVector
   , toUnboxedMVector
+  , fromUnboxedVector
+  , fromUnboxedMVector
   ) where
 
 import Control.DeepSeq (NFData(..), deepseq)
 import Data.Massiv.Array.Delayed.Pull (eq, ord)
 import Data.Massiv.Array.Manifest.Internal (M, toManifest)
 import Data.Massiv.Array.Manifest.List as A
-import Data.Massiv.Array.Manifest.Vector.Stream as S (steps)
+import Data.Massiv.Vector.Stream as S (steps, isteps)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.List
@@ -78,6 +80,8 @@
   unsafeLinearIndex (UArray _ _ v) =
     INDEX_CHECK("(Source U ix e).unsafeLinearIndex", Sz . VU.length, VU.unsafeIndex) v
   {-# INLINE unsafeLinearIndex #-}
+  unsafeLinearSlice i k (UArray c _ v) = UArray c k $ VU.unsafeSlice i (unSz k) v
+  {-# INLINE unsafeLinearSlice #-}
 
 
 instance Index ix => Resize U ix where
@@ -188,6 +192,8 @@
 instance (Index ix, VU.Unbox e) => Stream U ix e where
   toStream = S.steps
   {-# INLINE toStream #-}
+  toStreamIx = S.isteps
+  {-# INLINE toStreamIx #-}
 
 
 instance ( VU.Unbox e
@@ -218,3 +224,20 @@
 toUnboxedMVector :: MArray s U ix e -> VU.MVector s e
 toUnboxedMVector (MUArray _ mv) = mv
 {-# INLINE toUnboxedMVector #-}
+
+
+
+-- | /O(1)/ - Wrap an unboxed vector and produce an unboxed flat array.
+--
+-- @since 0.5.0
+fromUnboxedVector :: VU.Unbox e => VU.Vector e -> Array U Ix1 e
+fromUnboxedVector v = UArray Seq (SafeSz (VU.length v)) v
+{-# INLINE fromUnboxedVector #-}
+
+
+-- | /O(1)/ - Wrap an unboxed mutable vector and produce a mutable unboxed flat array.
+--
+-- @since 0.5.0
+fromUnboxedMVector :: VU.Unbox e => VU.MVector s e -> MArray s U Ix1 e
+fromUnboxedMVector mv = MUArray (SafeSz (MVU.length mv)) mv
+{-# INLINE fromUnboxedMVector #-}
diff --git a/src/Data/Massiv/Array/Manifest/Vector.hs b/src/Data/Massiv/Array/Manifest/Vector.hs
--- a/src/Data/Massiv/Array/Manifest/Vector.hs
+++ b/src/Data/Massiv/Array/Manifest/Vector.hs
@@ -54,9 +54,10 @@
   VRepr N = VB.Vector
 
 
--- | /O(1)/ - conversion from vector to an array with a corresponding
--- representation. Will return `Nothing` if there is a size mismatch, vector has
--- been sliced before or if some non-standard vector type is supplied.
+-- | /O(1)/ - conversion from vector to an array with a corresponding representation. Will
+-- return `Nothing` if there is a size mismatch or if some non-standard vector type is
+-- supplied. Is suppplied is the boxed `Data.Vector.Vector` then it's all elements will be
+-- evaluated toWHNF, therefore complexity will be /O(n)/
 castFromVector :: forall v r ix e. (VG.Vector v e, Typeable v, Mutable r ix e, ARepr v ~ r)
                => Comp
                -> Sz ix -- ^ Size of the result Array
@@ -72,13 +73,12 @@
          sVector <- join $ gcast1 (Just vector)
          return $ SArray {sComp = comp, sSize = sz, sData = sVector}
     , do Refl <- eqT :: Maybe (v :~: VP.Vector)
-         VP.Vector 0 _ arr <- join $ gcast1 (Just vector)
-         return $ PArray {pComp = comp, pSize = sz, pData = arr}
+         VP.Vector o _ ba <- join $ gcast1 (Just vector)
+         return $ PArray {pComp = comp, pSize = sz, pOffset = o, pData = ba}
     , do Refl <- eqT :: Maybe (v :~: VB.Vector)
          bVector <- join $ gcast1 (Just vector)
-         arr <- castVectorToArray bVector
-         let barr = BArray {bComp = comp, bSize = sz, bData = arr}
-         barr `seqArray` return barr
+         let ba = unsafeFromBoxedVector bVector
+         ba `seqArray` pure (unsafeResize sz ba)
     ]
 {-# NOINLINE castFromVector #-}
 
@@ -124,8 +124,10 @@
 -- | /O(1)/ - conversion from `Mutable` array to a corresponding vector. Will
 -- return `Nothing` only if source array representation was not one of `B`, `N`,
 -- `P`, `S` or `U`.
-castToVector :: forall v r ix e . (Mutable r ix e, VRepr r ~ v)
-         => Array r ix e -> Maybe (v e)
+castToVector ::
+     forall v r ix e. (Mutable r ix e, VRepr r ~ v)
+  => Array r ix e
+  -> Maybe (v e)
 castToVector arr =
   msum
     [ do Refl <- eqT :: Maybe (r :~: U)
@@ -136,13 +138,13 @@
          return $ sData sArr
     , do Refl <- eqT :: Maybe (r :~: P)
          pArr <- gcastArr arr
-         return $ VP.Vector 0 (totalElem (size arr)) $ pData pArr
+         return $ VP.Vector (pOffset pArr) (totalElem (size arr)) $ pData pArr
     , do Refl <- eqT :: Maybe (r :~: B)
          bArr <- gcastArr arr
-         return $ castArrayToVector $ bData bArr
+         return $ toBoxedVector bArr
     , do Refl <- eqT :: Maybe (r :~: N)
          bArr <- gcastArr arr
-         return $ castArrayToVector $ bData $ bArray bArr
+         return $ toBoxedVector $ bArray bArr
     ]
 {-# NOINLINE castToVector #-}
 
diff --git a/src/Data/Massiv/Array/Manifest/Vector/Stream.hs b/src/Data/Massiv/Array/Manifest/Vector/Stream.hs
deleted file mode 100644
--- a/src/Data/Massiv/Array/Manifest/Vector/Stream.hs
+++ /dev/null
@@ -1,407 +0,0 @@
-{-# LANGUAGE TupleSections #-}
-{-# LANGUAGE FlexibleContexts #-}
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
--- |
--- Module      : Data.Massiv.Array.Manifest.Vector.Stream
--- Copyright   : (c) Alexey Kuleshevich 2019
--- License     : BSD3
--- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
--- Stability   : experimental
--- Portability : non-portable
---
-module Data.Massiv.Array.Manifest.Vector.Stream
-  ( -- | __Important__ - This module is still experimental, as such it is considered
-    -- internal and exported for the curious users only.
-    Steps(..)
-  , Stream(..)
-  -- * Conversion
-  , steps
-  , isteps
-  , fromStream
-  , fromStreamM
-  , fromStreamExactM
-  , unstreamExact
-  , unstreamMax
-  , unstreamMaxM
-  , unstreamUnknown
-  , unstreamUnknownM
-  , unstreamIntoM
-  -- * Bundle
-  , toBundle
-  , fromBundle
-  , fromBundleM
-  -- * Operations on Steps
-  , length
-  , empty
-  , singleton
-  , generate
-  , cons
-  , uncons
-  , snoc
-  , drop
-  , take
-  , slice
-  , traverse
-  , mapM
-  , concatMap
-  , append
-  , zipWith
-  , zipWithM
-  -- ** Folding
-  , foldl
-  , foldr
-  , foldlM
-  , foldrM
-  -- ** Unfolding
-  , unfoldr
-  , unfoldrN
-  -- * Lists
-  , toList
-  , fromList
-  , fromListN
-  -- ** Filter
-  , mapMaybe
-  , mapMaybeA
-  , mapMaybeM
-  , filter
-  , filterA
-  , filterM
-  , transStepsId
-  -- * Useful re-exports
-  , module Data.Vector.Fusion.Bundle.Size
-  , module Data.Vector.Fusion.Util
-  ) where
-
-import Data.Maybe (catMaybes)
-import qualified Control.Monad as M
-import Control.Monad.ST
-import Data.Massiv.Core.Common hiding (empty, singleton)
-import qualified Data.Traversable as Traversable (traverse)
-import qualified Data.Vector.Fusion.Bundle.Monadic as B
-import Data.Vector.Fusion.Bundle.Size
-import qualified Data.Vector.Fusion.Stream.Monadic as S
-import Data.Vector.Fusion.Util
-import Prelude hiding (zipWith, mapM, traverse, length, foldl, foldr, filter, concatMap, drop, take)
-
-
--- TODO: benchmark: `fmap snd . isteps`
-steps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m e
-steps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
-  where
-    k = totalElem $ size arr
-    step i
-      | i < k =
-        let e = unsafeLinearIndex arr i
-         in e `seq` return $ S.Yield e (i + 1)
-      | otherwise = return S.Done
-    {-# INLINE step #-}
-{-# INLINE steps #-}
-
-
-isteps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m (ix, e)
-isteps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
-  where
-    sz = size arr
-    k = totalElem sz
-    step i
-      | i < k =
-        let e = unsafeLinearIndex arr i
-         in e `seq` return $ S.Yield (fromLinearIndex sz i, e) (i + 1)
-      | otherwise = return S.Done
-    {-# INLINE step #-}
-{-# INLINE isteps #-}
-
-toBundle :: (Monad m, Source r ix e) => Array r ix e -> B.Bundle m v e
-toBundle arr =
-  let Steps str k = steps arr
-   in B.fromStream str k
-{-# INLINE toBundle #-}
-
-fromBundle :: Mutable r Ix1 e => B.Bundle Id v e -> Array r Ix1 e
-fromBundle bundle = fromStream (B.sSize bundle) (B.sElems bundle)
-{-# INLINE fromBundle #-}
-
-
-fromBundleM :: (Monad m, Mutable r Ix1 e) => B.Bundle m v e -> m (Array r Ix1 e)
-fromBundleM bundle = fromStreamM (B.sSize bundle) (B.sElems bundle)
-{-# INLINE fromBundleM #-}
-
-
-fromStream :: forall r e . Mutable r Ix1 e => Size -> S.Stream Id e -> Array r Ix1 e
-fromStream sz str =
-  case upperBound sz of
-    Nothing -> unstreamUnknown str
-    Just k  -> unstreamMax k str
-{-# INLINE fromStream #-}
-
-fromStreamM :: forall r e m. (Monad m, Mutable r Ix1 e) => Size -> S.Stream m e -> m (Array r Ix1 e)
-fromStreamM sz str = do
-  xs <- S.toList str
-  case upperBound sz of
-    Nothing -> pure $! unstreamUnknown (S.fromList xs)
-    Just k  -> pure $! unstreamMax k (S.fromList xs)
-{-# INLINE fromStreamM #-}
-
-fromStreamExactM ::
-     forall r ix e m. (Monad m, Mutable r ix e)
-  => Sz ix
-  -> S.Stream m e
-  -> m (Array r ix e)
-fromStreamExactM sz str = do
-  xs <- S.toList str
-  pure $! unstreamExact sz (S.fromList xs)
-{-# INLINE fromStreamExactM #-}
-
-
-unstreamIntoM ::
-     (Mutable r Ix1 a, PrimMonad m)
-  => MArray (PrimState m) r Ix1 a
-  -> Size
-  -> S.Stream Id a
-  -> m (MArray (PrimState m) r Ix1 a)
-unstreamIntoM marr sz str =
-  case sz of
-    Exact _ -> marr <$ unstreamMaxM marr str
-    Max _ -> unsafeLinearShrink marr . SafeSz =<< unstreamMaxM marr str
-    Unknown  -> unstreamUnknownM marr str
-{-# INLINE unstreamIntoM #-}
-
-
-
-unstreamMax ::
-     forall r e. (Mutable r Ix1 e)
-  => Int
-  -> S.Stream Id e
-  -> Array r Ix1 e
-unstreamMax kMax str =
-  runST $ do
-    marr <- unsafeNew (SafeSz kMax)
-    k <- unstreamMaxM marr str
-    unsafeLinearShrink marr (SafeSz k) >>= unsafeFreeze Seq
-{-# INLINE unstreamMax #-}
-
-
-unstreamMaxM ::
-     (Mutable r ix a, PrimMonad m) => MArray (PrimState m) r ix a -> S.Stream Id a -> m Int
-unstreamMaxM marr (S.Stream step s) = stepLoad s 0
-  where
-    stepLoad t i =
-      case unId (step t) of
-        S.Yield e' t' -> do
-          unsafeLinearWrite marr i e'
-          stepLoad t' (i + 1)
-        S.Skip t' -> stepLoad t' i
-        S.Done -> return i
-    {-# INLINE stepLoad #-}
-{-# INLINE unstreamMaxM #-}
-
-
-unstreamUnknown :: Mutable r Ix1 a => S.Stream Id a -> Array r Ix1 a
-unstreamUnknown str =
-  runST $ do
-    marr <- unsafeNew zeroSz
-    unstreamUnknownM marr str >>= unsafeFreeze Seq
-{-# INLINE unstreamUnknown #-}
-
-
-unstreamUnknownM ::
-     (Mutable r Ix1 a, PrimMonad m)
-  => MArray (PrimState m) r Ix1 a
-  -> S.Stream Id a
-  -> m (MArray (PrimState m) r Ix1 a)
-unstreamUnknownM marrInit (S.Stream step s) = stepLoad s 0 (unSz (msize marrInit)) marrInit
-  where
-    stepLoad t i kMax marr
-      | i < kMax =
-        case unId (step t) of
-          S.Yield e' t' -> do
-            unsafeLinearWrite marr i e'
-            stepLoad t' (i + 1) kMax marr
-          S.Skip t' -> stepLoad t' i kMax marr
-          S.Done -> unsafeLinearShrink marr (SafeSz i)
-      | otherwise = do
-        let kMax' = max 1 (kMax * 2)
-        marr' <- unsafeLinearGrow marr (SafeSz kMax')
-        stepLoad t i kMax' marr'
-    {-# INLINE stepLoad #-}
-{-# INLINE unstreamUnknownM #-}
-
-
-unstreamExact ::
-     forall r ix e. (Mutable r ix e)
-  => Sz ix
-  -> S.Stream Id e
-  -> Array r ix e
-unstreamExact sz str =
-  runST $ do
-    marr <- unsafeNew sz
-    _ <- unstreamMaxM marr str
-    unsafeFreeze Seq marr
-{-# INLINE unstreamExact #-}
-
-length :: Steps Id a -> Int
-length (Steps str sz) =
-  case sz of
-    Exact k -> k
-    _       -> unId (S.length str)
-{-# INLINE length #-}
-
-empty :: Monad m => Steps m e
-empty = Steps S.empty (Exact 0)
-{-# INLINE empty #-}
-
-singleton :: Monad m => e -> Steps m e
-singleton e = Steps (S.singleton e) (Exact 1)
-{-# INLINE singleton #-}
-
-generate :: Monad m => Int -> (Int -> e) -> Steps m e
-generate k f = Steps (S.generate k f) (Exact k)
-{-# INLINE generate #-}
-
-cons :: Monad m => e -> Steps m e -> Steps m e
-cons e (Steps str k) = Steps (S.cons e str) (k + 1)
-{-# INLINE cons #-}
-
-uncons :: Monad m => Steps m e -> m (Maybe (e, Steps m e))
-uncons sts@(Steps str _) = do
-  mx <- str S.!? 0
-  pure $ fmap (, drop 1 sts) mx
-{-# INLINE uncons #-}
-
-snoc :: Monad m => Steps m e -> e -> Steps m e
-snoc (Steps str k) e = Steps (S.snoc str e) (k + 1)
-{-# INLINE snoc #-}
-
-traverse :: (Monad m, Applicative f) => (e -> f a) -> Steps Id e -> f (Steps m a)
-traverse f (Steps str k) = (`Steps` k) <$> liftListA (Traversable.traverse f) str
-{-# INLINE traverse #-}
-
-append :: Monad m => Steps m e -> Steps m e -> Steps m e
-append (Steps str1 k1) (Steps str2 k2) = Steps (str1 S.++ str2) (k1 + k2)
-{-# INLINE append #-}
-
-mapM :: Monad m => (e -> m a) -> Steps m e -> Steps m a
-mapM f (Steps str k) = Steps (S.mapM f str) k
-{-# INLINE mapM #-}
-
-zipWith :: Monad m => (a -> b -> e) -> Steps m a -> Steps m b -> Steps m e
-zipWith f (Steps str1 k1) (Steps str2 k2) = Steps (S.zipWith f str1 str2) (smaller k1 k2)
-{-# INLINE zipWith #-}
-
-zipWithM :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> Steps m c
-zipWithM f (Steps str1 k1) (Steps str2 k2) = Steps (S.zipWithM f str1 str2) (smaller k1 k2)
-{-# INLINE zipWithM #-}
-
-transStepsId :: Monad m => Steps Id e -> Steps m e
-transStepsId (Steps sts k) = Steps (S.trans (pure . unId) sts) k
-{-# INLINE transStepsId #-}
-
-
-foldr :: (a -> b -> b) -> b -> Steps Id a -> b
-foldr f acc sts = unId (S.foldr f acc (stepsStream sts))
-{-# INLINE foldr #-}
-
-
-foldl :: (b -> a -> b) -> b -> Steps Id a -> b
-foldl f acc sts = unId (S.foldl f acc (stepsStream sts))
-{-# INLINE foldl #-}
-
-
-foldlM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
-foldlM f acc (Steps sts _) = S.foldlM f acc sts
-{-# INLINE foldlM #-}
-
-
-foldrM :: Monad m => (b -> a -> m a) -> a -> Steps m b -> m a
-foldrM f acc (Steps sts _) = S.foldrM f acc sts
-{-# INLINE foldrM #-}
-
-
-mapMaybe :: Monad m => (a -> Maybe e) -> Steps m a -> Steps m e
-mapMaybe f (Steps str k) = Steps (S.mapMaybe f str) (toMax k)
-{-# INLINE mapMaybe #-}
-
-concatMap :: Monad m => (a -> Steps m e) -> Steps m a -> Steps m e
-concatMap f (Steps str _) = Steps (S.concatMap (stepsStream . f) str) Unknown
-{-# INLINE concatMap #-}
-
-
-mapMaybeA :: (Monad m, Applicative f) => (a -> f (Maybe e)) -> Steps Id a -> f (Steps m e)
-mapMaybeA f (Steps str k) = (`Steps` toMax k) <$> liftListA (mapMaybeListA f) str
-{-# INLINE mapMaybeA #-}
-
-mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Steps m a -> Steps m b
-mapMaybeM f (Steps str k) = Steps (mapMaybeStreamM f str) (toMax k)
-{-# INLINE mapMaybeM #-}
-
-mapMaybeListA :: Applicative f => (a -> f (Maybe b)) -> [a] -> f [b]
-mapMaybeListA f = fmap catMaybes . Traversable.traverse f
-{-# INLINE mapMaybeListA #-}
-
-mapMaybeStreamM :: Monad m => (a -> m (Maybe b)) -> S.Stream m a -> S.Stream m b
-mapMaybeStreamM f (S.Stream step t) = S.Stream step' t
-  where
-    step' s = do
-      r <- step s
-      case r of
-        S.Yield x s' -> do
-          b <- f x
-          return $
-            case b of
-              Nothing -> S.Skip s'
-              Just b' -> S.Yield b' s'
-        S.Skip s' -> return $ S.Skip s'
-        S.Done -> return S.Done
-    {-# INLINE step' #-}
-{-# INLINE mapMaybeStreamM #-}
-
-filter :: Monad m => (a -> Bool) -> Steps m a -> Steps m a
-filter f (Steps str k) = Steps (S.filter f str) (toMax k)
-{-# INLINE filter #-}
-
-
-filterA :: (Monad m, Applicative f) => (e -> f Bool) -> Steps Id e -> f (Steps m e)
-filterA f (Steps str k) = (`Steps` toMax k) <$> liftListA (M.filterM f) str
-{-# INLINE filterA #-}
-
-filterM :: Monad m => (e -> m Bool) -> Steps m e -> Steps m e
-filterM f (Steps str k) = Steps (S.filterM f str) (toMax k)
-{-# INLINE filterM #-}
-
-take :: Monad m => Int -> Steps m a -> Steps m a
-take n (Steps str _) = Steps (S.take n str) (Max n)
-{-# INLINE take #-}
-
-drop :: Monad m => Int -> Steps m a -> Steps m a
-drop n (Steps str k) = Steps (S.drop n str) (k `clampedSubtract` Exact n)
-{-# INLINE drop #-}
-
-slice :: Monad m => Int -> Int -> Steps m a -> Steps m a
-slice i k (Steps str _) = Steps (S.slice i k str) (Max k)
-{-# INLINE slice #-}
-
-unfoldr :: Monad m => (s -> Maybe (e, s)) -> s -> Steps m e
-unfoldr f e0 = Steps (S.unfoldr f e0) Unknown
-{-# INLINE unfoldr #-}
-
-unfoldrN :: Monad m => Sz1 -> (s -> Maybe (e, s)) -> s -> Steps m e
-unfoldrN n f e0 = Steps (S.unfoldrN (unSz n) f e0) (Max (unSz n))
-{-# INLINE unfoldrN #-}
-
-toList :: Steps Id e -> [e]
-toList (Steps str _) = unId (S.toList str)
-{-# INLINE toList #-}
-
-fromList :: Monad m => [e] -> Steps m e
-fromList = (`Steps` Unknown) . S.fromList
-{-# INLINE fromList #-}
-
-fromListN :: Monad m => Int -> [e] -> Steps m e
-fromListN n  = (`Steps` Exact n) . S.fromListN n
-{-# INLINE fromListN #-}
-
-liftListA :: (Monad m, Functor f) => ([a] -> f [b]) -> S.Stream Id a -> f (S.Stream m b)
-liftListA f str = S.fromList <$> f (unId (S.toList str))
-{-# INLINE liftListA #-}
diff --git a/src/Data/Massiv/Array/Mutable.hs b/src/Data/Massiv/Array/Mutable.hs
--- a/src/Data/Massiv/Array/Mutable.hs
+++ b/src/Data/Massiv/Array/Mutable.hs
@@ -78,8 +78,11 @@
   , iforLinearPrimM_
   -- *** Modify
   , withMArray
+  , withMArray_
   , withMArrayS
+  , withMArrayS_
   , withMArrayST
+  , withMArrayST_
   -- *** Initialize
   , initialize
   , initializeNew
@@ -99,6 +102,7 @@
 import Control.Monad.ST
 import Control.Scheduler
 import Data.Massiv.Core.Common
+import Data.Massiv.Array.Mutable.Internal
 import Prelude hiding (mapM, read)
 
 -- | /O(n)/ - Initialize a new mutable array. All elements will be set to some default value. For
@@ -409,7 +413,7 @@
 --
 -- >>> :set -XTypeApplications
 -- >>> import Data.Massiv.Array
--- >>> createArrayS_ @P @_ @Int Seq (Sz1 2) (\ marr -> write marr 0 10 >> write marr 1 12)
+-- >>> createArrayS_ @P @_ @Int (Sz1 2) (\ marr -> write marr 0 10 >> write marr 1 12)
 -- Array P Seq (Sz1 2)
 --   [ 10, 12 ]
 --
@@ -417,12 +421,11 @@
 --
 createArrayS_ ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy to use after `MArray` gets frozen and onward.
-  -> Sz ix -- ^ Size of the newly created array
+  => Sz ix -- ^ Size of the newly created array
   -> (MArray (PrimState m) r ix e -> m a)
   -- ^ An action that should fill all elements of the brand new mutable array
   -> m (Array r ix e)
-createArrayS_ comp sz action = snd <$> createArrayS comp sz action
+createArrayS_ sz action = snd <$> createArrayS sz action
 {-# INLINE createArrayS_ #-}
 
 -- | Just like `createArray_`, but together with `Array` it returns the result of the filling action.
@@ -431,15 +434,14 @@
 --
 createArrayS ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy to use after `MArray` gets frozen and onward.
-  -> Sz ix -- ^ Size of the newly created array
+  => Sz ix -- ^ Size of the newly created array
   -> (MArray (PrimState m) r ix e -> m a)
   -- ^ An action that should fill all elements of the brand new mutable array
   -> m (a, Array r ix e)
-createArrayS comp sz action = do
+createArrayS sz action = do
   marr <- new sz
   a <- action marr
-  arr <- unsafeFreeze comp marr
+  arr <- unsafeFreeze Seq marr
   return (a, arr)
 {-# INLINE createArrayS #-}
 
@@ -449,11 +451,10 @@
 --
 createArrayST_ ::
      forall r ix e a. Mutable r ix e
-  => Comp
-  -> Sz ix
+  => Sz ix
   -> (forall s. MArray s r ix e -> ST s a)
   -> Array r ix e
-createArrayST_ comp sz action = runST $ createArrayS_ comp sz action
+createArrayST_ sz action = runST $ createArrayS_ sz action
 {-# INLINE createArrayST_ #-}
 
 
@@ -463,11 +464,10 @@
 --
 createArrayST ::
      forall r ix e a. Mutable r ix e
-  => Comp
-  -> Sz ix
+  => Sz ix
   -> (forall s. MArray s r ix e -> ST s a)
   -> (a, Array r ix e)
-createArrayST comp sz action = runST $ createArrayS comp sz action
+createArrayST sz action = runST $ createArrayS sz action
 {-# INLINE createArrayST #-}
 
 
@@ -575,8 +575,7 @@
   -> Sz ix
   -> (ix -> s -> m e)
   -> m (Array r ix e)
-generateArrayWS states sz make =
-  generateArrayLinearWS states sz (\ix -> make (fromLinearIndex sz ix))
+generateArrayWS states sz make = generateArrayLinearWS states sz (make . fromLinearIndex sz)
 {-# INLINE generateArrayWS #-}
 
 
@@ -588,7 +587,7 @@
 -- each element of the array.
 --
 -- >>> import Data.Massiv.Array
--- >>> unfoldrPrimM_ Seq  (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return (f0, (f1, fn))) (0, 1) :: IO (Array P Ix1 Int)
+-- >>> unfoldrPrimM_ (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return (f0, (f1, fn))) (0, 1) :: IO (Array P Ix1 Int)
 -- (0,1)
 -- (1,1)
 -- (1,2)
@@ -606,12 +605,11 @@
 --
 unfoldrPrimM_ ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> m (e, a)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (Array r ix e)
-unfoldrPrimM_ comp sz gen acc0 = snd <$> unfoldrPrimM comp sz gen acc0
+unfoldrPrimM_ sz gen acc0 = snd <$> unfoldrPrimM sz gen acc0
 {-# INLINE unfoldrPrimM_ #-}
 
 -- | Same as `unfoldrPrimM_` but do the unfolding with index aware function.
@@ -620,12 +618,11 @@
 --
 iunfoldrPrimM_ ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> ix -> m (e, a)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (Array r ix e)
-iunfoldrPrimM_ comp sz gen acc0 = snd <$> iunfoldrPrimM comp sz gen acc0
+iunfoldrPrimM_ sz gen acc0 = snd <$> iunfoldrPrimM sz gen acc0
 {-# INLINE iunfoldrPrimM_ #-}
 
 
@@ -634,18 +631,17 @@
 -- @since 0.3.0
 iunfoldrPrimM ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> ix -> m (e, a)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (a, Array r ix e)
-iunfoldrPrimM comp sz gen acc0 =
-  createArrayS comp sz $ \marr ->
+iunfoldrPrimM sz gen acc0 =
+  unsafeCreateArrayS sz $ \marr ->
     let sz' = msize marr
-     in iterLinearM sz' 0 (totalElem sz') 1 (<) acc0 $ \i ix acc -> do
+     in iterLinearM sz' 0 (totalElem sz') 1 (<) acc0 $ \ !i ix !acc -> do
           (e, acc') <- gen acc ix
           unsafeLinearWrite marr i e
-          pure $! acc'
+          pure acc'
 {-# INLINE iunfoldrPrimM #-}
 
 -- | Just like `iunfoldrPrimM`, but do the unfolding with index aware function.
@@ -653,18 +649,17 @@
 -- @since 0.3.0
 unfoldrPrimM ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> m (e, a)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (a, Array r ix e)
-unfoldrPrimM comp sz gen acc0 =
-  createArrayS comp sz $ \marr ->
+unfoldrPrimM sz gen acc0 =
+  unsafeCreateArrayS sz $ \marr ->
     let sz' = msize marr
-     in loopM 0 (< totalElem sz') (+1) acc0 $ \i acc -> do
+     in loopM 0 (< totalElem sz') (+ 1) acc0 $ \ !i !acc -> do
           (e, acc') <- gen acc
           unsafeLinearWrite marr i e
-          pure $! acc'
+          pure acc'
 {-# INLINE unfoldrPrimM #-}
 
 -- | Sequentially unfold an array from the left.
@@ -675,7 +670,7 @@
 -- the accumulator for each element of the array.
 --
 -- >>> import Data.Massiv.Array
--- >>> unfoldlPrimM_ Seq  (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return ((f1, fn), f0)) (0, 1) :: IO (Array P Ix1 Int)
+-- >>> unfoldlPrimM_ (Sz1 10) (\a@(f0, f1) -> let fn = f0 + f1 in print a >> return ((f1, fn), f0)) (0, 1) :: IO (Array P Ix1 Int)
 -- (0,1)
 -- (1,1)
 -- (1,2)
@@ -693,12 +688,11 @@
 --
 unfoldlPrimM_ ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> m (a, e)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (Array r ix e)
-unfoldlPrimM_ comp sz gen acc0 = snd <$> unfoldlPrimM comp sz gen acc0
+unfoldlPrimM_ sz gen acc0 = snd <$> unfoldlPrimM sz gen acc0
 {-# INLINE unfoldlPrimM_ #-}
 
 -- | Same as `unfoldlPrimM_` but do the unfolding with index aware function.
@@ -707,12 +701,11 @@
 --
 iunfoldlPrimM_ ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> ix -> m (a, e)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (Array r ix e)
-iunfoldlPrimM_ comp sz gen acc0 = snd <$> iunfoldlPrimM comp sz gen acc0
+iunfoldlPrimM_ sz gen acc0 = snd <$> iunfoldlPrimM sz gen acc0
 {-# INLINE iunfoldlPrimM_ #-}
 
 
@@ -721,18 +714,17 @@
 -- @since 0.3.0
 iunfoldlPrimM ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> ix -> m (a, e)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (a, Array r ix e)
-iunfoldlPrimM comp sz gen acc0 =
-  createArrayS comp sz $ \marr ->
+iunfoldlPrimM sz gen acc0 =
+  unsafeCreateArrayS sz $ \marr ->
     let sz' = msize marr
-     in iterLinearM sz' (totalElem sz' - 1) 0 (negate 1) (>=) acc0 $ \i ix acc -> do
+     in iterLinearM sz' (totalElem sz' - 1) 0 (negate 1) (>=) acc0 $ \ !i ix !acc -> do
           (acc', e) <- gen acc ix
           unsafeLinearWrite marr i e
-          pure $! acc'
+          pure acc'
 {-# INLINE iunfoldlPrimM #-}
 
 -- | Just like `iunfoldlPrimM`, but do the unfolding with index aware function.
@@ -740,18 +732,17 @@
 -- @since 0.3.0
 unfoldlPrimM ::
      forall r ix e a m. (Mutable r ix e, PrimMonad m)
-  => Comp -- ^ Computation strategy (ignored during initial creation)
-  -> Sz ix -- ^ Size of the desired array
+  => Sz ix -- ^ Size of the desired array
   -> (a -> m (a, e)) -- ^ Unfolding action
   -> a -- ^ Initial accumulator
   -> m (a, Array r ix e)
-unfoldlPrimM comp sz gen acc0 =
-  createArrayS comp sz $ \marr ->
+unfoldlPrimM sz gen acc0 =
+  unsafeCreateArrayS sz $ \marr ->
     let sz' = msize marr
-     in loopDeepM 0 (< totalElem sz') (+1) acc0 $ \i acc -> do
+     in loopDeepM 0 (< totalElem sz') (+1) acc0 $ \ !i !acc -> do
           (acc', e) <- gen acc
           unsafeLinearWrite marr i e
-          pure $! acc'
+          pure acc'
 {-# INLINE unfoldlPrimM #-}
 
 -- | Sequentially loop over a mutable array while reading each element and applying an
@@ -811,6 +802,20 @@
   loopM_ 0 (< totalElem (msize marr)) (+ 1) (\i -> unsafeLinearModify marr (f i) i)
 {-# INLINE iforLinearPrimM #-}
 
+-- | Same as `withMArray_`, but allows to keep artifacts of scheduled tasks.
+--
+-- @since 0.5.0
+withMArray ::
+     (Mutable r ix e, MonadUnliftIO m)
+  => Array r ix e
+  -> (Scheduler m a -> MArray RealWorld r ix e -> m b)
+  -> m ([a], Array r ix e)
+withMArray arr action = do
+  marr <- thaw arr
+  xs <- withScheduler (getComp arr) (`action` marr)
+  liftIO ((,) xs <$> unsafeFreeze (getComp arr) marr)
+{-# INLINE withMArray #-}
+
 -- | Create a copy of a pure array, mutate it in place and return its frozen version. The big
 -- difference between `withMArrayS` is that it's not only gonna respect the computation strategy
 -- supplied to it while making a copy, but it will also pass extra argumens to the action that
@@ -823,47 +828,68 @@
 --
 -- * And, of course, the mutable array itself.
 --
--- @since 0.3.0
-withMArray ::
+-- @since 0.5.0
+withMArray_ ::
      (Mutable r ix e, MonadUnliftIO m)
   => Array r ix e
   -> (Scheduler m () -> MArray RealWorld r ix e -> m a)
   -> m (Array r ix e)
-withMArray arr action = do
+withMArray_ arr action = do
   marr <- thaw arr
   withScheduler_ (getComp arr) (`action` marr)
   liftIO $ unsafeFreeze (getComp arr) marr
-{-# INLINE withMArray #-}
+{-# INLINE withMArray_ #-}
 
 
 -- | Create a copy of a pure array, mutate it in place and return its frozen version. The important
--- benefit over doing a manual `thawS` followed by a `freezeS` is that an array will be only copied
+-- benefit over doing a manual `thawS` followed by a `freezeS` is that an array will only be copied
 -- once.
 --
--- @since 0.3.2
+-- @since 0.5.0
 withMArrayS ::
      (Mutable r ix e, PrimMonad m)
   => Array r ix e
   -> (MArray (PrimState m) r ix e -> m a)
-  -> m (Array r ix e)
+  -> m (a, Array r ix e)
 withMArrayS arr action = do
   marr <- thawS arr
-  _ <- action marr
-  unsafeFreeze (getComp arr) marr
+  a <- action marr
+  (,) a <$> unsafeFreeze (getComp arr) marr
 {-# INLINE withMArrayS #-}
 
 
+-- | Same as `withMArrayS`, but discards rhe element produced by the supplied action
+--
+-- @since 0.5.0
+withMArrayS_ ::
+     (Mutable r ix e, PrimMonad m)
+  => Array r ix e
+  -> (MArray (PrimState m) r ix e -> m a)
+  -> m (Array r ix e)
+withMArrayS_ arr action = snd <$> withMArrayS arr action
+{-# INLINE withMArrayS_ #-}
+
+
 -- | Same as `withMArrayS` but in `ST`. This is not only pure, but also the safest way to do
 -- mutation to the array.
 --
--- @since 0.2.2
+-- @since 0.5.0
 withMArrayST ::
      Mutable r ix e
   => Array r ix e
   -> (forall s . MArray s r ix e -> ST s a)
-  -> Array r ix e
+  -> (a, Array r ix e)
 withMArrayST arr f = runST $ withMArrayS arr f
 {-# INLINE withMArrayST #-}
+
+-- | Same as `withMArrayS` but in `ST`. This is not only pure, but also the safest way to do
+-- mutation to the array.
+--
+-- @since 0.5.0
+withMArrayST_ ::
+     Mutable r ix e => Array r ix e -> (forall s. MArray s r ix e -> ST s a) -> Array r ix e
+withMArrayST_ arr f = runST $ withMArrayS_ arr f
+{-# INLINE withMArrayST_ #-}
 
 
 -- | /O(1)/ - Lookup an element in the mutable array. Returns `Nothing` when index is out of bounds.
diff --git a/src/Data/Massiv/Array/Mutable/Algorithms.hs b/src/Data/Massiv/Array/Mutable/Algorithms.hs
--- a/src/Data/Massiv/Array/Mutable/Algorithms.hs
+++ b/src/Data/Massiv/Array/Mutable/Algorithms.hs
@@ -25,6 +25,7 @@
 --
 -- >>> import Data.Massiv.Array as A
 -- >>> import Data.Massiv.Array.Mutable.Algorithms
+-- >>> :set -XOverloadedLists
 -- >>> m <- thaw ([2,1,50,10,20,8] :: Array P Ix1 Int)
 -- >>> unstablePartitionM m (<= 10)
 -- 4
diff --git a/src/Data/Massiv/Array/Mutable/Internal.hs b/src/Data/Massiv/Array/Mutable/Internal.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Massiv/Array/Mutable/Internal.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE ExplicitForAll #-}
+-- |
+-- Module      : Data.Massiv.Array.Mutable.Internal
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
+-- License     : BSD3
+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
+-- Stability   : experimental
+-- Portability : non-portable
+--
+module Data.Massiv.Array.Mutable.Internal
+  ( unsafeCreateArray
+  , unsafeCreateArray_
+  , unsafeCreateArrayS
+  ) where
+
+import Control.Scheduler
+import Data.Massiv.Core.Common
+
+-- | Same as `Data.Massiv.Array.Mutable.createArrayS`, but memory will not be initialized
+-- and for unboxed types might contain garbage.
+--
+-- @since 0.5.0
+unsafeCreateArrayS ::
+     forall r ix e a m. (Mutable r ix e, PrimMonad m)
+  => Sz ix -- ^ Size of the newly created array
+  -> (MArray (PrimState m) r ix e -> m a)
+  -- ^ An action that should fill all elements of the brand new mutable array
+  -> m (a, Array r ix e)
+unsafeCreateArrayS sz action = do
+  marr <- unsafeNew sz
+  a <- action marr
+  arr <- unsafeFreeze Seq marr
+  return (a, arr)
+{-# INLINE unsafeCreateArrayS #-}
+
+-- | Same as `Data.Massiv.Array.Mutable.createArray`, but memory will not be initialized
+-- and for unboxed types might contain garbage.
+--
+-- @since 0.5.0
+unsafeCreateArray ::
+     forall r ix e a m b. (Mutable r ix e, PrimMonad m, MonadUnliftIO m)
+  => Comp -- ^ Computation strategy to use after `MArray` gets frozen and onward.
+  -> Sz ix -- ^ Size of the newly created array
+  -> (Scheduler m a -> MArray (PrimState m) r ix e -> m b)
+  -- ^ An action that should fill all elements of the brand new mutable array
+  -> m ([a], Array r ix e)
+unsafeCreateArray comp sz action = do
+  marr <- unsafeNew sz
+  a <- withScheduler comp (`action` marr)
+  arr <- unsafeFreeze comp marr
+  return (a, arr)
+{-# INLINE unsafeCreateArray #-}
+
+-- | Same as `Data.Massiv.Array.Mutable.createArray_`, but memory will not be initialized
+-- and for unboxed types might contain garbage.
+--
+-- @since 0.5.0
+unsafeCreateArray_ ::
+     forall r ix e a m b. (Mutable r ix e, PrimMonad m, MonadUnliftIO m)
+  => Comp -- ^ Computation strategy to use after `MArray` gets frozen and onward.
+  -> Sz ix -- ^ Size of the newly created array
+  -> (Scheduler m a -> MArray (PrimState m) r ix e -> m b)
+  -- ^ An action that should fill all elements of the brand new mutable array
+  -> m (Array r ix e)
+unsafeCreateArray_ comp sz action = do
+  marr <- unsafeNew sz
+  withScheduler_ comp (`action` marr)
+  arr <- unsafeFreeze comp marr
+  return arr
+{-# INLINE unsafeCreateArray_ #-}
diff --git a/src/Data/Massiv/Array/Ops/Construct.hs b/src/Data/Massiv/Array/Ops/Construct.hs
--- a/src/Data/Massiv/Array/Ops/Construct.hs
+++ b/src/Data/Massiv/Array/Ops/Construct.hs
@@ -30,12 +30,14 @@
   , iterateN
   , iiterateN
     -- *** Unfolding
-  , unfoldr
-  , unfoldrN
   , unfoldlS_
+  -- , unfoldlS
   , iunfoldlS_
+  --, iunfoldlS
   , unfoldrS_
+  --, unfoldrS
   , iunfoldrS_
+  --, iunfoldrS
     -- *** Random
   , randomArray
   , randomArrayS
@@ -70,10 +72,10 @@
 import Control.Monad.ST
 import Data.Massiv.Array.Delayed.Pull
 import Data.Massiv.Array.Delayed.Push
-import Data.Massiv.Array.Delayed.Stream (unfoldr, unfoldrN)
+--import Data.Massiv.Array.Delayed.Stream (unfoldr, unfoldrN)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Core.Common
-import Prelude as P hiding (enumFromTo, replicate)
+import Prelude hiding (enumFromTo, replicate)
 
 -- | Just like `makeArray` but with ability to specify the result representation as an
 -- argument. Note the `Data.Massiv.Array.U`nboxed type constructor in the below example.
@@ -116,8 +118,8 @@
 -- | Replicate the same element
 --
 -- @since 0.3.0
-replicate :: forall r ix e . Construct r ix e => Comp -> Sz ix -> e -> Array r ix e
-replicate comp sz e = makeArray comp sz (const e)
+replicate :: forall ix e . Index ix => Comp -> Sz ix -> e -> Array DL ix e
+replicate comp sz e = makeLoadArray comp sz e $ \_ _ -> pure ()
 {-# INLINE replicate #-}
 
 
@@ -206,13 +208,12 @@
 iiterateN sz f = iunfoldrS_ sz $ \a ix -> let !a' = f a ix in (a', a')
 {-# INLINE iiterateN #-}
 
-
--- | Right unfold of a delayed load array. For the inverse direction use `unfoldlS_`.
+-- | Right unfold into a delayed load array. For the opposite direction use `unfoldlS_`.
 --
 -- ==== __Examples__
 --
 -- >>> import Data.Massiv.Array
--- >>> unfoldrS_ (Sz1 10) (\xs -> (head xs, tail xs)) ([10 ..] :: [Int])
+-- >>> unfoldrS_ (Sz1 10) (\xs -> (Prelude.head xs, Prelude.tail xs)) ([10 ..] :: [Int])
 -- Array DL Seq (Sz1 10)
 --   [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ]
 --
@@ -377,7 +378,7 @@
      -- ^ A function that produces a random value and the next generator
   -> (g, Array r ix e)
 randomArrayS gen sz nextRandom =
-  runST $ unfoldrPrimM Seq sz (pure . nextRandom) gen
+  runST $ unfoldrPrimM sz (pure . nextRandom) gen
 {-# INLINE randomArrayS #-}
 
 -- | This is a stateful approach of generating random values. If your generator is pure
diff --git a/src/Data/Massiv/Array/Ops/Map.hs b/src/Data/Massiv/Array/Ops/Map.hs
--- a/src/Data/Massiv/Array/Ops/Map.hs
+++ b/src/Data/Massiv/Array/Ops/Map.hs
@@ -19,26 +19,17 @@
   , traverseA_
   , itraverseA
   , itraverseA_
-  , traverseAR
-  , itraverseAR
   , sequenceA
   , sequenceA_
-  , traverseS
   -- *** PrimMonad
   , traversePrim
   , itraversePrim
-  , traversePrimR
-  , itraversePrimR
   -- ** Monadic mapping
   -- *** Sequential
   , mapM
-  , mapMR
   , forM
-  , forMR
   , imapM
-  , imapMR
   , iforM
-  , iforMR
   , mapM_
   , forM_
   , imapM_
@@ -80,7 +71,6 @@
 import Control.Scheduler
 import Data.Coerce
 import Data.Massiv.Array.Delayed.Pull
-import Data.Massiv.Array.Delayed.Stream
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Array.Ops.Construct (makeArrayA, makeArrayLinearA)
 import Data.Massiv.Core.Common
@@ -97,10 +87,6 @@
 map f = imap (const f)
 {-# INLINE map #-}
 
--- | Map an index aware function over an array
-imap :: Source r ix e' => (ix -> e' -> e) -> Array r ix e' -> Array D ix e
-imap f !arr = DArray (getComp arr) (size arr) (\ !ix -> f ix (unsafeIndex arr ix))
-{-# INLINE imap #-}
 
 --------------------------------------------------------------------------------
 -- zip -------------------------------------------------------------------------
@@ -339,37 +325,6 @@
 {-# INLINE itraverseA_ #-}
 
 
-
--- | Same as `traverseA`, except with ability to specify representation.
---
--- @since 0.2.6
---
-traverseAR ::
-     (Source r' ix a, Mutable r ix b, Applicative f)
-  => r
-  -> (a -> f b)
-  -> Array r' ix a
-  -> f (Array r ix b)
-traverseAR _ = traverseA
-{-# INLINE traverseAR #-}
-{-# DEPRECATED traverseAR "In favor of `traverseA`" #-}
-
--- | Same as `itraverseA`, except with ability to specify representation.
---
--- @since 0.2.6
---
-itraverseAR ::
-     (Source r' ix a, Mutable r ix b, Applicative f)
-  => r
-  -> (ix -> a -> f b)
-  -> Array r' ix a
-  -> f (Array r ix b)
-itraverseAR _ = itraverseA
-{-# INLINE itraverseAR #-}
-{-# DEPRECATED itraverseAR "In favor of `itraverseA`" #-}
-
-
-
 -- | Traverse sequentially within `PrimMonad` over an array with an action.
 --
 -- @since 0.3.0
@@ -400,36 +355,6 @@
         in f ix (unsafeLinearIndex arr i))
 {-# INLINE itraversePrim #-}
 
-
--- | Same as `traversePrim`, but with ability to specify the desired representation.
---
--- @since 0.3.0
---
-traversePrimR ::
-     (Source r' ix a, Mutable r ix b, PrimMonad m)
-  => r
-  -> (a -> m b)
-  -> Array r' ix a
-  -> m (Array r ix b)
-traversePrimR _ = traversePrim
-{-# INLINE traversePrimR #-}
-{-# DEPRECATED traversePrimR "In favor of `traversePrim`" #-}
-
--- | Same as `itraversePrim`, but with ability to specify the desired representation.
---
--- @since 0.3.0
---
-itraversePrimR ::
-     (Source r' ix a, Mutable r ix b, PrimMonad m)
-  => r
-  -> (ix -> a -> m b)
-  -> Array r' ix a
-  -> m (Array r ix b)
-itraversePrimR _ = itraversePrim
-{-# INLINE itraversePrimR #-}
-{-# DEPRECATED itraversePrimR "In favor of `itraversePrim`" #-}
-
-
 --------------------------------------------------------------------------------
 -- mapM ------------------------------------------------------------------------
 --------------------------------------------------------------------------------
@@ -446,19 +371,6 @@
 {-# INLINE mapM #-}
 
 
--- | Same as `mapM`, except with ability to specify result representation.
---
--- @since 0.2.6
-mapMR ::
-     forall r ix b r' a m. (Source r' ix a, Mutable r ix b, Monad m)
-  => r
-  -> (a -> m b)
-  -> Array r' ix a
-  -> m (Array r ix b)
-mapMR _ = traverseA
-{-# INLINE mapMR #-}
-
-
 -- | Same as `mapM` except with arguments flipped.
 --
 -- @since 0.2.6
@@ -471,20 +383,6 @@
 {-# INLINE forM #-}
 
 
--- | Same as `forM`, except with ability to specify result representation.
---
--- @since 0.2.6
-forMR ::
-     forall r ix b r' a m. (Source r' ix a, Mutable r ix b, Monad m)
-  => r
-  -> Array r' ix a
-  -> (a -> m b)
-  -> m (Array r ix b)
-forMR _ = flip traverseA
-{-# INLINE forMR #-}
-
-
-
 -- | Map a monadic action over an array sequentially.
 --
 -- @since 0.2.6
@@ -497,20 +395,6 @@
 {-# INLINE imapM #-}
 
 
--- | Same as `imapM`, except with ability to specify result representation.
---
--- @since 0.2.6
-imapMR ::
-     forall r ix b r' a m. (Source r' ix a, Mutable r ix b, Monad m)
-  => r
-  -> (ix -> a -> m b)
-  -> Array r' ix a
-  -> m (Array r ix b)
-imapMR _ = itraverseA
-{-# INLINE imapMR #-}
-
-
-
 -- | Same as `forM`, except map an index aware action.
 --
 -- @since 0.2.6
@@ -521,20 +405,6 @@
   -> m (Array r ix b)
 iforM = itraverseA
 {-# INLINE iforM #-}
-
-
--- | Same as `iforM`, except with ability to specify result representation.
---
--- @since 0.2.6
---
-iforMR ::
-     forall r ix b r' a m. (Source r' ix a, Mutable r ix b, Monad m)
-  => r
-  -> (ix -> a -> m b)
-  -> Array r' ix a
-  -> m (Array r ix b)
-iforMR _ = itraverseA
-{-# INLINE iforMR #-}
 
 
 -- | Map a monadic function over an array sequentially, while discarding the result.
diff --git a/src/Data/Massiv/Array/Ops/Sort.hs b/src/Data/Massiv/Array/Ops/Sort.hs
--- a/src/Data/Massiv/Array/Ops/Sort.hs
+++ b/src/Data/Massiv/Array/Ops/Sort.hs
@@ -22,6 +22,7 @@
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Array.Ops.Transform
 import Data.Massiv.Core.Common
+import Data.Massiv.Vector (scatMaybes, sunfoldrN)
 import System.IO.Unsafe
 
 -- | Count how many occurance of each element there is in the array. Results will be
@@ -42,7 +43,7 @@
 tally :: (Mutable r Ix1 e, Resize r ix, Load r ix e, Ord e) => Array r ix e -> Array DS Ix1 (e, Int)
 tally arr
   | isEmpty arr = setComp (getComp arr) empty
-  | otherwise = catMaybesS $ unfoldrN (sz + 1) count (0, 0, sorted ! 0)
+  | otherwise = scatMaybes $ sunfoldrN (sz + 1) count (0, 0, sorted ! 0)
   where
     sz@(Sz k) = size sorted
     count (!i, !n, !prev)
@@ -99,7 +100,7 @@
 -- @since 0.3.2
 quicksort ::
      (Mutable r Ix1 e, Ord e) => Array r Ix1 e -> Array r Ix1 e
-quicksort arr = unsafePerformIO $ withMArray arr quicksortM_
+quicksort arr = unsafePerformIO $ withMArray_ arr quicksortM_
 {-# INLINE quicksort #-}
 
 
diff --git a/src/Data/Massiv/Array/Ops/Transform.hs b/src/Data/Massiv/Array/Ops/Transform.hs
--- a/src/Data/Massiv/Array/Ops/Transform.hs
+++ b/src/Data/Massiv/Array/Ops/Transform.hs
@@ -54,8 +54,6 @@
   , splitAtM
   , splitAt'
   , splitExtractM
-  , takeS
-  , dropS
   -- ** Upsample/Downsample
   , upsample
   , downsample
@@ -76,7 +74,6 @@
 import qualified Data.List as L (uncons)
 import Data.Massiv.Array.Delayed.Pull
 import Data.Massiv.Array.Delayed.Push
-import Data.Massiv.Array.Delayed.Stream
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Array.Ops.Construct
 import Data.Massiv.Array.Ops.Map
diff --git a/src/Data/Massiv/Array/Stencil/Internal.hs b/src/Data/Massiv/Array/Stencil/Internal.hs
--- a/src/Data/Massiv/Array/Stencil/Internal.hs
+++ b/src/Data/Massiv/Array/Stencil/Internal.hs
@@ -41,7 +41,9 @@
 -- | This is a simple wrapper for value of an array cell. It is used in order to improve safety of
 -- `Stencil` mapping. Using various class instances, such as `Num` and `Functor` for example, make
 -- it possible to manipulate the value, without having direct access to it.
-newtype Value e = Value { unValue :: e } deriving (Show, Bounded)
+newtype Value e = Value
+  { unValue :: e
+  } deriving (Bounded)
 
 instance Functor Value where
   fmap f (Value e) = Value (f e)
diff --git a/src/Data/Massiv/Array/Stencil/Unsafe.hs b/src/Data/Massiv/Array/Stencil/Unsafe.hs
--- a/src/Data/Massiv/Array/Stencil/Unsafe.hs
+++ b/src/Data/Massiv/Array/Stencil/Unsafe.hs
@@ -13,6 +13,8 @@
 module Data.Massiv.Array.Stencil.Unsafe
   ( -- * Stencil
     makeUnsafeStencil
+  , unsafeMapStencil
+  -- ** Deprecated
   , mapStencilUnsafe
   , forStencilUnsafe
   ) where
@@ -56,13 +58,9 @@
     stencil getVal !ix = inline relStencil $ \ !ixD -> getVal (liftIndex2 (+) ix ixD)
     {-# INLINE stencil #-}
 {-# INLINE forStencilUnsafe #-}
+{-# DEPRECATED forStencilUnsafe "In favor of `unsafeMapStencil`" #-}
 
 
--- | This is an unsafe version of `Data.Massiv.Array.Stencil.mapStencil`, that does no
--- stencil validation. There is no performance difference between the two, but the unsafe
--- version has an advantage of not requiring to deal with `Value` wrapper.
---
--- @since 0.4.3
 mapStencilUnsafe ::
      Manifest r ix e
   => Border e
@@ -71,7 +69,26 @@
   -> ((ix -> e) -> a)
   -> Array r ix e
   -> Array DW ix a
-mapStencilUnsafe b sSz sCenter stencilF !arr = insertWindow warr window
+mapStencilUnsafe b sz ix f = unsafeMapStencil b sz ix (const f)
+{-# INLINE mapStencilUnsafe #-}
+{-# DEPRECATED mapStencilUnsafe "In favor of `unsafeMapStencil`" #-}
+
+-- | This is an unsafe version of `Data.Massiv.Array.Stencil.mapStencil`, that does no
+-- take `Stencil` as argument, as such it does no stencil validation. There is no
+-- performance difference between the two, but the unsafe version has an advantage of not
+-- requiring to deal with `Value` wrapper and has access to the actual index with the
+-- array.
+--
+-- @since 0.5.0
+unsafeMapStencil ::
+     Manifest r ix e
+  => Border e
+  -> Sz ix
+  -> ix
+  -> (ix -> (ix -> e) -> a)
+  -> Array r ix e
+  -> Array DW ix a
+unsafeMapStencil b sSz sCenter stencilF !arr = insertWindow warr window
   where
     !warr = DArray (getComp arr) sz (stencil (borderIndex b arr))
     !window =
@@ -83,9 +100,9 @@
         }
     !sz = size arr
     !windowSz = Sz (liftIndex2 (-) (unSz sz) (liftIndex (subtract 1) (unSz sSz)))
-    stencil getVal !ix = inline stencilF $ \ !ixD -> getVal (liftIndex2 (+) ix ixD)
+    stencil getVal !ix = inline (stencilF ix) $ \ !ixD -> getVal (liftIndex2 (+) ix ixD)
     {-# INLINE stencil #-}
-{-# INLINE mapStencilUnsafe #-}
+{-# INLINE unsafeMapStencil #-}
 
 
 -- | Similar to `Data.Massiv.Array.Stencil.makeStencil`, but there are no guarantees that the
diff --git a/src/Data/Massiv/Array/Unsafe.hs b/src/Data/Massiv/Array/Unsafe.hs
--- a/src/Data/Massiv/Array/Unsafe.hs
+++ b/src/Data/Massiv/Array/Unsafe.hs
@@ -5,7 +5,7 @@
 {-# LANGUAGE PatternSynonyms #-}
 -- |
 -- Module      : Data.Massiv.Array.Unsafe
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -30,11 +30,14 @@
   , unsafeSlice
   , unsafeOuterSlice
   , unsafeInnerSlice
-  -- , unsafeLinearSlice
+  , unsafeLinearSlice
     -- * Mutable interface
   , unsafeThaw
   , unsafeFreeze
   , unsafeNew
+  , unsafeCreateArray
+  , unsafeCreateArray_
+  , unsafeCreateArrayS
     -- ** Read
   , unsafeRead
   , unsafeLinearRead
@@ -74,17 +77,27 @@
   , unsafeAtomicXorIntArray
   , unsafeCasIntArray
     -- ** Other operations
+  , unsafeBoxedArray
+  , unsafeNormalBoxedArray
+  , unsafeFromBoxedVector
   , unsafeUnstablePartitionRegionM
+  , module Data.Massiv.Vector.Unsafe
+  , module Data.Massiv.Array.Stencil.Unsafe
   ) where
 
 import Data.Massiv.Array.Delayed.Pull (D)
 import Data.Massiv.Array.Delayed.Push (unsafeMakeLoadArray)
+import Data.Massiv.Array.Manifest.Boxed
 import Data.Massiv.Array.Manifest.Primitive
 import Data.Massiv.Array.Manifest.Storable
+import Data.Massiv.Array.Mutable.Internal
+import Data.Massiv.Array.Ops.Sort (unsafeUnstablePartitionRegionM)
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.Index.Internal (Sz(SafeSz))
 import Data.Massiv.Core.Index.Stride (Stride(SafeStride))
-import Data.Massiv.Array.Ops.Sort (unsafeUnstablePartitionRegionM)
+import Data.Massiv.Vector.Unsafe
+import Data.Massiv.Array.Stencil.Unsafe
+
 
 unsafeBackpermute :: (Source r' ix' e, Index ix) =>
                      Sz ix -> (ix -> ix') -> Array r' ix' e -> Array D ix e
diff --git a/src/Data/Massiv/Core.hs b/src/Data/Massiv/Core.hs
--- a/src/Data/Massiv/Core.hs
+++ b/src/Data/Massiv/Core.hs
@@ -8,6 +8,10 @@
 --
 module Data.Massiv.Core
   ( Array(List, unList)
+  , Vector
+  , MVector
+  , Matrix
+  , MMatrix
   , Elt
   , Construct
   , Load(R, loadArrayM, defaultElement)
diff --git a/src/Data/Massiv/Core/Common.hs b/src/Data/Massiv/Core/Common.hs
--- a/src/Data/Massiv/Core/Common.hs
+++ b/src/Data/Massiv/Core/Common.hs
@@ -15,6 +15,10 @@
 -- Portability : non-portable
 module Data.Massiv.Core.Common
   ( Array
+  , Vector
+  , MVector
+  , Matrix
+  , MMatrix
   , Elt
   , Steps(..)
   , Stream(..)
@@ -96,7 +100,7 @@
 import Data.Massiv.Core.Index.Internal (Sz(SafeSz))
 import Data.Typeable
 import Data.Vector.Fusion.Bundle.Size
-import qualified Data.Vector.Fusion.Stream.Monadic as S
+import qualified Data.Vector.Fusion.Stream.Monadic as S (Stream)
 import Data.Vector.Fusion.Util
 
 #include "massiv.h"
@@ -107,6 +111,30 @@
 -- nested fashion, depth of which is controlled by @`Rank` ix@.
 data family Array r ix e :: *
 
+-- | Type synonym for a single dimension array, or simply a flat vector.
+--
+-- @since 0.5.0
+type Vector r e = Array r Ix1 e
+
+
+-- | Type synonym for a single dimension mutable array, or simply a flat mutable vector.
+--
+-- @since 0.5.0
+type MVector s r e = MArray s r Ix1 e
+
+-- | Type synonym for a two-dimentsional array, or simply a matrix.
+--
+-- @since 0.5.0
+type Matrix r e = Array r Ix2 e
+
+
+-- | Type synonym for a two-dimentsional mutable array, or simply a mutable matrix.
+--
+-- @since 0.5.0
+type MMatrix s r e = MArray s r Ix2 e
+
+
+
 type family Elt r ix e :: * where
   Elt r Ix1 e = e
   Elt r ix  e = Array (R r) (Lower ix) e
@@ -115,19 +143,17 @@
 
 
 
-class Stream r ix e where
+class Load r ix e => Stream r ix e where
   toStream :: Array r ix e -> Steps Id e
 
+  toStreamIx :: Array r ix e -> Steps Id (ix, e)
+
 data Steps m e = Steps
   { stepsStream :: S.Stream m e
   , stepsSize   :: Size
   }
 
-instance Monad m => Functor (Steps m) where
-  fmap f s = s { stepsStream = S.map f (stepsStream s) }
-  {-# INLINE fmap #-}
 
-
 -- | Array types that can be constructed.
 class (Typeable r, Index ix) => Construct r ix e where
   {-# MINIMAL setComp,(makeArray|makeArrayLinear) #-}
@@ -209,7 +235,7 @@
 
 -- | Arrays that can be used as source to practically any manipulation function.
 class Load r ix e => Source r ix e where
-  {-# MINIMAL (unsafeIndex|unsafeLinearIndex) #-}
+  {-# MINIMAL (unsafeIndex|unsafeLinearIndex), unsafeLinearSlice #-}
 
   -- | Lookup element in the array. No bounds check is performed and access of
   -- arbitrary memory is possible when invalid index is supplied.
@@ -229,10 +255,10 @@
   unsafeLinearIndex !arr = unsafeIndex arr . fromLinearIndex (size arr)
   {-# INLINE unsafeLinearIndex #-}
 
-  -- -- | Source arrays also give us ability to look at their linear slices
-  -- --
-  -- -- @since 0.4.0
-  -- unsafeLinearSlice :: Ix1 -> Sz1 -> Array r ix e -> Array r Ix1 e
+  -- | Source arrays also give us ability to look at their linear slices
+  --
+  -- @since 0.4.1
+  unsafeLinearSlice :: Ix1 -> Sz1 -> Array r ix e -> Array r Ix1 e
 
 -- | Any array that can be computed and loaded into memory
 class (Typeable r, Index ix) => Load r ix e where
@@ -268,15 +294,15 @@
   -- in constant time is not possible, `Nothing` should be returned. This value will be
   -- used as the initial size of the mutable array in which loading will happen.
   --
-  -- @since 0.4.1
+  -- @since 0.5.0
   maxSize :: Array r ix e -> Maybe (Sz ix)
   maxSize = Just . size
   {-# INLINE maxSize #-}
 
-  -- | Load into a supplied mutable array sequentially. Returned array does npt have to be
+  -- | Load into a supplied mutable array sequentially. Returned array does not have to be
   -- the same
   --
-  -- @since 0.4.1
+  -- @since 0.5.0
   unsafeLoadIntoS ::
        (Mutable r' ix e, PrimMonad m)
     => MArray (PrimState m) r' ix e
@@ -289,7 +315,7 @@
 
   -- | Same as `unsafeLoadIntoS`, but with respect of computation startegy.
   --
-  -- @since 0.4.1
+  -- @since 0.5.0
   unsafeLoadInto ::
        (Mutable r' ix e, MonadIO m)
     => MArray RealWorld r' ix e
diff --git a/src/Data/Massiv/Core/List.hs b/src/Data/Massiv/Core/List.hs
--- a/src/Data/Massiv/Core/List.hs
+++ b/src/Data/Massiv/Core/List.hs
@@ -32,7 +32,7 @@
 import Data.Coerce
 import Data.Foldable (foldr')
 import qualified Data.List as L
-import qualified Data.Massiv.Array.Manifest.Vector.Stream as S
+import qualified Data.Massiv.Vector.Stream as S
 import Data.Massiv.Core.Common
 import Data.Typeable
 import GHC.Exts
@@ -52,9 +52,9 @@
 instance Construct LN Ix1 e where
   setComp _ = id
   {-# INLINE setComp #-}
-  makeArray _ (Sz n) f = coerce (fmap f [0 .. n - 1])
+  makeArray _ (Sz n) f = coerce (L.map f [0 .. n - 1])
   {-# INLINE makeArray #-}
-  makeArrayLinear _ (Sz n) f = coerce (fmap f [0 .. n - 1])
+  makeArrayLinear _ (Sz n) f = coerce (L.map f [0 .. n - 1])
   {-# INLINE makeArrayLinear #-}
 
 instance {-# OVERLAPPING #-} Nested LN Ix1 e where
@@ -383,6 +383,12 @@
   toStream = S.fromList . coerce
   {-# INLINE toStream #-}
 
-instance Ragged L ix e => Stream L ix e where
-  toStream = S.fromList . coerce . lData . flattenRagged
+  toStreamIx = S.indexed . S.fromList . coerce
+  {-# INLINE toStreamIx #-}
+
+instance Stream L Ix1 e where
+  toStream = toStream . lData
   {-# INLINE toStream #-}
+
+  toStreamIx = toStreamIx . lData
+  {-# INLINE toStreamIx #-}
diff --git a/src/Data/Massiv/Vector.hs b/src/Data/Massiv/Vector.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Massiv/Vector.hs
@@ -0,0 +1,1904 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+-- |
+-- Module      : Data.Massiv.Vector
+-- Copyright   : (c) Alexey Kuleshevich 2020
+-- License     : BSD3
+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
+-- Stability   : experimental
+-- Portability : non-portable
+--
+module Data.Massiv.Vector
+  ( Vector
+  , MVector
+  -- * Accessors
+  -- *** Size
+  , slength
+  , snull
+  -- *** Indexing
+  , (!)
+  , (!?)
+  , head'
+  , shead'
+  , last'
+  -- *** Monadic Indexing
+  , indexM
+  , headM
+  , sheadM
+  , lastM
+  -- ** Slicing
+  , slice
+  , slice'
+  , sliceM
+  , sslice
+  , sliceAt
+  , sliceAt'
+  , sliceAtM
+  -- *** Init
+  , init
+  , init'
+  , initM
+  -- *** Tail
+  , tail
+  , tail'
+  , tailM
+  -- *** Take
+  , take
+  , take'
+  , takeM
+  , stake
+  -- *** Drop
+  , drop
+  , drop'
+  , dropM
+  , sdrop
+  -- * Construction
+  -- ** Initialization
+  , empty
+  , sempty
+  , singleton
+  , ssingleton
+  , A.replicate
+  , sreplicate
+  , generate
+  , sgenerate
+  -- , iterateN
+  -- , iiterateN
+  , siterateN
+  -- ** Monadic initialization
+  , sreplicateM
+  , sgenerateM
+  , siterateNM
+  -- , create
+  -- , createT
+  -- ** Unfolding
+  , sunfoldr
+  , sunfoldrM
+  , sunfoldrN
+  , sunfoldrNM
+  , sunfoldrExactN
+  , sunfoldrExactNM
+  -- , constructN
+  -- , constructrN
+  -- -- ** Enumeration
+  , senumFromN
+  , senumFromStepN
+  -- ** Concatenation
+  -- , consS -- cons
+  -- , snocS -- snoc
+  , sappend  -- (++)
+  , sconcat -- concat
+  -- -- ** Restricitng memory usage
+  -- , force
+  -- -- * Modifying
+  -- -- ** Bulk updates
+  -- , (//)
+  -- , update_
+  -- -- ** Accumulations
+  -- , accum
+  -- , accumulate_
+  -- -- ** Permutations
+  -- , reverse
+  -- , backpermute
+  -- -- ** Mutable updates
+  -- , modify
+  -- -- * Elementwise
+  -- -- ** Mapping
+  , smap
+  , simap
+  -- , sconcatMap
+  -- ** Monadic mapping
+  , straverse
+  , sitraverse
+  , smapM
+  , smapM_
+  , simapM
+  , simapM_
+  , sforM
+  , sforM_
+  , siforM
+  , siforM_
+  -- ** Zipping
+  , szip
+  , szip3
+  , szip4
+  , szip5
+  , szip6
+  , szipWith
+  , szipWith3
+  , szipWith4
+  , szipWith5
+  , szipWith6
+  , sizipWith
+  , sizipWith3
+  , sizipWith4
+  , sizipWith5
+  , sizipWith6
+  -- ** Monadic zipping
+  , szipWithM
+  , szipWith3M
+  , szipWith4M
+  , szipWith5M
+  , szipWith6M
+  , sizipWithM
+  , sizipWith3M
+  , sizipWith4M
+  , sizipWith5M
+  , sizipWith6M
+
+  , szipWithM_
+  , szipWith3M_
+  , szipWith4M_
+  , szipWith5M_
+  , szipWith6M_
+  , sizipWithM_
+  , sizipWith3M_
+  , sizipWith4M_
+  , sizipWith5M_
+  , sizipWith6M_
+  -- * Predicates
+  -- ** Filtering
+  , sfilter
+  , sifilter
+  , sfilterM
+  , sifilterM
+  -- , uniq -- sunique?
+  , smapMaybe
+  , smapMaybeM
+  , scatMaybes
+  , simapMaybe
+  , simapMaybeM
+  -- , takeWhile
+  -- , dropWhile
+  -- -- ** Partitioning
+  -- , partition
+  -- , unstablePartition
+  -- , partitionWith
+  -- , span
+  -- , break
+  -- -- ** Searching
+  -- , elem
+  -- , notElem
+  -- , find
+  -- , findIndex
+  -- , findIndices
+  -- , elemIndex
+  -- , elemIndices
+  -- * Folding
+  , sfoldl
+  , sfoldlM
+  , sfoldlM_
+  , sifoldl
+  , sifoldlM
+  , sifoldlM_
+  , sfoldl1'
+  , sfoldl1M
+  , sfoldl1M_
+  -- ** Specialized folds
+  , sor
+  , sand
+  , sall
+  , sany
+  , ssum
+  , sproduct
+  , smaximum'
+  , smaximumM
+  -- , maximumBy
+  , sminimum'
+  , sminimumM
+  -- , minimumBy
+  -- , minIndex
+  -- , minIndexBy
+  -- , maxIndex
+  -- , maxIndexBy
+  -- -- ** Prefix sums
+  -- , prescanl
+  -- , prescanl'
+  -- , postscanl
+  -- , postscanl'
+  -- , scanl
+  -- , scanl'
+  -- , scanl1
+  -- , scanl1'
+  -- , prescanr
+  -- , prescanr'
+  -- , postscanr
+  -- , postscanr'
+  -- , scanr
+  -- , scanr'
+  -- , scanr1
+  -- , scanr1'
+  -- * Conversions
+  -- ** Lists
+  , stoList
+  , sfromList
+  , sfromListN
+  -- -- ** Other vector types
+  -- , convert
+  -- -- ** Mutable vectors
+  -- , freeze
+  -- , thaw
+  -- , copy
+  -- , unsafeFreeze
+  -- , unsafeThaw
+  -- , unsafeCopy
+  -- * Deprecated
+  , takeS
+  , dropS
+  , unfoldr
+  , unfoldrN
+  , filterS
+  , ifilterS
+  , filterM
+  , ifilterM
+  , mapMaybeS
+  , imapMaybeS
+  , mapMaybeM
+  , imapMaybeM
+  , catMaybesS
+  , traverseS
+  ) where
+
+import Control.Monad hiding (filterM, replicateM)
+import Data.Coerce
+import Data.Massiv.Array.Delayed.Pull
+import Data.Massiv.Array.Delayed.Stream
+import qualified Data.Massiv.Array.Ops.Construct as A (makeArrayR, replicate)
+import Data.Massiv.Core.Common
+import qualified Data.Massiv.Vector.Stream as S
+import Data.Massiv.Vector.Unsafe
+import Prelude hiding (drop, init, length, null, replicate, splitAt, tail, take)
+
+-- ========= --
+-- Accessors --
+-- ========= --
+
+
+------------------------
+-- Length information --
+------------------------
+
+-- | /O(1)/ - Get the length of a stream vector, but only if it is known excatly. Calling
+-- `size` will always give you the exact size instead, but for `DS` representation could
+-- result in evaluating of the whole stream.
+--
+-- @since 0.5.0
+slength :: Stream r ix e => Array r ix e -> Maybe Sz1
+slength v =
+  case stepsSize (toStream v) of
+    Exact sz -> Just (SafeSz sz)
+    _        -> Nothing
+{-# INLINE slength #-}
+
+-- | /O(1)/ - Check if a stream array is empty.
+--
+-- @since 0.5.0
+snull :: Stream r ix e => Array r ix e -> Bool
+snull = S.unId . S.null . toStream
+{-# INLINE snull #-}
+
+--------------
+-- Indexing --
+--------------
+
+-- TODO: Add to vector: headMaybe
+
+-- | Get the first element of a `Source` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+head' :: Source r Ix1 e => Vector r e -> e
+head' = either throw id . headM
+{-# INLINE head' #-}
+
+
+-- | Get the first element of a `Source` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+headM :: (Source r Ix1 e, MonadThrow m) => Vector r e -> m e
+headM v
+  | isEmpty v = throwM $ SizeEmptyException (size v)
+  | otherwise = pure $ unsafeLinearIndex v 0
+{-# INLINE headM #-}
+
+
+-- | Get the first element of a `Stream` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+shead' :: Stream r Ix1 e => Vector r e -> e
+shead' = either throw id . sheadM
+{-# INLINE shead' #-}
+
+-- | Get the first element of a `Stream` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+sheadM :: (Stream r Ix1 e, MonadThrow m) => Vector r e -> m e
+sheadM v =
+  case S.unId (S.headMaybe (toStream v)) of
+    Nothing -> throwM $ SizeEmptyException (size v)
+    Just e  -> pure e
+{-# INLINE sheadM #-}
+
+-- | Get the last element of a `Source` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+last' :: Source r Ix1 e => Vector r e -> e
+last' = either throw id . lastM
+{-# INLINE last' #-}
+
+
+-- | Get the last element of a `Source` vector. Throws an error on empty.
+--
+-- @since 0.5.0
+lastM :: (Source r Ix1 e, MonadThrow m) => Vector r e -> m e
+lastM v
+  | k == 0 = throwM $ SizeEmptyException (size v)
+  | otherwise = pure $ unsafeLinearIndex v (k - 1)
+  where k = unSz (size v)
+{-# INLINE lastM #-}
+
+
+-- | /O(1)/ - Take a slice of a `Source` vector. Never fails, instead adjusts the indices.
+--
+-- @since 0.5.0
+slice :: Source r Ix1 e => Ix1 -> Sz1 -> Vector r e -> Vector r e
+slice !i (Sz k) v = unsafeLinearSlice i' newSz v
+  where
+    !i' = min n (max 0 i)
+    !newSz = SafeSz (min (n - i') k)
+    Sz n = size v
+{-# INLINE slice #-}
+
+-- | /O(1)/ - Take a slice of a `Stream` vector. Never fails, instead adjusts the indices.
+--
+-- @since 0.5.0
+sslice :: Stream r Ix1 e => Ix1 -> Sz1 -> Vector r e -> Vector DS e
+sslice !i (Sz k) = fromSteps . S.slice i k . S.toStream
+{-# INLINE sslice #-}
+
+
+-- | /O(1)/ - Take a slice of a `Source` vector. Throws an error on incorrect indices.
+--
+-- @since 0.5.0
+slice' :: Source r Ix1 e => Ix1 -> Sz1 -> Vector r e -> Vector r e
+slice' i k = either throw id . sliceM i k
+{-# INLINE slice' #-}
+
+-- | /O(1)/ - Take a slice of a `Source` vector. Throws an error on incorrect indices.
+--
+-- @since 0.5.0
+sliceM :: (Source r Ix1 e, MonadThrow m) => Ix1 -> Sz1 -> Vector r e -> m (Vector r e)
+sliceM i newSz@(Sz k) v
+  | i >= 0 && k <= n - i = pure $ unsafeLinearSlice i newSz v
+  | otherwise = throwM $ SizeSubregionException sz i newSz
+  where
+    sz@(Sz n) = size v
+{-# INLINE sliceM #-}
+
+-- | /O(1)/ - Get the vector without the last element. Never fails
+--
+-- @since 0.5.0
+init :: Source r Ix1 e => Vector r e -> Vector r e
+init v = unsafeLinearSlice 0 (Sz (coerce (size v) - 1)) v
+{-# INLINE init #-}
+
+-- | /O(1)/ - Get the vector without the last element. Throws an error on empty
+--
+-- @since 0.5.0
+init' :: Source r Ix1 e => Vector r e -> Vector r e
+init' = either throw id . initM
+{-# INLINE init' #-}
+
+-- | /O(1)/ - Get the vector without the last element. Throws an error on empty
+--
+-- @since 0.5.0
+initM :: (Source r Ix1 e, MonadThrow m) => Vector r e -> m (Vector r e)
+initM v = do
+  when (isEmpty v) $ throwM $ SizeEmptyException $ size v
+  pure $ unsafeInit v
+{-# INLINE initM #-}
+
+
+
+-- | /O(1)/ - Get the vector without the first element. Never fails
+--
+-- @since 0.5.0
+tail :: Source r Ix1 e => Vector r e -> Vector r e
+tail = drop 1
+{-# INLINE tail #-}
+
+
+-- | /O(1)/ - Get the vector without the first element. Throws an error on empty
+--
+-- @since 0.5.0
+tail' :: Source r Ix1 e => Vector r e -> Vector r e
+tail' = either throw id . tailM
+{-# INLINE tail' #-}
+
+
+-- | /O(1)/ - Get the vector without the first element. Throws an error on empty
+--
+-- @since 0.5.0
+tailM :: (Source r Ix1 e, MonadThrow m) => Vector r e -> m (Vector r e)
+tailM v = do
+  when (isEmpty v) $ throwM $ SizeEmptyException $ size v
+  pure $ unsafeTail v
+{-# INLINE tailM #-}
+
+
+
+-- | /O(1)/ - Get the vector with the first @n@ elements. Never fails
+--
+-- @since 0.5.0
+take :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+take k = fst . sliceAt k
+{-# INLINE take #-}
+
+-- | /O(1)/ - Get the vector with the first @n@ elements. Throws an error size is less than @n@
+--
+-- @since 0.5.0
+take' :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+take' k = either throw id . takeM k
+{-# INLINE take' #-}
+
+-- | /O(1)/ - Get the vector with the first @n@ elements. Throws an error size is less than @n@
+--
+-- @since 0.5.0
+takeM :: (Source r Ix1 e, MonadThrow m) => Sz1 -> Vector r e -> m (Vector r e)
+takeM k v = do
+  let sz = size v
+  when (k > sz) $ throwM $ SizeSubregionException sz 0 k
+  pure $ unsafeTake k v
+{-# INLINE takeM #-}
+
+-- | /O(1)/ - Get a `Stream` vector with the first @n@ elements. Never fails
+--
+-- @since 0.5.0
+stake :: Stream r Ix1 e => Sz1 -> Vector r e -> Vector DS e
+stake n = fromSteps . S.take (unSz n) . S.toStream
+{-# INLINE stake #-}
+
+-- |
+--
+-- @since 0.5.0
+drop :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+drop k = snd . sliceAt k
+{-# INLINE drop #-}
+
+-- | Keep all but the first @n@ elements from the delayed stream vector.
+--
+-- @since 0.5.0
+sdrop :: Stream r Ix1 e => Sz1 -> Vector r e -> Vector DS e
+sdrop n = fromSteps . S.drop (unSz n) . S.toStream
+{-# INLINE sdrop #-}
+
+-- |
+--
+-- @since 0.5.0
+drop' :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+drop' k = either throw id . dropM k
+{-# INLINE drop' #-}
+
+-- |
+--
+-- @since 0.5.0
+dropM :: (Source r Ix1 e, MonadThrow m) => Sz1 -> Vector r e -> m (Vector r e)
+dropM k@(Sz d) v = do
+  let sz@(Sz n) = size v
+  when (k > sz) $ throwM $ SizeSubregionException sz d (sz - k)
+  pure $ unsafeLinearSlice d (SafeSz (n - d)) v
+{-# INLINE dropM #-}
+
+
+-- | Samel as `sliceAt`, except it never fails.
+--
+--
+-- @since 0.5.0
+sliceAt :: Source r Ix1 e => Sz1 -> Vector r e -> (Vector r e, Vector r e)
+sliceAt (Sz k) v = (unsafeTake d v, unsafeDrop d v)
+  where
+    !n = coerce (size v)
+    !d = SafeSz (min k n)
+{-# INLINE sliceAt #-}
+
+-- | Same as `Data.Massiv.Array.splitAt'`, except for a flat vector.
+--
+-- @since 0.5.0
+sliceAt' :: Source r Ix1 e => Sz1 -> Vector r e -> (Vector r e, Vector r e)
+sliceAt' k = either throw id . sliceAtM k
+{-# INLINE sliceAt' #-}
+
+-- | Same as `Data.Massiv.Array.splitAtM`, except for a flat vector.
+--
+-- @since 0.5.0
+sliceAtM :: (Source r Ix1 e, MonadThrow m) => Sz1 -> Vector r e -> m (Vector r e, Vector r e)
+sliceAtM k v = do
+  l <- takeM k v
+  pure (l, unsafeDrop k v)
+{-# INLINE sliceAtM #-}
+
+
+-- | Create an empty delayed stream vector
+--
+-- @since 0.5.0
+sempty :: Vector DS e
+sempty = DSArray S.empty
+{-# INLINE sempty #-}
+
+-- | Create a delayed stream vector with a single element
+--
+-- @since 0.5.0
+ssingleton :: e -> Vector DS e
+ssingleton = DSArray . S.singleton
+{-# INLINE ssingleton #-}
+
+-- | Replicate the same element @n@ times
+--
+-- @since 0.5.0
+sreplicate :: Sz1 -> e -> Vector DS e
+sreplicate (Sz n) = DSArray . S.replicate n
+{-# INLINE sreplicate #-}
+
+-- | Create a delayed vector of length @n@ with a function that maps an index to an
+-- element. Same as `makeLinearArray`
+--
+-- @since 0.5.0
+generate :: Comp -> Sz1 -> (Ix1 -> e) -> Vector D e
+generate = makeArrayLinear
+{-# INLINE generate #-}
+
+-- | Create a delayed stream vector of length @n@ with a function that maps an index to an
+-- element. Same as `makeLinearArray`
+--
+-- @since 0.5.0
+sgenerate :: Sz1 -> (Ix1 -> e) -> Vector DS e
+sgenerate (Sz n) = DSArray . S.generate n
+{-# INLINE sgenerate #-}
+
+
+-- | Create a delayed stream vector of length @n@ by repeatedly apply a function to the
+-- initial value.
+--
+-- @since 0.5.0
+siterateN :: Sz1 -> (e -> e) -> e -> Vector DS e
+siterateN n f a = fromSteps $ S.iterateN (unSz n) f a
+{-# INLINE siterateN #-}
+
+
+-- | Create a vector by using the same monadic action @n@ times
+--
+-- @since 0.5.0
+sreplicateM :: Monad m => Sz1 -> m e -> m (Vector DS e)
+sreplicateM n f = fromStepsM $ S.replicateM (unSz n) f
+{-# INLINE sreplicateM #-}
+
+
+-- | Create a delayed stream vector of length @n@ with a monadic action that from an index
+-- generates an element.
+--
+-- @since 0.5.0
+sgenerateM :: Monad m => Sz1 -> (Ix1 -> m e) -> m (Vector DS e)
+sgenerateM n f = fromStepsM $ S.generateM (unSz n) f
+{-# INLINE sgenerateM #-}
+
+
+-- | Create a delayed stream vector of length @n@ by repeatedly apply a monadic action to
+-- the initial value.
+--
+-- @since 0.5.0
+siterateNM :: Monad m => Sz1 -> (e -> m e) -> e -> m (Vector DS e)
+siterateNM n f a = fromStepsM $ S.iterateNM (unSz n) f a
+{-# INLINE siterateNM #-}
+
+
+
+
+-- | Right unfolding function. Useful when it is unknown ahead of time on how many
+-- elements the vector will have.
+--
+-- ====__Example__
+--
+-- >>> import Data.Massiv.Array as A
+-- >>> sunfoldr (\i -> if i < 9 then Just (i * i, i + 1) else Nothing) (0 :: Int)
+-- Array DS Seq (Sz1 9)
+--   [ 0, 1, 4, 9, 16, 25, 36, 49, 64 ]
+--
+-- @since 0.5.0
+sunfoldr :: (s -> Maybe (e, s)) -> s -> Vector DS e
+sunfoldr f = DSArray . S.unfoldr f
+{-# INLINE sunfoldr #-}
+
+
+
+-- | /O(n)/ - Right unfolding function with at most @n@ number of elements.
+--
+-- ==== __Example__
+--
+-- >>> import Data.Massiv.Array as A
+-- >>> sunfoldrN 9 (\i -> Just (i*i, i + 1)) (0 :: Int)
+-- Array DS Seq (Sz1 9)
+--   [ 0, 1, 4, 9, 16, 25, 36, 49, 64 ]
+--
+-- @since 0.5.0
+sunfoldrN ::
+     Sz1
+  -- ^ @n@ - maximum number of elements that the vector will have
+  -> (s -> Maybe (e, s))
+  -- ^ Unfolding function. Stops when `Nothing` is returned or maximum number of elements
+  -- is reached.
+  -> s -- ^ Inititial element.
+  -> Vector DS e
+sunfoldrN (Sz n) f = DSArray . S.unfoldrN n f
+{-# INLINE sunfoldrN #-}
+
+-- | Same as `unfoldr`, by with monadic generating function.
+--
+-- @since 0.5.0
+sunfoldrM :: Monad m => (s -> m (Maybe (e, s))) -> s -> m (Vector DS e)
+sunfoldrM f = fromStepsM . S.unfoldrM f
+{-# INLINE sunfoldrM #-}
+
+-- | Same as `unfoldrN`, by with monadic generating function.
+--
+-- @since 0.5.0
+sunfoldrNM :: Monad m => Sz1 -> (s -> m (Maybe (e, s))) -> s -> m (Vector DS e)
+sunfoldrNM (Sz n) f = fromStepsM . S.unfoldrNM n f
+{-# INLINE sunfoldrNM #-}
+
+
+-- | Similar to `unfoldrN`, except the length of the resulting vector will be exactly @n@
+--
+-- @since 0.5.0
+sunfoldrExactN :: Sz1 -> (s -> (e, s)) -> s -> Vector DS e
+sunfoldrExactN (Sz n) f = fromSteps . S.unfoldrExactN n f
+{-# INLINE sunfoldrExactN #-}
+
+-- | Similar to `unfoldrNM`, except the length of the resulting vector will be exactly @n@
+--
+-- @since 0.5.0
+sunfoldrExactNM :: Monad m => Sz1 -> (s -> m (e, s)) -> s -> m (Vector DS e)
+sunfoldrExactNM (Sz n) f = fromStepsM . S.unfoldrExactNM n f
+{-# INLINE sunfoldrExactNM #-}
+
+
+-- | Enumerate from a starting number @n@ times with a step @1@
+--
+-- @since 0.5.0
+senumFromN :: Num e => e -> Sz1 -> Vector DS e
+senumFromN x (Sz n) = DSArray $ S.enumFromStepN x 1 n
+{-# INLINE senumFromN #-}
+
+-- | Enumerate from a starting number @n@ times with a custom step value
+--
+-- @since 0.5.0
+senumFromStepN ::
+     Num e
+  => e -- ^ Starting value
+  -> e -- ^ Step
+  -> Sz1 -- ^ Resulting length of a vector
+  -> Vector DS e
+senumFromStepN x step (Sz n) = DSArray $ S.enumFromStepN x step n
+{-# INLINE senumFromStepN #-}
+
+
+
+-- | Append two vectors together
+--
+-- @since 0.5.0
+sappend :: (Stream r1 Ix1 e, Stream r2 Ix1 e) => Vector r1 e -> Vector r2 e -> Vector DS e
+sappend a1 a2 = fromSteps (toStream a1 `S.append` toStream a2)
+{-# INLINE sappend #-}
+
+
+-- | Concat vectors together
+--
+-- @since 0.5.0
+sconcat :: Stream r Ix1 e => [Vector r e] -> Vector DS e
+sconcat = DSArray . foldMap toStream
+{-# INLINE sconcat #-}
+
+-- | Convert a list to a delayed stream vector
+--
+-- @since 0.5.0
+sfromList :: [e] -> Vector DS e
+sfromList = fromSteps . S.fromList
+{-# INLINE sfromList #-}
+
+-- | Convert a list of a known length to a delayed stream vector
+--
+-- @since 0.5.0
+sfromListN :: Int -> [e] -> Vector DS e
+sfromListN n = fromSteps . S.fromListN n
+{-# INLINE sfromListN #-}
+
+-- | Convert an array to a list by the means of a delayed stream vector.
+--
+-- @since 0.5.0
+stoList :: Stream r ix e => Array r ix e -> [e]
+stoList = S.toList . toStream
+{-# INLINE stoList #-}
+
+
+
+
+
+
+-- | Sequentially filter out elements from the array according to the supplied predicate.
+--
+-- ==== __Example__
+--
+-- >>> import Data.Massiv.Array as A
+-- >>> arr = makeArrayR D Seq (Sz2 3 4) fromIx2
+-- >>> arr
+-- Array D Seq (Sz (3 :. 4))
+--   [ [ (0,0), (0,1), (0,2), (0,3) ]
+--   , [ (1,0), (1,1), (1,2), (1,3) ]
+--   , [ (2,0), (2,1), (2,2), (2,3) ]
+--   ]
+-- >>> sfilter (even . fst) arr
+-- Array DS Seq (Sz1 8)
+--   [ (0,0), (0,1), (0,2), (0,3), (2,0), (2,1), (2,2), (2,3) ]
+--
+-- @since 0.5.0
+sfilter :: S.Stream r ix e => (e -> Bool) -> Array r ix e -> Vector DS e
+sfilter f = DSArray . S.filter f . S.toStream
+{-# INLINE sfilter #-}
+
+
+-- | Similar to `sfilter`, but map with an index aware function.
+--
+-- @since 0.5.0
+sifilter :: Stream r ix a => (ix -> a -> Bool) -> Array r ix a -> Vector DS a
+sifilter f =
+  simapMaybe $ \ix e ->
+    if f ix e
+      then Just e
+      else Nothing
+{-# INLINE sifilter #-}
+
+
+-- | Sequentially filter out elements from the array according to the supplied applicative predicate.
+--
+-- ==== __Example__
+--
+-- >>> import Data.Massiv.Array as A
+-- >>> arr = makeArrayR D Seq (Sz2 3 4) fromIx2
+-- >>> arr
+-- Array D Seq (Sz (3 :. 4))
+--   [ [ (0,0), (0,1), (0,2), (0,3) ]
+--   , [ (1,0), (1,1), (1,2), (1,3) ]
+--   , [ (2,0), (2,1), (2,2), (2,3) ]
+--   ]
+-- >>> sfilterM (Just . odd . fst) arr
+-- Just (Array DS Seq (Sz1 4)
+--   [ (1,0), (1,1), (1,2), (1,3) ]
+-- )
+-- >>> sfilterM (\ix@(_, j) -> print ix >> return (even j)) arr
+-- (0,0)
+-- (0,1)
+-- (0,2)
+-- (0,3)
+-- (1,0)
+-- (1,1)
+-- (1,2)
+-- (1,3)
+-- (2,0)
+-- (2,1)
+-- (2,2)
+-- (2,3)
+-- Array DS Seq (Sz1 6)
+--   [ (0,0), (0,2), (1,0), (1,2), (2,0), (2,2) ]
+--
+-- @since 0.5.0
+sfilterM :: (S.Stream r ix e, Applicative f) => (e -> f Bool) -> Array r ix e -> f (Vector DS e)
+sfilterM f arr = DSArray <$> S.filterA f (S.toStream arr)
+{-# INLINE sfilterM #-}
+
+
+-- | Similar to `filterM`, but map with an index aware function.
+--
+-- @since 0.5.0
+sifilterM ::
+     (Stream r ix a, Applicative f) => (ix -> a -> f Bool) -> Array r ix a -> f (Vector DS a)
+sifilterM f =
+  simapMaybeM $ \ix e ->
+    (\p ->
+       if p
+         then Just e
+         else Nothing) <$>
+    f ix e
+{-# INLINE sifilterM #-}
+
+
+-- | Apply a function to each element of the array, while discarding `Nothing` and
+-- keeping the `Maybe` result.
+--
+-- @since 0.5.0
+smapMaybe :: S.Stream r ix a => (a -> Maybe b) -> Array r ix a -> Vector DS b
+smapMaybe f = DSArray . S.mapMaybe f . S.toStream
+{-# INLINE smapMaybe #-}
+
+
+-- | Similar to `smapMaybe`, but map with an index aware function.
+--
+-- @since 0.5.0
+simapMaybe :: Stream r ix a => (ix -> a -> Maybe b) -> Array r ix a -> Vector DS b
+simapMaybe f = DSArray . S.mapMaybe (uncurry f) . toStreamIx
+{-# INLINE simapMaybe #-}
+
+-- | Similar to `smapMaybeM`, but map with an index aware function.
+--
+-- @since 0.5.0
+simapMaybeM ::
+     (Stream r ix a, Applicative f) => (ix -> a -> f (Maybe b)) -> Array r ix a -> f (Vector DS b)
+simapMaybeM f = fmap DSArray . S.mapMaybeA (uncurry f) . toStreamIx
+{-# INLINE simapMaybeM #-}
+
+
+-- | Keep all `Maybe`s and discard the `Nothing`s.
+--
+-- @since 0.5.0
+scatMaybes :: S.Stream r ix (Maybe a) => Array r ix (Maybe a) -> Vector DS a
+scatMaybes = smapMaybe id
+{-# INLINE scatMaybes #-}
+
+
+-- | Similar to `smapMaybe`, but with the use of `Applicative`
+--
+-- @since 0.5.0
+smapMaybeM ::
+     (S.Stream r ix a, Applicative f) => (a -> f (Maybe b)) -> Array r ix a -> f (Vector DS b)
+smapMaybeM f = fmap DSArray . S.mapMaybeA f . S.toStream
+{-# INLINE smapMaybeM #-}
+
+
+
+-- | Map a function over a stream vector
+--
+-- @since 0.5.0
+smap :: S.Stream r ix a => (a -> b) -> Array r ix a -> Vector DS b
+smap f = fromSteps . S.map f . S.toStream
+{-# INLINE smap #-}
+
+-- | Map an index aware function over a stream vector
+--
+-- @since 0.5.0
+simap :: S.Stream r ix a => (ix -> a -> b) -> Array r ix a -> Vector DS b
+simap f = fromSteps . S.map (uncurry f) . S.toStreamIx
+{-# INLINE simap #-}
+
+
+-- | Traverse a stream vector with an applicative function.
+--
+-- @since 0.5.0
+straverse :: (S.Stream r ix a, Applicative f) => (a -> f b) -> Array r ix a -> f (Vector DS b)
+straverse f = fmap fromSteps . S.traverse f . S.toStream
+{-# INLINE straverse #-}
+
+
+-- | Traverse a stream vector with an index aware applicative function.
+--
+-- @since 0.5.0
+sitraverse :: (S.Stream r ix a, Applicative f) => (ix -> a -> f b) -> Array r ix a -> f (Vector DS b)
+sitraverse f = fmap fromSteps . S.traverse (uncurry f) . S.toStreamIx
+{-# INLINE sitraverse #-}
+
+
+-- | Traverse a stream vector with a monadic function.
+--
+-- @since 0.5.0
+smapM :: (S.Stream r ix a, Monad m) => (a -> m b) -> Array r ix a -> m (Vector DS b)
+smapM f = fromStepsM . S.mapM f . S.transStepsId . S.toStream
+{-# INLINE smapM #-}
+
+-- | Traverse a stream vector with a monadic index aware function.
+--
+-- @since 0.5.0
+simapM :: (S.Stream r ix a, Monad m) => (ix -> a -> m b) -> Array r ix a -> m (Vector DS b)
+simapM f = fromStepsM . S.mapM (uncurry f) . S.transStepsId . S.toStreamIx
+{-# INLINE simapM #-}
+
+-- | Traverse a stream vector with a monadic function, while discarding the result
+--
+-- @since 0.5.0
+smapM_ :: (S.Stream r ix a, Monad m) => (a -> m b) -> Array r ix a -> m ()
+smapM_ f = S.mapM_ f . S.transStepsId . S.toStream
+{-# INLINE smapM_ #-}
+
+-- | Traverse a stream vector with a monadic index aware function, while discarding the result
+--
+-- @since 0.5.0
+simapM_ :: (S.Stream r ix a, Monad m) => (ix -> a -> m b) -> Array r ix a -> m ()
+simapM_ f = S.mapM_ (uncurry f) . S.transStepsId . S.toStreamIx
+{-# INLINE simapM_ #-}
+
+
+-- | Same as `smapM`, but with arguments flipped.
+--
+-- @since 0.5.0
+sforM :: (S.Stream r ix a, Monad m) => Array r ix a -> (a -> m b) -> m (Vector DS b)
+sforM = flip smapM
+{-# INLINE sforM #-}
+
+-- | Same as `simapM`, but with arguments flipped.
+--
+-- @since 0.5.0
+siforM :: (S.Stream r ix a, Monad m) => Array r ix a -> (ix -> a -> m b) -> m (Vector DS b)
+siforM = flip simapM
+{-# INLINE siforM #-}
+
+-- | Same as `smapM_`, but with arguments flipped.
+--
+-- @since 0.5.0
+sforM_ :: (S.Stream r ix a, Monad m) => Array r ix a -> (a -> m b) -> m ()
+sforM_ = flip smapM_
+{-# INLINE sforM_ #-}
+
+-- | Same as `simapM_`, but with arguments flipped.
+--
+-- @since 0.5.0
+siforM_ :: (S.Stream r ix a, Monad m) => Array r ix a -> (ix -> a -> m b) -> m ()
+siforM_ = flip simapM_
+{-# INLINE siforM_ #-}
+
+
+
+-- |
+--
+-- @since 0.5.0
+szip ::
+     (S.Stream ra ixa a, S.Stream rb ixb b) => Array ra ixa a -> Array rb ixb b -> Vector DS (a, b)
+szip = szipWith (,)
+{-# INLINE szip #-}
+
+-- |
+--
+-- @since 0.5.0
+szip3 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c)
+  => Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Vector DS (a, b, c)
+szip3 = szipWith3 (,,)
+{-# INLINE szip3 #-}
+
+-- |
+--
+-- @since 0.5.0
+szip4 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d)
+  => Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Vector DS (a, b, c, d)
+szip4 = szipWith4 (,,,)
+{-# INLINE szip4 #-}
+
+-- |
+--
+-- @since 0.5.0
+szip5 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d, S.Stream re ixe e)
+  => Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Vector DS (a, b, c, d, e)
+szip5 = szipWith5 (,,,,)
+{-# INLINE szip5 #-}
+
+-- |
+--
+-- @since 0.5.0
+szip6 ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , S.Stream rf ixf f
+     )
+  => Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Array rf ixf f
+  -> Vector DS (a, b, c, d, e, f)
+szip6 = szipWith6 (,,,,,)
+{-# INLINE szip6 #-}
+
+
+
+
+
+
+-- |
+--
+-- @since 0.5.0
+szipWith ::
+     (S.Stream ra ixa a, S.Stream rb ixb b)
+  => (a -> b -> c)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Vector DS c
+szipWith f v1 v2 = fromSteps $ S.zipWith f (S.toStream v1) (S.toStream v2)
+{-# INLINE szipWith #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith3 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c)
+  => (a -> b -> c -> d)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Vector DS d
+szipWith3 f v1 v2 v3 = fromSteps $ S.zipWith3 f (S.toStream v1) (S.toStream v2) (S.toStream v3)
+{-# INLINE szipWith3 #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith4 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d)
+  => (a -> b -> c -> d -> e)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Vector DS e
+szipWith4 f v1 v2 v3 v4 =
+  fromSteps $ S.zipWith4 f (S.toStream v1) (S.toStream v2) (S.toStream v3) (S.toStream v4)
+{-# INLINE szipWith4 #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith5 ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d, S.Stream re ixe e)
+  => (a -> b -> c -> d -> e -> f)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Vector DS f
+szipWith5 f v1 v2 v3 v4 v5 =
+  fromSteps $
+  S.zipWith5 f (S.toStream v1) (S.toStream v2) (S.toStream v3) (S.toStream v4) (S.toStream v5)
+{-# INLINE szipWith5 #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith6 ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , S.Stream rf ixf f
+     )
+  => (a -> b -> c -> d -> e -> f -> g)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Array rf ixf f
+  -> Vector DS g
+szipWith6 f v1 v2 v3 v4 v5 v6 =
+  fromSteps $
+  S.zipWith6
+    f
+    (S.toStream v1)
+    (S.toStream v2)
+    (S.toStream v3)
+    (S.toStream v4)
+    (S.toStream v5)
+    (S.toStream v6)
+{-# INLINE szipWith6 #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith ::
+     (S.Stream ra ix a, S.Stream rb ix b)
+  => (ix -> a -> b -> c)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Vector DS c
+sizipWith f v1 v2 = fromSteps $ S.zipWith (uncurry f) (S.toStreamIx v1) (S.toStream v2)
+{-# INLINE sizipWith #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith3 ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c)
+  => (ix -> a -> b -> c -> d)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Vector DS d
+sizipWith3 f v1 v2 v3 =
+  fromSteps $ S.zipWith3 (uncurry f) (S.toStreamIx v1) (S.toStream v2) (S.toStream v3)
+{-# INLINE sizipWith3 #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith4 ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, S.Stream rd ix d)
+  => (ix -> a -> b -> c -> d -> e)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Vector DS e
+sizipWith4 f v1 v2 v3 v4 =
+  fromSteps $
+  S.zipWith4 (uncurry f) (S.toStreamIx v1) (S.toStream v2) (S.toStream v3) (S.toStream v4)
+{-# INLINE sizipWith4 #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith5 ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, S.Stream rd ix d, S.Stream re ix e)
+  => (ix -> a -> b -> c -> d -> e -> f)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> Vector DS f
+sizipWith5 f v1 v2 v3 v4 v5 =
+  fromSteps $
+  S.zipWith5
+    (uncurry f)
+    (S.toStreamIx v1)
+    (S.toStream v2)
+    (S.toStream v3)
+    (S.toStream v4)
+    (S.toStream v5)
+{-# INLINE sizipWith5 #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith6 ::
+     ( S.Stream ra ix a
+     , S.Stream rb ix b
+     , S.Stream rc ix c
+     , S.Stream rd ix d
+     , S.Stream re ix e
+     , S.Stream rf ix f
+     )
+  => (ix -> a -> b -> c -> d -> e -> f -> g)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> Array rf ix f
+  -> Vector DS g
+sizipWith6 f v1 v2 v3 v4 v5 v6 =
+  fromSteps $
+  S.zipWith6
+    (uncurry f)
+    (S.toStreamIx v1)
+    (S.toStream v2)
+    (S.toStream v3)
+    (S.toStream v4)
+    (S.toStream v5)
+    (S.toStream v6)
+{-# INLINE sizipWith6 #-}
+
+
+-- |
+--
+-- @since 0.5.0
+szipWithM ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, Monad m)
+  => (a -> b -> m c)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> m (Vector DS c)
+szipWithM f v1 v2 = fromStepsM $ S.zipWithM f (toStreamM v1) (toStreamM v2)
+{-# INLINE szipWithM #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith3M ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, Monad m)
+  => (a -> b -> c -> m d)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> m (Vector DS d)
+szipWith3M f v1 v2 v3 = fromStepsM $ S.zipWith3M f (toStreamM v1) (toStreamM v2) (toStreamM v3)
+{-# INLINE szipWith3M #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith4M ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d, Monad m)
+  => (a -> b -> c -> d -> m e)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> m (Vector DS e)
+szipWith4M f v1 v2 v3 v4 =
+  fromStepsM $ S.zipWith4M f (toStreamM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4)
+{-# INLINE szipWith4M #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith5M ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , Monad m
+     )
+  => (a -> b -> c -> d -> e -> m f)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> m (Vector DS f)
+szipWith5M f v1 v2 v3 v4 v5 =
+  fromStepsM $
+  S.zipWith5M f (toStreamM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4) (toStreamM v5)
+{-# INLINE szipWith5M #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith6M ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , S.Stream rf ixf f
+     , Monad m
+     )
+  => (a -> b -> c -> d -> e -> f -> m g)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Array rf ixf f
+  -> m (Vector DS g)
+szipWith6M f v1 v2 v3 v4 v5 v6 =
+  fromStepsM $
+  S.zipWith6M
+    f
+    (toStreamM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+    (toStreamM v6)
+{-# INLINE szipWith6M #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sizipWithM ::
+     (S.Stream ra ix a, S.Stream rb ix b, Monad m)
+  => (ix -> a -> b -> m c)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> m (Vector DS c)
+sizipWithM f v1 v2 = fromStepsM $ S.zipWithM (uncurry f) (toStreamIxM v1) (toStreamM v2)
+{-# INLINE sizipWithM #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sizipWith3M ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, Monad m)
+  => (ix -> a -> b -> c -> m d)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> m (Vector DS d)
+sizipWith3M f v1 v2 v3 =
+  fromStepsM $ S.zipWith3M (uncurry f) (toStreamIxM v1) (toStreamM v2) (toStreamM v3)
+{-# INLINE sizipWith3M #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith4M ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, S.Stream rd ix d, Monad m)
+  => (ix -> a -> b -> c -> d -> m e)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> m (Vector DS e)
+sizipWith4M f v1 v2 v3 v4 =
+  fromStepsM $
+  S.zipWith4M (uncurry f) (toStreamIxM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4)
+{-# INLINE sizipWith4M #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith5M ::
+     ( S.Stream ra ix a
+     , S.Stream rb ix b
+     , S.Stream rc ix c
+     , S.Stream rd ix d
+     , S.Stream re ix e
+     , Monad m
+     )
+  => (ix -> a -> b -> c -> d -> e -> m f)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> m (Vector DS f)
+sizipWith5M f v1 v2 v3 v4 v5 =
+  fromStepsM $
+  S.zipWith5M
+    (uncurry f)
+    (toStreamIxM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+{-# INLINE sizipWith5M #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith6M ::
+     ( S.Stream ra ix a
+     , S.Stream rb ix b
+     , S.Stream rc ix c
+     , S.Stream rd ix d
+     , S.Stream re ix e
+     , S.Stream rf ix f
+     , Monad m
+     )
+  => (ix -> a -> b -> c -> d -> e -> f -> m g)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> Array rf ix f
+  -> m (Vector DS g)
+sizipWith6M f v1 v2 v3 v4 v5 v6 =
+  fromStepsM $
+  S.zipWith6M
+    (uncurry f)
+    (toStreamIxM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+    (toStreamM v6)
+{-# INLINE sizipWith6M #-}
+
+
+-- |
+--
+-- @since 0.5.0
+szipWithM_ ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, Monad m)
+  => (a -> b -> m c)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> m ()
+szipWithM_ f v1 v2 = S.zipWithM_ f (toStreamM v1) (toStreamM v2)
+{-# INLINE szipWithM_ #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith3M_ ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, Monad m)
+  => (a -> b -> c -> m d)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> m ()
+szipWith3M_ f v1 v2 v3 = S.zipWith3M_ f (toStreamM v1) (toStreamM v2) (toStreamM v3)
+{-# INLINE szipWith3M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith4M_ ::
+     (S.Stream ra ixa a, S.Stream rb ixb b, S.Stream rc ixc c, S.Stream rd ixd d, Monad m)
+  => (a -> b -> c -> d -> m e)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> m ()
+szipWith4M_ f v1 v2 v3 v4 =
+  S.zipWith4M_ f (toStreamM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4)
+{-# INLINE szipWith4M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith5M_ ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , Monad m
+     )
+  => (a -> b -> c -> d -> e -> m f)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> m ()
+szipWith5M_ f v1 v2 v3 v4 v5 =
+  S.zipWith5M_ f (toStreamM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4) (toStreamM v5)
+{-# INLINE szipWith5M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+szipWith6M_ ::
+     ( S.Stream ra ixa a
+     , S.Stream rb ixb b
+     , S.Stream rc ixc c
+     , S.Stream rd ixd d
+     , S.Stream re ixe e
+     , S.Stream rf ixf f
+     , Monad m
+     )
+  => (a -> b -> c -> d -> e -> f -> m g)
+  -> Array ra ixa a
+  -> Array rb ixb b
+  -> Array rc ixc c
+  -> Array rd ixd d
+  -> Array re ixe e
+  -> Array rf ixf f
+  -> m ()
+szipWith6M_ f v1 v2 v3 v4 v5 v6 =
+  S.zipWith6M_
+    f
+    (toStreamM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+    (toStreamM v6)
+{-# INLINE szipWith6M_ #-}
+
+
+
+
+-- |
+--
+-- @since 0.5.0
+sizipWithM_ ::
+     (S.Stream ra ix a, S.Stream rb ix b, Monad m)
+  => (ix -> a -> b -> m c)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> m ()
+sizipWithM_ f v1 v2 = S.zipWithM_ (uncurry f) (toStreamIxM v1) (toStreamM v2)
+{-# INLINE sizipWithM_ #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sizipWith3M_ ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, Monad m)
+  => (ix -> a -> b -> c -> m d)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> m ()
+sizipWith3M_ f v1 v2 v3 = S.zipWith3M_ (uncurry f) (toStreamIxM v1) (toStreamM v2) (toStreamM v3)
+{-# INLINE sizipWith3M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith4M_ ::
+     (S.Stream ra ix a, S.Stream rb ix b, S.Stream rc ix c, S.Stream rd ix d, Monad m)
+  => (ix -> a -> b -> c -> d -> m e)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> m ()
+sizipWith4M_ f v1 v2 v3 v4 =
+  S.zipWith4M_ (uncurry f) (toStreamIxM v1) (toStreamM v2) (toStreamM v3) (toStreamM v4)
+{-# INLINE sizipWith4M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith5M_ ::
+     ( S.Stream ra ix a
+     , S.Stream rb ix b
+     , S.Stream rc ix c
+     , S.Stream rd ix d
+     , S.Stream re ix e
+     , Monad m
+     )
+  => (ix -> a -> b -> c -> d -> e -> m f)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> m ()
+sizipWith5M_ f v1 v2 v3 v4 v5 =
+  S.zipWith5M_
+    (uncurry f)
+    (toStreamIxM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+{-# INLINE sizipWith5M_ #-}
+
+-- |
+--
+-- @since 0.5.0
+sizipWith6M_ ::
+     ( S.Stream ra ix a
+     , S.Stream rb ix b
+     , S.Stream rc ix c
+     , S.Stream rd ix d
+     , S.Stream re ix e
+     , S.Stream rf ix f
+     , Monad m
+     )
+  => (ix -> a -> b -> c -> d -> e -> f -> m g)
+  -> Array ra ix a
+  -> Array rb ix b
+  -> Array rc ix c
+  -> Array rd ix d
+  -> Array re ix e
+  -> Array rf ix f
+  -> m ()
+sizipWith6M_ f v1 v2 v3 v4 v5 v6 =
+  S.zipWith6M_
+    (uncurry f)
+    (toStreamIxM v1)
+    (toStreamM v2)
+    (toStreamM v3)
+    (toStreamM v4)
+    (toStreamM v5)
+    (toStreamM v6)
+{-# INLINE sizipWith6M_ #-}
+
+
+
+
+
+-- |
+--
+-- @since 0.5.0
+sfoldl :: Stream r ix e => (a -> e -> a) -> a -> Array r ix e -> a
+sfoldl f acc = S.unId . S.foldl f acc . toStream
+{-# INLINE sfoldl #-}
+
+-- |
+--
+-- @since 0.5.0
+sfoldlM :: (Stream r ix e, Monad m) => (a -> e -> m a) -> a -> Array r ix e -> m a
+sfoldlM f acc = S.foldlM f acc . S.transStepsId . toStream
+{-# INLINE sfoldlM #-}
+
+-- |
+--
+-- @since 0.5.0
+sfoldlM_ :: (Stream r ix e, Monad m) => (a -> e -> m a) -> a -> Array r ix e -> m ()
+sfoldlM_ f acc = void . sfoldlM f acc
+{-# INLINE sfoldlM_ #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sfoldl1' :: Stream r ix e => (e -> e -> e) -> Array r ix e -> e
+sfoldl1' f = either throw id . sfoldl1M (\e -> pure . f e)
+{-# INLINE sfoldl1' #-}
+
+-- |
+--
+-- @since 0.5.0
+sfoldl1M :: (Stream r ix e, MonadThrow m) => (e -> e -> m e) -> Array r ix e -> m e
+sfoldl1M f arr = do
+  let str = S.transStepsId $ toStream arr
+  nullStream <- S.null str
+  when nullStream $ throwM $ SizeEmptyException (size arr)
+  S.foldl1M f str
+{-# INLINE sfoldl1M #-}
+
+-- |
+--
+-- @since 0.5.0
+sfoldl1M_ :: (Stream r ix e, MonadThrow m) => (e -> e -> m e) -> Array r ix e -> m ()
+sfoldl1M_ f = void . sfoldl1M f
+{-# INLINE sfoldl1M_ #-}
+
+
+
+-- |
+--
+-- @since 0.5.0
+sifoldl :: Stream r ix e => (a -> ix -> e -> a) -> a -> Array r ix e -> a
+sifoldl f acc = S.unId . S.foldl (\a (ix, e) -> f a ix e) acc . toStreamIx
+{-# INLINE sifoldl #-}
+
+-- |
+--
+-- @since 0.5.0
+sifoldlM :: (Stream r ix e, Monad m) => (a -> ix -> e -> m a) -> a -> Array r ix e -> m a
+sifoldlM f acc = S.foldlM (\a (ix, e) -> f a ix e) acc . S.transStepsId . toStreamIx
+{-# INLINE sifoldlM #-}
+
+-- |
+--
+-- @since 0.5.0
+sifoldlM_ :: (Stream r ix e, Monad m) => (a -> ix -> e -> m a) -> a -> Array r ix e -> m ()
+sifoldlM_ f acc = void . sifoldlM f acc
+{-# INLINE sifoldlM_ #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sor :: Stream r ix Bool => Array r ix Bool -> Bool
+sor = S.unId . S.or . toStream
+{-# INLINE sor #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sand :: Stream r ix Bool => Array r ix Bool -> Bool
+sand = S.unId . S.and . toStream
+{-# INLINE sand #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sany :: Stream r ix e => (e -> Bool) -> Array r ix e -> Bool
+sany f = S.unId . S.or . S.map f . toStream
+{-# INLINE sany #-}
+
+
+-- |
+--
+-- @since 0.5.0
+sall :: Stream r ix e => (e -> Bool) -> Array r ix e -> Bool
+sall f = S.unId . S.and . S.map f . toStream
+{-# INLINE sall #-}
+
+
+
+-- |
+--
+-- @since 0.5.0
+ssum :: (Num e, Stream r ix e) => Array r ix e -> e
+ssum = sfoldl (+) 0
+{-# INLINE ssum #-}
+
+-- |
+--
+-- @since 0.5.0
+sproduct :: (Num e, Stream r ix e) => Array r ix e -> e
+sproduct = sfoldl (*) 1
+{-# INLINE sproduct #-}
+
+
+-- |
+--
+-- @since 0.5.0
+smaximum' :: (Ord e, Stream r ix e) => Array r ix e -> e
+smaximum' = sfoldl1' max
+{-# INLINE smaximum' #-}
+
+-- |
+--
+-- @since 0.5.0
+smaximumM :: (Ord e, Stream r ix e, MonadThrow m) => Array r ix e -> m e
+smaximumM = sfoldl1M (\e acc -> pure (max e acc))
+{-# INLINE smaximumM #-}
+
+
+
+-- |
+--
+-- @since 0.5.0
+sminimum' :: (Ord e, Stream r ix e) => Array r ix e -> e
+sminimum' = sfoldl1' min
+{-# INLINE sminimum' #-}
+
+-- |
+--
+-- @since 0.5.0
+sminimumM :: (Ord e, Stream r ix e, MonadThrow m) => Array r ix e -> m e
+sminimumM = sfoldl1M (\e acc -> pure (min e acc))
+{-# INLINE sminimumM #-}
+
+
+
+-- | See `stake`.
+--
+-- @since 0.4.1
+takeS :: Stream r ix e => Sz1 -> Array r ix e -> Array DS Ix1 e
+takeS n = fromSteps . S.take (unSz n) . S.toStream
+{-# INLINE takeS #-}
+{-# DEPRECATED takeS "In favor of `stake`" #-}
+
+-- | See `sdrop`.
+--
+-- @since 0.4.1
+dropS :: Stream r ix e => Sz1 -> Array r ix e -> Array DS Ix1 e
+dropS n = fromSteps . S.drop (unSz n) . S.toStream
+{-# INLINE dropS #-}
+{-# DEPRECATED dropS "In favor of `sdrop`" #-}
+
+-- | See `sunfoldr`
+--
+-- @since 0.4.1
+unfoldr :: (s -> Maybe (e, s)) -> s -> Vector DS e
+unfoldr = sunfoldr
+{-# INLINE unfoldr #-}
+{-# DEPRECATED unfoldr "In favor of `sunfoldr`" #-}
+
+
+-- | See `sunfoldrN`
+--
+-- @since 0.4.1
+unfoldrN :: Sz1 -> (s -> Maybe (e, s)) -> s -> Vector DS e
+unfoldrN = unfoldrN
+{-# INLINE unfoldrN #-}
+{-# DEPRECATED unfoldrN "In favor of `sunfoldrN`" #-}
+
+
+-- | See `sfilterM`
+--
+-- @since 0.4.1
+filterM :: (S.Stream r ix e, Applicative f) => (e -> f Bool) -> Array r ix e -> f (Vector DS e)
+filterM f arr = DSArray <$> S.filterA f (S.toStream arr)
+{-# INLINE filterM #-}
+{-# DEPRECATED filterM "In favor of `sfilterM`" #-}
+
+-- | See `sfilter`
+--
+-- @since 0.4.1
+filterS :: S.Stream r ix e => (e -> Bool) -> Array r ix e -> Array DS Ix1 e
+filterS = sfilter
+{-# INLINE filterS #-}
+{-# DEPRECATED filterS "In favor of `sfilter`" #-}
+
+
+-- | See `smapMaybe`
+--
+-- @since 0.4.1
+mapMaybeS :: S.Stream r ix a => (a -> Maybe b) -> Array r ix a -> Vector DS b
+mapMaybeS = smapMaybe
+{-# INLINE mapMaybeS #-}
+{-# DEPRECATED mapMaybeS "In favor of `smapMaybe`" #-}
+
+-- | See `scatMaybes`
+--
+-- @since 0.4.4
+catMaybesS :: S.Stream r ix (Maybe a) => Array r ix (Maybe a) -> Vector DS a
+catMaybesS = scatMaybes
+{-# INLINE catMaybesS #-}
+{-# DEPRECATED catMaybesS "In favor of `scatMaybes`" #-}
+
+-- | See `smapMaybeM`
+--
+-- @since 0.4.1
+mapMaybeM ::
+     (S.Stream r ix a, Applicative f) => (a -> f (Maybe b)) -> Array r ix a -> f (Vector DS b)
+mapMaybeM = smapMaybeM
+{-# INLINE mapMaybeM #-}
+{-# DEPRECATED mapMaybeM "In favor of `smapMaybeM`" #-}
+
+-- | See `traverseS`
+--
+-- @since 0.4.5
+traverseS :: (S.Stream r ix a, Applicative f) => (a -> f b) -> Array r ix a -> f (Vector DS b)
+traverseS = straverse
+{-# INLINE traverseS #-}
+{-# DEPRECATED traverseS "In favor of `straverse`" #-}
+
+-- | See `simapMaybe`
+--
+-- @since 0.4.1
+imapMaybeS :: Source r ix a => (ix -> a -> Maybe b) -> Array r ix a -> Array DS Ix1 b
+imapMaybeS f arr =
+  mapMaybeS (uncurry f) $ A.makeArrayR D (getComp arr) (size arr) $ \ix -> (ix, unsafeIndex arr ix)
+{-# INLINE imapMaybeS #-}
+{-# DEPRECATED imapMaybeS "In favor of `simapMaybe`" #-}
+
+-- | See `simapMaybeM`
+--
+-- @since 0.4.1
+imapMaybeM ::
+     (Source r ix a, Applicative f) => (ix -> a -> f (Maybe b)) -> Array r ix a -> f (Array DS Ix1 b)
+imapMaybeM f arr =
+  mapMaybeM (uncurry f) $ A.makeArrayR D (getComp arr) (size arr) $ \ix -> (ix, unsafeIndex arr ix)
+{-# INLINE imapMaybeM #-}
+{-# DEPRECATED imapMaybeM "In favor of `simapMaybeM`" #-}
+
+-- | Similar to `filterS`, but map with an index aware function.
+--
+-- @since 0.4.1
+ifilterS :: Source r ix a => (ix -> a -> Bool) -> Array r ix a -> Array DS Ix1 a
+ifilterS f =
+  imapMaybeS $ \ix e ->
+    if f ix e
+      then Just e
+      else Nothing
+{-# INLINE ifilterS #-}
+{-# DEPRECATED ifilterS "In favor of `sifilter`" #-}
+
+
+-- | Similar to `filterM`, but map with an index aware function.
+--
+-- @since 0.4.1
+ifilterM ::
+     (Source r ix a, Applicative f) => (ix -> a -> f Bool) -> Array r ix a -> f (Array DS Ix1 a)
+ifilterM f =
+  imapMaybeM $ \ix e ->
+    (\p ->
+       if p
+         then Just e
+         else Nothing) <$>
+    f ix e
+{-# INLINE ifilterM #-}
+{-# DEPRECATED ifilterM "In favor of `sifilterM`" #-}
diff --git a/src/Data/Massiv/Vector/Stream.hs b/src/Data/Massiv/Vector/Stream.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Massiv/Vector/Stream.hs
@@ -0,0 +1,816 @@
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# OPTIONS_HADDOCK hide, not-home #-}
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+-- |
+-- Module      : Data.Massiv.Vector.Stream
+-- Copyright   : (c) Alexey Kuleshevich 2019-2020
+-- License     : BSD3
+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
+-- Stability   : experimental
+-- Portability : non-portable
+--
+module Data.Massiv.Vector.Stream
+  ( -- | This module has a similar purpose as the 'Data.Vector.Fusion.Bundle.Monadic', but
+    -- quite a bit simpler.
+    --
+    -- __Important__ - This module is still experimental, as such it is considered
+    -- internal and exported for the curious users only.
+    Steps(..)
+  , Stream(..)
+  -- * Conversion
+  , steps
+  , isteps
+  , consume
+  , fromStream
+  , fromStreamM
+  , fromStreamExactM
+  , unstreamExact
+  , unstreamMax
+  , unstreamMaxM
+  , unstreamUnknown
+  , unstreamUnknownM
+  , unstreamIntoM
+  -- * Bundle
+  , toBundle
+  , fromBundle
+  , fromBundleM
+  -- * Operations on Steps
+  , length
+  , null
+  , empty
+  , singleton
+  , generate
+  , headMaybe
+  , last
+  , cons
+  , uncons
+  , snoc
+  , drop
+  , take
+  , slice
+  , iterateN
+  , iterateNM
+  , replicate
+  , replicateM
+  , generateM
+  , traverse
+  , map
+  , mapM
+  , mapM_
+  , indexed
+  , concatMap
+  , append
+  , zipWith
+  , zipWith3
+  , zipWith4
+  , zipWith5
+  , zipWith6
+  , zipWithM
+  , zipWith3M
+  , zipWith4M
+  , zipWith5M
+  , zipWith6M
+  , zipWithM_
+  , zipWith3M_
+  , zipWith4M_
+  , zipWith5M_
+  , zipWith6M_
+  -- ** Folding
+  , foldl
+  , foldl1
+  , foldlM
+  , foldl1M
+  , foldlLazy
+  , foldl1Lazy
+  , foldlLazyM
+  , foldl1LazyM
+  , foldrLazy
+  , foldr1Lazy
+  , foldrLazyM
+  , foldr1LazyM
+
+  , or
+  , and
+  -- ** Unfolding
+  , unfoldr
+  , unfoldrN
+  , unfoldrM
+  , unfoldrNM
+  , unfoldrExactN
+  , unfoldrExactNM
+  -- ** Enumeration
+  , enumFromStepN
+  -- * Lists
+  , toList
+  , fromList
+  , fromListN
+  -- ** Filter
+  , mapMaybe
+  , mapMaybeA
+  , mapMaybeM
+  , filter
+  , filterA
+  , filterM
+  -- * Transformations
+  , transSteps
+  , transStepsId
+  -- * Useful re-exports
+  , module Data.Vector.Fusion.Bundle.Size
+  , module Data.Vector.Fusion.Util
+  , Id(..)
+  ) where
+
+import qualified Control.Monad as M
+import Control.Monad.ST
+import qualified Data.Foldable as F
+import Data.Massiv.Core.Common hiding (empty, singleton)
+import Data.Maybe (catMaybes)
+import qualified Data.Traversable as Traversable (traverse)
+import qualified Data.Vector.Fusion.Bundle.Monadic as B
+import Data.Vector.Fusion.Bundle.Size
+import qualified Data.Vector.Fusion.Stream.Monadic as S
+import Data.Vector.Fusion.Util
+import Prelude hiding (and, concatMap, drop, filter, foldl, foldl1, foldr,
+                foldr1, length, map, mapM, mapM_, null, or, replicate, take,
+                traverse, zipWith, zipWith3)
+
+
+instance Monad m => Functor (Steps m) where
+  fmap f str = str {stepsStream = S.map f (stepsStream str)}
+  {-# INLINE fmap #-}
+  (<$) e str =
+    case stepsSize str of
+      Exact n -> str {stepsStream = S.replicate n e}
+      _       -> fmap (const e) str
+  {-# INLINE (<$) #-}
+
+instance Monad m => Semigroup (Steps m e) where
+  (<>) = append
+  {-# INLINE (<>) #-}
+
+instance Monad m => Monoid (Steps m e) where
+  mempty = empty
+  {-# INLINE mempty #-}
+  mappend = append
+  {-# INLINE mappend #-}
+
+
+instance Foldable (Steps Id) where
+  foldr f acc = unId . foldrLazy f acc
+  {-# INLINE foldr #-}
+  foldl f acc = unId . foldlLazy f acc
+  {-# INLINE foldl #-}
+  foldl' f acc = unId . foldl f acc
+  {-# INLINE foldl' #-}
+  foldr1 f = unId . foldr1Lazy f
+  {-# INLINE foldr1 #-}
+  foldl1 f = unId . foldl1Lazy f
+  {-# INLINE foldl1 #-}
+  toList = toList
+  {-# INLINE toList #-}
+  length = unId . length
+  {-# INLINE length #-}
+  null = unId . null
+  {-# INLINE null #-}
+  sum = unId . foldl (+) 0
+  {-# INLINE sum #-}
+  product = unId . foldl (*) 1
+  {-# INLINE product #-}
+  maximum = unId . foldl1 max
+  {-# INLINE maximum #-}
+  minimum = unId . foldl1 min
+  {-# INLINE minimum #-}
+
+
+-- TODO: benchmark: `fmap snd . isteps`
+steps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m e
+steps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
+  where
+    k = totalElem $ size arr
+    step i
+      | i < k =
+        let e = unsafeLinearIndex arr i
+         in e `seq` return $ S.Yield e (i + 1)
+      | otherwise = return S.Done
+    {-# INLINE step #-}
+{-# INLINE steps #-}
+
+
+isteps :: forall r ix e m . (Monad m, Source r ix e) => Array r ix e -> Steps m (ix, e)
+isteps arr = k `seq` arr `seq` Steps (S.Stream step 0) (Exact k)
+  where
+    sz = size arr
+    k = totalElem sz
+    step i
+      | i < k =
+        let e = unsafeLinearIndex arr i
+         in e `seq` return $ S.Yield (fromLinearIndex sz i, e) (i + 1)
+      | otherwise = return S.Done
+    {-# INLINE step #-}
+{-# INLINE isteps #-}
+
+toBundle :: (Monad m, Source r ix e) => Array r ix e -> B.Bundle m v e
+toBundle arr =
+  let Steps str k = steps arr
+   in B.fromStream str k
+{-# INLINE toBundle #-}
+
+fromBundle :: Mutable r Ix1 e => B.Bundle Id v e -> Array r Ix1 e
+fromBundle bundle = fromStream (B.sSize bundle) (B.sElems bundle)
+{-# INLINE fromBundle #-}
+
+
+fromBundleM :: (Monad m, Mutable r Ix1 e) => B.Bundle m v e -> m (Array r Ix1 e)
+fromBundleM bundle = fromStreamM (B.sSize bundle) (B.sElems bundle)
+{-# INLINE fromBundleM #-}
+
+
+fromStream :: forall r e . Mutable r Ix1 e => Size -> S.Stream Id e -> Array r Ix1 e
+fromStream sz str =
+  case upperBound sz of
+    Nothing -> unstreamUnknown str
+    Just k  -> unstreamMax k str
+{-# INLINE fromStream #-}
+
+fromStreamM :: forall r e m. (Monad m, Mutable r Ix1 e) => Size -> S.Stream m e -> m (Array r Ix1 e)
+fromStreamM sz str = do
+  xs <- S.toList str
+  case upperBound sz of
+    Nothing -> pure $! unstreamUnknown (S.fromList xs)
+    Just k  -> pure $! unstreamMax k (S.fromList xs)
+{-# INLINE fromStreamM #-}
+
+fromStreamExactM ::
+     forall r ix e m. (Monad m, Mutable r ix e)
+  => Sz ix
+  -> S.Stream m e
+  -> m (Array r ix e)
+fromStreamExactM sz str = do
+  xs <- S.toList str
+  pure $! unstreamExact sz (S.fromList xs)
+{-# INLINE fromStreamExactM #-}
+
+
+unstreamIntoM ::
+     (Mutable r Ix1 a, PrimMonad m)
+  => MArray (PrimState m) r Ix1 a
+  -> Size
+  -> S.Stream Id a
+  -> m (MArray (PrimState m) r Ix1 a)
+unstreamIntoM marr sz str =
+  case sz of
+    Exact _ -> marr <$ unstreamMaxM marr str
+    Max _   -> unsafeLinearShrink marr . SafeSz =<< unstreamMaxM marr str
+    Unknown -> unstreamUnknownM marr str
+{-# INLINE unstreamIntoM #-}
+
+
+
+unstreamMax ::
+     forall r e. (Mutable r Ix1 e)
+  => Int
+  -> S.Stream Id e
+  -> Array r Ix1 e
+unstreamMax kMax str =
+  runST $ do
+    marr <- unsafeNew (SafeSz kMax)
+    k <- unstreamMaxM marr str
+    unsafeLinearShrink marr (SafeSz k) >>= unsafeFreeze Seq
+{-# INLINE unstreamMax #-}
+
+
+unstreamMaxM ::
+     (Mutable r ix a, PrimMonad m) => MArray (PrimState m) r ix a -> S.Stream Id a -> m Int
+unstreamMaxM marr (S.Stream step s) = stepLoad s 0
+  where
+    stepLoad t i =
+      case unId (step t) of
+        S.Yield e' t' -> do
+          unsafeLinearWrite marr i e'
+          stepLoad t' (i + 1)
+        S.Skip t' -> stepLoad t' i
+        S.Done -> return i
+    {-# INLINE stepLoad #-}
+{-# INLINE unstreamMaxM #-}
+
+
+unstreamUnknown :: Mutable r Ix1 a => S.Stream Id a -> Array r Ix1 a
+unstreamUnknown str =
+  runST $ do
+    marr <- unsafeNew zeroSz
+    unstreamUnknownM marr str >>= unsafeFreeze Seq
+{-# INLINE unstreamUnknown #-}
+
+
+unstreamUnknownM ::
+     (Mutable r Ix1 a, PrimMonad m)
+  => MArray (PrimState m) r Ix1 a
+  -> S.Stream Id a
+  -> m (MArray (PrimState m) r Ix1 a)
+unstreamUnknownM marrInit (S.Stream step s) = stepLoad s 0 (unSz (msize marrInit)) marrInit
+  where
+    stepLoad t i kMax marr
+      | i < kMax =
+        case unId (step t) of
+          S.Yield e' t' -> do
+            unsafeLinearWrite marr i e'
+            stepLoad t' (i + 1) kMax marr
+          S.Skip t' -> stepLoad t' i kMax marr
+          S.Done -> unsafeLinearShrink marr (SafeSz i)
+      | otherwise = do
+        let kMax' = max 1 (kMax * 2)
+        marr' <- unsafeLinearGrow marr (SafeSz kMax')
+        stepLoad t i kMax' marr'
+    {-# INLINE stepLoad #-}
+{-# INLINE unstreamUnknownM #-}
+
+
+unstreamExact ::
+     forall r ix e. (Mutable r ix e)
+  => Sz ix
+  -> S.Stream Id e
+  -> Array r ix e
+unstreamExact sz str =
+  runST $ do
+    marr <- unsafeNew sz
+    _ <- unstreamMaxM marr str
+    unsafeFreeze Seq marr
+{-# INLINE unstreamExact #-}
+
+length :: Monad m => Steps m a -> m Int
+length (Steps str sz) =
+  case sz of
+    Exact k -> pure k
+    _       -> S.length str
+{-# INLINE length #-}
+
+
+null :: Monad m => Steps m a -> m Bool
+null (Steps str sz) =
+  case sz of
+    Exact k -> pure (k == 0)
+    _       -> S.null str
+{-# INLINE null #-}
+
+empty :: Monad m => Steps m e
+empty = Steps S.empty (Exact 0)
+{-# INLINE empty #-}
+
+singleton :: Monad m => e -> Steps m e
+singleton e = Steps (S.singleton e) (Exact 1)
+{-# INLINE singleton #-}
+
+generate :: Monad m => Int -> (Int -> e) -> Steps m e
+generate k f = Steps (S.generate k f) (Exact k)
+{-# INLINE generate #-}
+
+-- | First element of the 'Stream' or error if empty
+headMaybe :: Monad m => Steps m a -> m (Maybe a)
+headMaybe (Steps (S.Stream step t) _) = headMaybeLoop S.SPEC t
+  where
+    headMaybeLoop !_ s = do
+      r <- step s
+      case r of
+        S.Yield x _ -> pure $ Just x
+        S.Skip s'   -> headMaybeLoop S.SPEC s'
+        S.Done      -> pure Nothing
+    {-# INLINE [0] headMaybeLoop #-}
+{-# INLINE headMaybe #-}
+
+
+cons :: Monad m => e -> Steps m e -> Steps m e
+cons e (Steps str k) = Steps (S.cons e str) (k + 1)
+{-# INLINE cons #-}
+
+uncons :: Monad m => Steps m e -> m (Maybe (e, Steps m e))
+uncons sts@(Steps str _) = do
+  mx <- str S.!? 0
+  pure $ fmap (, drop 1 sts) mx
+{-# INLINE uncons #-}
+
+snoc :: Monad m => Steps m e -> e -> Steps m e
+snoc (Steps str k) e = Steps (S.snoc str e) (k + 1)
+{-# INLINE snoc #-}
+
+traverse :: (Monad m, Applicative f) => (e -> f a) -> Steps Id e -> f (Steps m a)
+traverse f (Steps str k) = (`Steps` k) <$> liftListA (Traversable.traverse f) str
+{-# INLINE traverse #-}
+
+append :: Monad m => Steps m e -> Steps m e -> Steps m e
+append (Steps str1 k1) (Steps str2 k2) = Steps (str1 S.++ str2) (k1 + k2)
+{-# INLINE append #-}
+
+map :: Monad m => (e -> a) -> Steps m e -> Steps m a
+map f (Steps str k) = Steps (S.map f str) k
+{-# INLINE map #-}
+
+indexed :: Monad m => Steps m e -> Steps m (Int, e)
+indexed (Steps str k) = Steps (S.indexed str) k
+{-# INLINE indexed #-}
+
+mapM :: Monad m => (e -> m a) -> Steps m e -> Steps m a
+mapM f (Steps str k) = Steps (S.mapM f str) k
+{-# INLINE mapM #-}
+
+mapM_ :: Monad m => (e -> m a) -> Steps m e -> m ()
+mapM_ f (Steps str _) = S.mapM_ f str
+{-# INLINE mapM_ #-}
+
+zipWith :: Monad m => (a -> b -> e) -> Steps m a -> Steps m b -> Steps m e
+zipWith f (Steps sa ka) (Steps sb kb) = Steps (S.zipWith f sa sb) (smaller ka kb)
+{-# INLINE zipWith #-}
+
+zipWith3 :: Monad m => (a -> b -> c -> d) -> Steps m a -> Steps m b -> Steps m c -> Steps m d
+zipWith3 f (Steps sa ka) (Steps sb kb) (Steps sc kc) =
+  Steps (S.zipWith3 f sa sb sc) (smaller ka (smaller kb kc))
+{-# INLINE zipWith3 #-}
+
+zipWith4 ::
+  Monad m => (a -> b -> c -> d -> e) -> Steps m a -> Steps m b -> Steps m c -> Steps m d -> Steps m e
+zipWith4 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) =
+  Steps (S.zipWith4 f sa sb sc sd) (smaller ka (smaller kb (smaller kc kd)))
+{-# INLINE zipWith4 #-}
+
+zipWith5 ::
+     Monad m
+  => (a -> b -> c -> d -> e -> f)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> Steps m f
+zipWith5 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) =
+  Steps (S.zipWith5 f sa sb sc sd se) (smaller ka (smaller kb (smaller kc (smaller kd ke))))
+{-# INLINE zipWith5 #-}
+
+zipWith6 ::
+     Monad m
+  => (a -> b -> c -> d -> e -> f -> g)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> Steps m f
+  -> Steps m g
+zipWith6 f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) (Steps sf kf) =
+  Steps
+    (S.zipWith6 f sa sb sc sd se sf)
+    (smaller ka (smaller kb (smaller kc (smaller kd (smaller ke kf)))))
+{-# INLINE zipWith6 #-}
+
+zipWithM :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> Steps m c
+zipWithM f (Steps sa ka) (Steps sb kb) = Steps (S.zipWithM f sa sb) (smaller ka kb)
+{-# INLINE zipWithM #-}
+
+
+zipWith3M :: Monad m => (a -> b -> c -> m d) -> Steps m a -> Steps m b -> Steps m c -> Steps m d
+zipWith3M f (Steps sa ka) (Steps sb kb) (Steps sc kc) =
+  Steps (S.zipWith3M f sa sb sc) (smaller ka (smaller kb kc))
+{-# INLINE zipWith3M #-}
+
+zipWith4M ::
+     Monad m
+  => (a -> b -> c -> d -> m e)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+zipWith4M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) =
+  Steps (S.zipWith4M f sa sb sc sd) (smaller ka (smaller kb (smaller kc kd)))
+{-# INLINE zipWith4M #-}
+
+zipWith5M ::
+     Monad m
+  => (a -> b -> c -> d -> e -> m f)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> Steps m f
+zipWith5M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) =
+  Steps (S.zipWith5M f sa sb sc sd se) (smaller ka (smaller kb (smaller kc (smaller kd ke))))
+{-# INLINE zipWith5M #-}
+
+zipWith6M ::
+     Monad m
+  => (a -> b -> c -> d -> e -> f -> m g)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> Steps m f
+  -> Steps m g
+zipWith6M f (Steps sa ka) (Steps sb kb) (Steps sc kc) (Steps sd kd) (Steps se ke) (Steps sf kf) =
+  Steps
+    (S.zipWith6M f sa sb sc sd se sf)
+    (smaller ka (smaller kb (smaller kc (smaller kd (smaller ke kf)))))
+{-# INLINE zipWith6M #-}
+
+
+zipWithM_ :: Monad m => (a -> b -> m c) -> Steps m a -> Steps m b -> m ()
+zipWithM_ f (Steps str1 _) (Steps str2 _) = S.zipWithM_ f str1 str2
+{-# INLINE zipWithM_ #-}
+
+zipWith3M_ :: Monad m => (a -> b -> c -> m d) -> Steps m a -> Steps m b -> Steps m c -> m ()
+zipWith3M_ f sa sb sc = consume $ zipWith3M f sa sb sc
+{-# INLINE zipWith3M_ #-}
+
+
+zipWith4M_ ::
+     Monad m
+  => (a -> b -> c -> d -> m e)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> m ()
+zipWith4M_ f sa sb sc sd = consume $ zipWith4M f sa sb sc sd
+{-# INLINE zipWith4M_ #-}
+
+zipWith5M_ ::
+     Monad m
+  => (a -> b -> c -> d -> e -> m f)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> m ()
+zipWith5M_ f sa sb sc sd se = consume $ zipWith5M f sa sb sc sd se
+{-# INLINE zipWith5M_ #-}
+
+zipWith6M_ ::
+     Monad m
+  => (a -> b -> c -> d -> e -> f -> m g)
+  -> Steps m a
+  -> Steps m b
+  -> Steps m c
+  -> Steps m d
+  -> Steps m e
+  -> Steps m f
+  -> m ()
+zipWith6M_ f sa sb sc sd se sf = consume $ zipWith6M f sa sb sc sd se sf
+{-# INLINE zipWith6M_ #-}
+
+
+
+consume :: Monad m => Steps m a -> m ()
+consume (Steps (S.Stream step t) _) = consumeLoop S.SPEC t
+  where
+    consumeLoop !_ s = do
+      r <- step s
+      case r of
+        S.Yield _ s' -> consumeLoop S.SPEC s'
+        S.Skip s' -> consumeLoop S.SPEC s'
+        S.Done -> pure ()
+{-# INLINE consume #-}
+
+transStepsId :: Monad m => Steps Id e -> Steps m e
+transStepsId (Steps sts k) = Steps (S.trans (pure . unId) sts) k
+{-# INLINE transStepsId #-}
+
+transSteps :: (Monad m, Monad n) => Steps m e -> m (Steps n e)
+transSteps (Steps strM sz@(Exact _)) = (`Steps` sz) <$> transListM strM
+transSteps (Steps strM _) = do
+  (n, strN) <- transListNM strM
+  pure (Steps strN (Exact n))
+{-# INLINE transSteps #-}
+
+
+foldl :: Monad m => (b -> a -> b) -> b -> Steps m a -> m b
+foldl f acc = S.foldl' f acc . stepsStream
+{-# INLINE foldl #-}
+
+foldl1 :: Monad m => (a -> a -> a) -> Steps m a -> m a
+foldl1 f = S.foldl1' f . stepsStream
+{-# INLINE foldl1 #-}
+
+
+foldlM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
+foldlM f acc = S.foldlM' f acc . stepsStream
+{-# INLINE foldlM #-}
+
+
+foldl1M :: Monad m => (a -> a -> m a) -> Steps m a -> m a
+foldl1M f (Steps sts _) = S.foldl1M' f sts
+{-# INLINE foldl1M #-}
+
+
+foldrLazy :: Monad m => (a -> b -> b) -> b -> Steps m a -> m b
+foldrLazy f acc = S.foldr f acc . stepsStream
+{-# INLINE foldrLazy #-}
+
+foldr1Lazy :: Monad m => (a -> a -> a) -> Steps m a -> m a
+foldr1Lazy f = S.foldr1 f . stepsStream
+{-# INLINE foldr1Lazy #-}
+
+foldlLazy :: Monad m => (b -> a -> b) -> b -> Steps m a -> m b
+foldlLazy f acc = S.foldl f acc . stepsStream
+{-# INLINE foldlLazy #-}
+
+foldl1Lazy :: Monad m => (a -> a -> a) -> Steps m a -> m a
+foldl1Lazy f = S.foldl1 f . stepsStream
+{-# INLINE foldl1Lazy #-}
+
+
+foldlLazyM :: Monad m => (a -> b -> m a) -> a -> Steps m b -> m a
+foldlLazyM f acc = S.foldlM f acc . stepsStream
+{-# INLINE foldlLazyM #-}
+
+
+foldl1LazyM :: Monad m => (a -> a -> m a) -> Steps m a -> m a
+foldl1LazyM f (Steps sts _) = S.foldl1M f sts
+{-# INLINE foldl1LazyM #-}
+
+
+foldrLazyM :: Monad m => (b -> a -> m a) -> a -> Steps m b -> m a
+foldrLazyM f acc (Steps sts _) = S.foldrM f acc sts
+{-# INLINE foldrLazyM #-}
+
+
+foldr1LazyM :: Monad m => (a -> a -> m a) -> Steps m a -> m a
+foldr1LazyM f = S.foldr1M f . stepsStream
+{-# INLINE foldr1LazyM #-}
+
+
+or :: Monad m => Steps m Bool -> m Bool
+or = S.or . stepsStream
+{-# INLINE or #-}
+
+and :: Monad m => Steps m Bool -> m Bool
+and = S.and . stepsStream
+{-# INLINE and #-}
+
+
+mapMaybe :: Monad m => (a -> Maybe e) -> Steps m a -> Steps m e
+mapMaybe f (Steps str k) = Steps (S.mapMaybe f str) (toMax k)
+{-# INLINE mapMaybe #-}
+
+concatMap :: Monad m => (a -> Steps m e) -> Steps m a -> Steps m e
+concatMap f (Steps str _) = Steps (S.concatMap (stepsStream . f) str) Unknown
+{-# INLINE concatMap #-}
+
+
+mapMaybeA :: (Monad m, Applicative f) => (a -> f (Maybe e)) -> Steps Id a -> f (Steps m e)
+mapMaybeA f (Steps str k) = (`Steps` toMax k) <$> liftListA (mapMaybeListA f) str
+{-# INLINE mapMaybeA #-}
+
+mapMaybeM :: Monad m => (a -> m (Maybe b)) -> Steps m a -> Steps m b
+mapMaybeM f (Steps str k) = Steps (mapMaybeStreamM f str) (toMax k)
+{-# INLINE mapMaybeM #-}
+
+mapMaybeListA :: Applicative f => (a -> f (Maybe b)) -> [a] -> f [b]
+mapMaybeListA f = fmap catMaybes . Traversable.traverse f
+{-# INLINE mapMaybeListA #-}
+
+mapMaybeStreamM :: Monad m => (a -> m (Maybe b)) -> S.Stream m a -> S.Stream m b
+mapMaybeStreamM f (S.Stream step t) = S.Stream step' t
+  where
+    step' s = do
+      r <- step s
+      case r of
+        S.Yield x s' -> do
+          b <- f x
+          return $
+            case b of
+              Nothing -> S.Skip s'
+              Just b' -> S.Yield b' s'
+        S.Skip s' -> return $ S.Skip s'
+        S.Done -> return S.Done
+    {-# INLINE [0] step' #-}
+{-# INLINE mapMaybeStreamM #-}
+
+filter :: Monad m => (a -> Bool) -> Steps m a -> Steps m a
+filter f (Steps str k) = Steps (S.filter f str) (toMax k)
+{-# INLINE filter #-}
+
+
+filterA :: (Monad m, Applicative f) => (e -> f Bool) -> Steps Id e -> f (Steps m e)
+filterA f (Steps str k) = (`Steps` toMax k) <$> liftListA (M.filterM f) str
+{-# INLINE filterA #-}
+
+filterM :: Monad m => (e -> m Bool) -> Steps m e -> Steps m e
+filterM f (Steps str k) = Steps (S.filterM f str) (toMax k)
+{-# INLINE filterM #-}
+
+take :: Monad m => Int -> Steps m a -> Steps m a
+take n (Steps str sz) =
+  Steps (S.take n str) $!
+  case sz of
+    Exact k -> Exact (min n k)
+    Max k -> Max (min n k)
+    Unknown -> Unknown
+{-# INLINE take #-}
+
+drop :: Monad m => Int -> Steps m a -> Steps m a
+drop n (Steps str k) = Steps (S.drop n str) (k `clampedSubtract` Exact n)
+{-# INLINE drop #-}
+
+slice :: Monad m => Int -> Int -> Steps m a -> Steps m a
+slice i k (Steps str _) = Steps (S.slice i k str) (Max k)
+{-# INLINE slice #-}
+
+iterateN :: Monad m => Int -> (a -> a) -> a -> Steps m a
+iterateN n f a = Steps (S.iterateN n f a) (Exact n)
+{-# INLINE iterateN #-}
+
+iterateNM :: Monad m => Int -> (a -> m a) -> a -> Steps m a
+iterateNM n f a = Steps (S.iterateNM n f a) (Exact n)
+{-# INLINE iterateNM #-}
+
+replicate :: Monad m => Int -> a -> Steps m a
+replicate n a = Steps (S.replicate n a) (Exact n)
+{-# INLINE replicate #-}
+
+replicateM :: Monad m => Int -> m a -> Steps m a
+replicateM n f = Steps (S.replicateM n f) (Exact n)
+{-# INLINE replicateM #-}
+
+
+generateM :: Monad m => Int -> (Int -> m a) -> Steps m a
+generateM n f = Steps (S.generateM n f) (Exact n)
+{-# INLINE generateM #-}
+
+
+unfoldr :: Monad m => (s -> Maybe (e, s)) -> s -> Steps m e
+unfoldr f e0 = Steps (S.unfoldr f e0) Unknown
+{-# INLINE unfoldr #-}
+
+unfoldrN :: Monad m => Int -> (s -> Maybe (e, s)) -> s -> Steps m e
+unfoldrN n f e0 = Steps (S.unfoldrN n f e0) (Max n)
+{-# INLINE unfoldrN #-}
+
+unfoldrM :: Monad m => (s -> m (Maybe (e, s))) -> s -> Steps m e
+unfoldrM f e0 = Steps (S.unfoldrM f e0) Unknown
+{-# INLINE unfoldrM #-}
+
+unfoldrNM :: Monad m => Int -> (s -> m (Maybe (e, s))) -> s -> Steps m e
+unfoldrNM n f e0 = Steps (S.unfoldrNM n f e0) (Max n)
+{-# INLINE unfoldrNM #-}
+
+unfoldrExactN :: Monad m => Int -> (s -> (a, s)) -> s -> Steps m a
+unfoldrExactN n f = unfoldrExactNM n (pure . f)
+{-# INLINE unfoldrExactN #-}
+
+unfoldrExactNM :: Monad m => Int -> (s -> m (a, s)) -> s -> Steps m a
+unfoldrExactNM n f t = Steps (S.Stream step (t, n)) (Exact n)
+  where
+    step (s, i)
+      | i <= 0 = pure S.Done
+      | otherwise = fmap (\(x, s') -> S.Yield x (s', i - 1)) (f s)
+    {-# INLINE [0] step #-}
+{-# INLINE unfoldrExactNM #-}
+
+
+enumFromStepN :: (Num a, Monad m) => a -> a -> Int -> Steps m a
+enumFromStepN x step k = Steps (S.enumFromStepN x step k) (Exact k)
+{-# INLINE enumFromStepN #-}
+
+
+
+
+toList :: Steps Id e -> [e]
+toList (Steps str _) = unId (S.toList str)
+{-# INLINE toList #-}
+
+fromList :: Monad m => [e] -> Steps m e
+fromList = (`Steps` Unknown) . S.fromList
+{-# INLINE fromList #-}
+
+fromListN :: Monad m => Int -> [e] -> Steps m e
+fromListN n  = (`Steps` Exact n) . S.fromListN n
+{-# INLINE fromListN #-}
+
+liftListA :: (Monad m, Functor f) => ([a] -> f [b]) -> S.Stream Id a -> f (S.Stream m b)
+liftListA f str = S.fromList <$> f (unId (S.toList str))
+{-# INLINE liftListA #-}
+
+
+transListM :: (Monad m, Monad n) => S.Stream m a -> m (S.Stream n a)
+transListM str = do
+  xs <- S.toList str
+  pure $ S.fromList xs
+{-# INLINE transListM #-}
+
+transListNM :: (Monad m, Monad n) => S.Stream m a -> m (Int, S.Stream n a)
+transListNM str = do
+  (n, xs) <- toListN str
+  pure (n, S.fromList xs)
+{-# INLINE transListNM #-}
+
+
+toListN :: Monad m => S.Stream m a -> m (Int, [a])
+toListN = S.foldr (\x (i, xs) -> (i + 1, x:xs)) (0, [])
+{-# INLINE toListN #-}
+
diff --git a/src/Data/Massiv/Vector/Unsafe.hs b/src/Data/Massiv/Vector/Unsafe.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Massiv/Vector/Unsafe.hs
@@ -0,0 +1,125 @@
+{-# LANGUAGE FlexibleContexts #-}
+-- |
+-- Module      : Data.Massiv.Vector.Unsafe
+-- Copyright   : (c) Alexey Kuleshevich 2020
+-- License     : BSD3
+-- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
+-- Stability   : experimental
+-- Portability : non-portable
+--
+module Data.Massiv.Vector.Unsafe
+  (
+  -- * Vector
+  -- ** Accessors
+  -- *** Indexing
+    unsafeHead
+  , unsafeLast
+  -- *** Monadic Indexing
+  , unsafeIndexM
+  , unsafeHeadM
+  , unsafeLastM
+  -- *** Slicing
+  , unsafeInit
+  , unsafeTail
+  , unsafeTake
+  , unsafeDrop
+  -- -- ** Modifying
+  -- -- *** Bulk updates
+  -- , unsafeUpdate
+  -- , unsafeUpdate_
+  -- -- *** Accumulation
+  -- , unsafeAccum
+  -- , unsafeAccumulate_
+  -- , unsafeBackpermute
+  -- -- ** Predicates
+  -- , unsafePartition
+  ) where
+
+import Data.Coerce
+import Data.Massiv.Core.Common
+
+-- ========= --
+-- Accessors --
+-- ========= --
+
+--------------
+-- Indexing --
+--------------
+
+
+-- |
+--
+-- @since 0.5.0
+unsafeHead :: Source r Ix1 e => Vector r e -> e
+unsafeHead = (`unsafeLinearIndex` 0)
+{-# INLINE unsafeHead #-}
+
+-- |
+--
+-- @since 0.5.0
+unsafeLast :: Source r Ix1 e => Vector r e -> e
+unsafeLast v = unsafeLinearIndex v (max 0 (unSz (size v) - 1))
+{-# INLINE unsafeLast #-}
+
+----------------------
+-- Monadic indexing --
+----------------------
+
+-- |
+--
+-- @since 0.5.0
+unsafeIndexM :: (Source r Ix1 e, Monad m) => Vector r e -> Ix1 -> m e
+unsafeIndexM v i = pure $! unsafeLinearIndex v i
+{-# INLINE unsafeIndexM #-}
+
+
+-- |
+--
+-- @since 0.5.0
+unsafeHeadM :: Monad m => Source r Ix1 e => Vector r e -> m e
+unsafeHeadM v = pure $! unsafeHead v
+{-# INLINE unsafeHeadM #-}
+
+-- |
+--
+-- @since 0.5.0
+unsafeLastM :: Monad m => Source r Ix1 e => Vector r e -> m e
+unsafeLastM v = pure $! unsafeLast v
+{-# INLINE unsafeLastM #-}
+
+
+-------------
+-- Slicing --
+-------------
+
+
+-- |
+--
+-- @since 0.5.0
+unsafeInit :: Source r Ix1 e => Vector r e -> Vector r e
+unsafeInit v = unsafeLinearSlice 0 (SafeSz (coerce (size v) - 1)) v
+{-# INLINE unsafeInit #-}
+
+
+-- |
+--
+-- @since 0.5.0
+unsafeTail :: Source r Ix1 e => Vector r e -> Vector r e
+unsafeTail = unsafeDrop 1
+{-# INLINE unsafeTail #-}
+
+
+-- |
+--
+-- @since 0.5.0
+unsafeTake :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+unsafeTake = unsafeLinearSlice 0
+{-# INLINE unsafeTake #-}
+
+-- |
+--
+-- @since 0.5.0
+unsafeDrop :: Source r Ix1 e => Sz1 -> Vector r e -> Vector r e
+unsafeDrop (Sz d) v = unsafeLinearSlice d (SafeSz (coerce (size v) - d)) v
+{-# INLINE unsafeDrop #-}
+
