diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,2 +1,10 @@
 # massiv
+
 Efficient Haskell Arrays featuring Parallel computation
+
+There is a decent introduction to the library with some examples in the main
+[README](https://github.com/lehins/massiv/blob/master/README.md) on github.
+
+See [massiv-io](https://hackage.haskell.org/package/massiv-io) for ability to read/write images.
+
+
diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.1.0.0
+version:             0.1.1.0
 synopsis:            Massiv (Массив) is an Array Library.
 description:         Multi-dimensional Arrays with fusion, stencils and parallel computation.
 homepage:            https://github.com/lehins/massiv
@@ -50,7 +50,7 @@
                      , Data.Massiv.Core.Index.Ix
                      , Data.Massiv.Core.Iterator
                      , Data.Massiv.Core.List
-  build-depends:       base            >= 4.7 && < 5
+  build-depends:       base            >= 4.8 && < 5
                      , data-default-class
                      , deepseq
                      , ghc-prim
@@ -66,6 +66,7 @@
   Main-Is:            Spec.hs
   Other-Modules:      Data.Massiv.Array.DelayedSpec
                     , Data.Massiv.Array.Manifest.VectorSpec
+                    , Data.Massiv.Array.MutableSpec
                     , Data.Massiv.Array.Ops.ConstructSpec
                     , Data.Massiv.Array.Ops.FoldSpec
                     , Data.Massiv.Array.Ops.SliceSpec
@@ -74,7 +75,7 @@
                     , Data.Massiv.CoreArbitrary
                     , Data.Massiv.Core.IndexSpec
                     , Data.Massiv.Core.SchedulerSpec
-  Build-Depends:      base            >= 4.5 && < 5
+  Build-Depends:      base            >= 4.8 && < 5
                     , deepseq
                     , data-default
                     , safe-exceptions
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
@@ -76,10 +76,14 @@
   , setComp
   , compute
   , computeAs
+  , computeProxy
   , computeSource
   , clone
   , convert
   , convertAs
+  , convertProxy
+  , fromRaggedArray
+  , fromRaggedArray'
   -- * Size
   , size
   , Core.elemsCount
@@ -106,6 +110,8 @@
   , module Data.Massiv.Array.Ops.Slice
   -- * Conversion
   , module Data.Massiv.Array.Manifest.List
+  -- * Mutable
+  , module Data.Massiv.Array.Mutable
   -- * Core
   , module Data.Massiv.Core
   -- * Representations
@@ -118,10 +124,10 @@
 
 import           Data.Massiv.Array.Delayed
 import           Data.Massiv.Array.Manifest
-import           Data.Massiv.Array.Numeric
 import           Data.Massiv.Array.Manifest.Internal
 import           Data.Massiv.Array.Manifest.List
-import           Data.Massiv.Array.Mutable           as A
+import           Data.Massiv.Array.Mutable
+import           Data.Massiv.Array.Numeric
 import           Data.Massiv.Array.Ops.Construct
 import           Data.Massiv.Array.Ops.Fold
 import           Data.Massiv.Array.Ops.Map
@@ -134,10 +140,10 @@
                                                               isEmpty)
 import           Data.Massiv.Core.Common
 import           Prelude                             as P hiding (all, and, any,
-                                                           foldl, foldr,
-                                                           maximum, minimum, or,
-                                                           product, splitAt,
-                                                           sum)
+                                                           foldl, foldr, mapM,
+                                                           mapM_, maximum,
+                                                           minimum, or, product,
+                                                           splitAt, sum)
 {- $folding
 
 All folding is done in a row-major order.
diff --git a/src/Data/Massiv/Array/Delayed/Internal.hs b/src/Data/Massiv/Array/Delayed/Internal.hs
--- a/src/Data/Massiv/Array/Delayed/Internal.hs
+++ b/src/Data/Massiv/Array/Delayed/Internal.hs
@@ -17,6 +17,7 @@
   , Array(..)
   , delay
   , eq
+  , ord
   , liftArray
   , liftArray2
   ) where
@@ -95,6 +96,9 @@
   (==) = eq (==)
   {-# INLINE (==) #-}
 
+instance (Ord e, Index ix) => Ord (Array D ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 instance Functor (Array D ix) where
   fmap f (DArray c sz g) = DArray c sz (f . g)
@@ -217,6 +221,20 @@
     (DArray (getComp arr1 <> getComp arr2) (size arr1) $ \ix ->
        f (unsafeIndex arr1 ix) (unsafeIndex arr2 ix))
 {-# INLINE eq #-}
+
+-- | /O(n1 + n2)/ - Compute array ordering by applying a comparing function to each element.
+-- The exact ordering is unspecified so this is only intended for use in maps and the like where
+-- you need an ordering but do not care about which one is used.
+ord :: (Source r1 ix e1, Source r2 ix e2) =>
+       (e1 -> e2 -> Ordering) -> Array r1 ix e1 -> Array r2 ix e2 -> Ordering
+ord f arr1 arr2 =
+  (compare (size arr1) (size arr2)) <>
+  A.fold
+    (<>)
+    mempty
+    (DArray (getComp arr1 <> getComp arr2) (size arr1) $ \ix ->
+       f (unsafeIndex arr1 ix) (unsafeIndex arr2 ix))
+{-# INLINE ord #-}
 
 
 liftArray :: Source r ix b => (b -> e) -> Array r ix b -> Array D ix e
diff --git a/src/Data/Massiv/Array/Manifest/BoxedNF.hs b/src/Data/Massiv/Array/Manifest/BoxedNF.hs
--- a/src/Data/Massiv/Array/Manifest/BoxedNF.hs
+++ b/src/Data/Massiv/Array/Manifest/BoxedNF.hs
@@ -25,7 +25,7 @@
 
 import           Control.DeepSeq                     (NFData (..), deepseq)
 import           Control.Monad.ST                    (runST)
-import           Data.Massiv.Array.Delayed.Internal  (eq)
+import           Data.Massiv.Array.Delayed.Internal  (eq, ord)
 import           Data.Massiv.Array.Manifest.Internal (M, toManifest)
 import           Data.Massiv.Array.Manifest.List     as A
 import           Data.Massiv.Array.Mutable
@@ -63,6 +63,10 @@
 instance (Index ix, NFData e, Eq e) => Eq (Array N ix e) where
   (==) = eq (==)
   {-# INLINE (==) #-}
+
+instance (Index ix, NFData e, Ord e) => Ord (Array N ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 
 instance (Index ix, NFData e) => Construct N ix e where
diff --git a/src/Data/Massiv/Array/Manifest/BoxedStrict.hs b/src/Data/Massiv/Array/Manifest/BoxedStrict.hs
--- a/src/Data/Massiv/Array/Manifest/BoxedStrict.hs
+++ b/src/Data/Massiv/Array/Manifest/BoxedStrict.hs
@@ -20,7 +20,7 @@
 
 import           Control.DeepSeq                     (NFData (..))
 import qualified Data.Foldable                       as F (Foldable (..))
-import           Data.Massiv.Array.Delayed.Internal  (eq)
+import           Data.Massiv.Array.Delayed.Internal  (eq, ord)
 import           Data.Massiv.Array.Manifest.BoxedNF  (deepseqArray,
                                                       deepseqArrayP)
 import           Data.Massiv.Array.Unsafe            (unsafeGenerateArray,
@@ -57,6 +57,10 @@
 instance (Index ix, Eq e) => Eq (Array B ix e) where
   (==) = eq (==)
   {-# INLINE (==) #-}
+
+instance (Index ix, Ord e) => Ord (Array B ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 instance Index ix => Construct B ix e where
   getComp = bComp
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
@@ -22,10 +22,12 @@
   , toManifest
   , compute
   , computeAs
+  , computeProxy
   , computeSource
   , clone
   , convert
   , convertAs
+  , convertProxy
   , gcastArr
   , loadMutableS
   , loadMutableOnP
@@ -40,7 +42,6 @@
 import           Data.Foldable                      (Foldable (..))
 import           Data.Massiv.Array.Delayed.Internal
 import           Data.Massiv.Array.Ops.Fold         as M
-import           Data.Massiv.Array.Ops.Map          (iforM_)
 import           Data.Massiv.Array.Unsafe
 import           Data.Massiv.Core.Common
 import           Data.Massiv.Core.List
@@ -213,11 +214,36 @@
 {-# INLINE compute #-}
 
 -- | Just as `compute`, but let's you supply resulting representation type as an argument.
+--
+-- ====__Examples__
+--
+-- >>> computeAs P $ range Seq 0 10
+-- (Array P Seq (10)
+--   [ 0,1,2,3,4,5,6,7,8,9 ])
+--
 computeAs :: (Load r' ix e, Mutable r ix e) => r -> Array r' ix e -> Array r ix e
 computeAs _ = compute
 {-# INLINE computeAs #-}
 
 
+-- | Same as `convert` and `convertAs`, but let's you supply resulting representation type as a proxy
+-- argument.
+--
+-- @since 0.1.1
+--
+-- ====__Examples__
+--
+-- Useful for cases when representation constructor isn't available for some reason:
+--
+-- >>> computeProxy (Nothing :: Maybe P) $ range Seq 0 10
+-- (Array P Seq (10)
+--   [ 0,1,2,3,4,5,6,7,8,9 ])
+--
+computeProxy :: (Load r' ix e, Mutable r ix e) => proxy r -> Array r' ix e -> Array r ix e
+computeProxy _ = compute
+{-# INLINE computeProxy #-}
+
+
 -- | This is just like `compute`, but can be applied to `Source` arrays and will be a noop if
 -- resulting type is the same as the input.
 computeSource :: forall r' r ix e . (Source r' ix e, Mutable r ix e)
@@ -254,12 +280,22 @@
 {-# INLINE convertAs #-}
 
 
+-- | Same as `convert` and `convertAs`, but let's you supply resulting representation type as a
+-- proxy argument.
+--
+-- @since 0.1.1
+--
+convertProxy :: (Mutable r' ix e, Mutable r ix e, Typeable ix, Typeable e)
+             => proxy r -> Array r' ix e -> Array r ix e
+convertProxy _ = convert
+{-# INLINE convertProxy #-}
+
 sequenceOnP :: (Source r1 ix (IO e), Mutable r ix e) =>
                [Int] -> Array r1 ix (IO e) -> IO (Array r ix e)
 sequenceOnP wIds !arr = do
   resArrM <- unsafeNew (size arr)
   withScheduler_ wIds $ \scheduler ->
-    iforM_ arr $ \ !ix action ->
+    flip imapM_ arr $ \ !ix action ->
       scheduleWork scheduler $ action >>= unsafeWrite resArrM ix
   unsafeFreeze (getComp arr) resArrM
 {-# INLINE sequenceOnP #-}
@@ -270,41 +306,22 @@
 {-# INLINE sequenceP #-}
 
 
-
-
-
--- sequenceOnP' :: (NFData e, Source r1 ix (IO e), Mutable r ix e) =>
---                [Int] -> Array r1 ix (IO e) -> IO (Array r ix e)
--- sequenceOnP' wIds !arr = do
---   resArrM <- unsafeNew (size arr)
---   scheduler <- makeScheduler wIds
---   iforM_ arr $ \ !ix action ->
---     submitRequest scheduler $ JobRequest $ do
---       res <- action
---       res `deepseq` unsafeWrite resArrM ix res
---   waitTillDone scheduler
---   unsafeFreeze resArrM
--- {-# INLINE sequenceOnP' #-}
-
-
--- sequenceP' :: (NFData e, Source r1 ix (IO e), Mutable r ix e)
---            => Array r1 ix (IO e) -> IO (Array r ix e)
--- sequenceP' = sequenceOnP' []
--- {-# INLINE sequenceP' #-}
-
 -- | Convert a ragged array into a usual rectangular shaped one.
 fromRaggedArray :: (Ragged r' ix e, Mutable r ix e) =>
                    Array r' ix e -> Either ShapeError (Array r ix e)
-fromRaggedArray arr = unsafePerformIO $ do
-  let sz = edgeSize arr
-  mArr <- unsafeNew sz
-  let loadWith using =
-        loadRagged using (unsafeLinearWrite mArr) 0 (totalElem sz) (tailDim sz) arr
-  try $ case getComp arr of
-          Seq -> loadWith id >> unsafeFreeze (getComp arr) mArr
-          ParOn ss -> do
-            withScheduler_ ss (loadWith . scheduleWork)
-            unsafeFreeze (getComp arr) mArr
+fromRaggedArray arr =
+  unsafePerformIO $ do
+    let sz = edgeSize arr
+    mArr <- unsafeNew sz
+    let loadWith using = loadRagged using (unsafeLinearWrite mArr) 0 (totalElem sz) (tailDim sz) arr
+    try $
+      case getComp arr of
+        Seq -> do
+          loadWith id
+          unsafeFreeze Seq mArr
+        pComp@(ParOn ss) -> do
+          withScheduler_ ss (loadWith . scheduleWork)
+          unsafeFreeze pComp mArr
 {-# INLINE fromRaggedArray #-}
 
 -- | Same as `fromRaggedArray`, but will throw an error if its shape is not
@@ -317,4 +334,3 @@
     Left RowTooLongError  -> error "Too many elements in a row"
     Right resArr          -> resArr
 {-# INLINE fromRaggedArray' #-}
-
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
@@ -1,9 +1,11 @@
 {-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MagicHash             #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UnboxedTuples         #-}
 {-# LANGUAGE UndecidableInstances  #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest.Primitive
@@ -22,7 +24,7 @@
 
 import           Control.DeepSeq                     (NFData (..), deepseq)
 import           Control.Monad.ST                    (runST)
-import           Data.Massiv.Array.Delayed.Internal  (eq)
+import           Data.Massiv.Array.Delayed.Internal  (eq, ord)
 import           Data.Massiv.Array.Manifest.Internal
 import           Data.Massiv.Array.Manifest.List     as A
 import           Data.Massiv.Array.Mutable
@@ -33,8 +35,12 @@
 import           Data.Primitive                      (sizeOf)
 import           Data.Primitive.ByteArray
 import           Data.Primitive.Types                (Prim)
+import           Data.Primitive.Types
 import qualified Data.Vector.Primitive               as VP
+import           GHC.Base                            (unsafeCoerce#)
 import           GHC.Exts                            as GHC (IsList (..))
+import           GHC.Int                             (Int (..))
+import           GHC.Prim
 import           Prelude                             hiding (mapM)
 
 -- | Representation for `Prim`itive elements
@@ -55,6 +61,9 @@
   (==) = eq (==)
   {-# INLINE (==) #-}
 
+instance (Prim e, Ord e, Index ix) => Ord (Array P ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 instance (Prim e, Index ix) => Construct P ix e where
   getComp = pComp
@@ -161,7 +170,34 @@
   unsafeLinearWrite (MPArray _ v) = writeByteArray v
   {-# INLINE unsafeLinearWrite #-}
 
+  unsafeNewA sz (State s#) =
+    let kb# = totalSize# sz (undefined :: e)
+        (# s'#, mba# #) = newByteArray# kb# s# in
+      pure (State s'#, MPArray sz (MutableByteArray mba#))
+  {-# INLINE unsafeNewA #-}
 
+  unsafeThawA (PArray _ sz (ByteArray ba#)) s =
+    pure (s, MPArray sz (MutableByteArray (unsafeCoerce# ba#)))
+  {-# INLINE unsafeThawA #-}
+
+  unsafeFreezeA comp (MPArray sz (MutableByteArray mba#)) (State s#) =
+    let (# s'#, ba# #) = unsafeFreezeByteArray# mba# s# in
+      pure (State s'#, PArray comp sz (ByteArray ba#))
+  {-# INLINE unsafeFreezeA #-}
+
+  unsafeLinearWriteA (MPArray _ (MutableByteArray mba#)) (I# i#) val (State s#) =
+    pure (State (writeByteArray# mba# i# val s#))
+  {-# INLINE unsafeLinearWriteA #-}
+
+
+
+totalSize# :: (Index ix, Prim e) => ix -> e -> Int#
+totalSize# sz dummy = k# *# sizeOf# dummy
+  where
+    !(I# k#) = totalElem sz
+{-# INLINE totalSize# #-}
+
+
 instance ( VP.Prim e
          , IsList (Array L ix e)
          , Nested LN ix e
@@ -186,5 +222,4 @@
            copyByteArray marr 0 arr (start * elSize) (len * elSize)
            unsafeFreezeByteArray marr
 {-# INLINE vectorToByteArray #-}
-
 
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
@@ -20,7 +20,7 @@
   ) where
 
 import           Control.DeepSeq                     (NFData (..), deepseq)
-import           Data.Massiv.Array.Delayed.Internal  (eq)
+import           Data.Massiv.Array.Delayed.Internal  (eq, ord)
 import           Data.Massiv.Array.Manifest.Internal
 import           Data.Massiv.Array.Manifest.List     as A
 import           Data.Massiv.Array.Mutable
@@ -49,6 +49,10 @@
 instance (VS.Storable e, Eq e, Index ix) => Eq (Array S ix e) where
   (==) = eq (==)
   {-# INLINE (==) #-}
+
+instance (VS.Storable e, Ord e, Index ix) => Ord (Array S ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 instance (VS.Storable e, Index ix) => Construct S ix e where
   getComp = sComp
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
@@ -20,7 +20,7 @@
   ) where
 
 import           Control.DeepSeq                     (NFData (..), deepseq)
-import           Data.Massiv.Array.Delayed.Internal  (eq)
+import           Data.Massiv.Array.Delayed.Internal  (eq, ord)
 import           Data.Massiv.Array.Manifest.Internal (M, toManifest)
 import           Data.Massiv.Array.Manifest.List     as A
 import           Data.Massiv.Array.Mutable
@@ -63,6 +63,10 @@
 instance (VU.Unbox e, Eq e, Index ix) => Eq (Array U ix e) where
   (==) = eq (==)
   {-# INLINE (==) #-}
+
+instance (VU.Unbox e, Ord e, Index ix) => Ord (Array U ix e) where
+  compare = ord compare
+  {-# INLINE compare #-}
 
 
 instance (VU.Unbox e, Index ix) => Source U ix e where
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
@@ -1,8 +1,11 @@
+{-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE MagicHash             #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
+{-# LANGUAGE UnboxedTuples         #-}
 -- |
 -- Module      : Data.Massiv.Array.Mutable
 -- Copyright   : (c) Alexey Kuleshevich 2018
@@ -26,15 +29,27 @@
   , modify'
   , swap
   , swap'
+  -- * Generate (experimental)
+
+  -- $generate
+  , generateM
+  , generateLinearM
+  , mapM
+  , imapM
+  , forM
+  , iforM
+  , sequenceM
   ) where
 
-import           Prelude                  hiding (read)
+import           Prelude                             hiding (mapM, read)
 
-import           Control.Monad            (unless)
-import           Control.Monad.Primitive  (PrimMonad (..))
+import           Control.Monad                       (unless)
+import           Control.Monad.Primitive             (PrimMonad (..))
 import           Data.Massiv.Array.Manifest.Internal
 import           Data.Massiv.Array.Unsafe
 import           Data.Massiv.Core.Common
+import           GHC.Int                             (Int (..))
+import           GHC.Prim
 
 -- errorSizeMismatch fName sz1 sz2 =
 --   error $ fName ++ ": Size mismatch: " ++ show sz1 ++ " /= " ++ show sz2
@@ -156,3 +171,133 @@
       else ix1
 {-# INLINE swap' #-}
 
+
+unsafeLinearFillM :: (Mutable r ix e, Monad m) =>
+                     MArray RealWorld r ix e -> (Int -> m e) -> WorldState -> m WorldState
+unsafeLinearFillM ma f (State s_#) = go 0# s_#
+  where
+    !(I# k#) = totalElem (msize ma)
+    go i# s# =
+      case i# <# k# of
+        0# -> return (State s#)
+        _ -> do
+          let i = I# i#
+          res <- f i
+          State s'# <- unsafeLinearWriteA ma i res (State s#)
+          go (i# +# 1#) s'#
+{-# INLINE unsafeLinearFillM #-}
+
+
+-- | /O(n)/ - Same as `generateM` but using a flat index.
+--
+-- @since 0.1.1
+generateLinearM :: (Monad m, Mutable r ix e) => Comp -> ix -> (Int -> m e) -> m (Array r ix e)
+generateLinearM comp sz f = do
+  (s, mba) <- unsafeNewA (liftIndex (max 0) sz) (State (noDuplicate# realWorld#))
+  s' <- unsafeLinearFillM mba f s
+  (_, ba) <- unsafeFreezeA comp mba s'
+  return ba
+{-# INLINE generateLinearM #-}
+
+-- | /O(n)/ - Generate an array monadically using it's mutable interface. Computation will be done
+  -- sequentially, regardless of `Comp` argument.
+--
+-- @since 0.1.1
+generateM :: (Monad m, Mutable r ix e) => Comp -> ix -> (ix -> m e) -> m (Array r ix e)
+generateM comp sz f = generateLinearM comp sz (f . fromLinearIndex sz)
+{-# INLINE generateM #-}
+
+
+-- | /O(n)/ - Map an index aware monadic action over an Array. This operation will force computation
+-- sequentially and will result in a manifest Array.
+--
+-- @since 0.1.1
+imapM
+  :: (Monad m, Source r ix e, Mutable r' ix e') =>
+     r' -> (ix -> e -> m e') -> Array r ix e -> m (Array r' ix e')
+imapM _ f arr =
+  generateLinearM (getComp arr) sz (\ !i -> f (fromLinearIndex sz i) (unsafeLinearIndex arr i))
+  where
+    !sz = size arr
+{-# INLINE imapM #-}
+
+-- | /O(n)/ - Map a monadic action over an Array. This operation will force computation sequentially
+-- and will result in a manifest Array.
+--
+-- @since 0.1.1
+--
+-- ====__Examples__
+--
+-- >>> mapM P (\i -> Just (i*i)) $ range Seq 0 5
+-- Just (Array P Seq (5)
+--   [ 0,1,4,9,16 ])
+--
+mapM
+  :: (Monad m, Source r ix e, Mutable r' ix e') =>
+     r' -> (e -> m e') -> Array r ix e -> m (Array r' ix e')
+mapM r f = imapM r (const f)
+{-# INLINE mapM #-}
+
+
+-- | /O(n)/ - Same as `mapM`, but with its arguments flipped.
+--
+-- @since 0.1.1
+forM ::
+     (Monad m, Source r ix e, Mutable r' ix e')
+  => r'
+  -> Array r ix e
+  -> (e -> m e')
+  -> m (Array r' ix e')
+forM r = flip (mapM r)
+{-# INLINE forM #-}
+
+
+-- | /O(n)/ - Same as `imapM`, but with its arguments flipped.
+--
+-- @since 0.1.1
+iforM :: (Monad m, Source r ix e, Mutable r' ix e') =>
+         r' -> Array r ix e -> (ix -> e -> m e') -> m (Array r' ix e')
+iforM r = flip (imapM r)
+{-# INLINE iforM #-}
+
+
+-- | /O(n)/ - Sequence monadic actions in a source Array. This operation will force the computation
+-- sequentially and will result in a manifest Array.
+--
+-- @since 0.1.1
+sequenceM
+  :: (Monad m, Source r ix (m e), Mutable r' ix e) =>
+     r' -> Array r ix (m e) -> m (Array r' ix e)
+sequenceM r = mapM r id
+{-# INLINE sequenceM #-}
+
+
+{- $generate
+
+Functions in this sections can monadically generate manifest arrays using their associated mutable
+interface. Due to the sequential nature of monads generation is done also sequentially regardless of
+supplied computation strategy. All of functions here are very much experimental, so please
+<https://github.com/lehins/massiv/issues/new report an issue> if you see something not working
+properly.
+
+Here is a very imperative like for loop that creates an array while performing a side effect for
+each newly created element:
+
+@
+printSquare :: Int -> IO (Array P Ix1 Int)
+printSquare n = forM P (range Seq 0 n) $ \i -> do
+  let e = i*i
+  putStrLn $ "Element at index: " ++ show i ++ " = " ++ show e ++ ";"
+  return e
+@
+
+>>> printSquare 5
+Element at index: 0 = 0;
+Element at index: 1 = 1;
+Element at index: 2 = 4;
+Element at index: 3 = 9;
+Element at index: 4 = 16;
+(Array P Seq (5)
+  [ 0,1,4,9,16 ])
+
+-}
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
@@ -14,8 +14,8 @@
   , imap
   -- ** Monadic
   , mapM_
-  , imapM_
   , forM_
+  , imapM_
   , iforM_
   , mapP_
   , imapP_
@@ -30,13 +30,14 @@
   , izipWith3
   ) where
 
-import           Control.Monad              (void, when)
+
+import           Control.Monad                       (void, when)
 import           Data.Massiv.Array.Delayed.Internal
 import           Data.Massiv.Core.Common
 import           Data.Massiv.Core.Scheduler
-import           Prelude                    hiding (map, mapM_, unzip, unzip3,
-                                             zip, zip3, zipWith, zipWith3)
-
+import           Prelude                             hiding (map, mapM, mapM_,
+                                                      unzip, unzip3, zip, zip3,
+                                                      zipWith, zipWith3)
 
 -- | Map a function over an array
 map :: Source r ix e' => (e' -> e) -> Array r ix e' -> Array D ix e
@@ -148,22 +149,6 @@
 {-# INLINE forM_ #-}
 
 
--- | Map a monadic index aware function over an array sequentially, while discarding the result.
---
--- ==== __Examples__
---
--- >>> imapM_ (curry print) $ range 10 15
--- (0,10)
--- (1,11)
--- (2,12)
--- (3,13)
--- (4,14)
---
-imapM_ :: (Source r ix a, Monad m) => (ix -> a -> m b) -> Array r ix a -> m ()
-imapM_ f !arr =
-  iterM_ zeroIndex (size arr) 1 (<) $ \ !ix -> f ix (unsafeIndex arr ix)
-{-# INLINE imapM_ #-}
-
 -- | Just like `imapM_`, except with flipped arguments.
 iforM_ :: (Source r ix a, Monad m) => Array r ix a -> (ix -> a -> m b) -> m ()
 iforM_ = flip imapM_
@@ -197,24 +182,3 @@
         void $ f ix (unsafeLinearIndex arr i)
 {-# INLINE imapP_ #-}
 
-
-
--- -- | Map an IO action, that is index aware, over an array in parallel, while
--- -- discarding the result.
--- imapP_ :: (NFData b, Source r ix a) => (ix -> a -> IO b) -> Array r ix a -> IO ()
--- imapP_ f !arr = do
---   let !sz = size arr
---   splitWork_ sz $ \ !scheduler !chunkLength !totalLength !slackStart -> do
---     loopM_ 0 (< slackStart) (+ chunkLength) $ \ !start ->
---       submitRequest scheduler $
---       JobRequest 0 $
---       iterLinearM_ sz start (start + chunkLength) 1 (<) $ \ !i ix -> do
---         res <- f ix (unsafeLinearIndex arr i)
---         res `deepseq` return ()
---     when (slackStart < totalLength) $
---       submitRequest scheduler $
---       JobRequest 0 $
---       iterLinearM_ sz slackStart totalLength 1 (<) $ \ !i ix -> do
---         res <- f ix (unsafeLinearIndex arr i)
---         res `deepseq` return ()
--- {-# INLINE imapP_ #-}
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
@@ -62,3 +62,4 @@
 isEmpty :: Size r ix e => Array r ix e -> Bool
 isEmpty !arr = 0 == elemsCount arr
 {-# INLINE isEmpty #-}
+
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
@@ -1,8 +1,11 @@
 {-# LANGUAGE BangPatterns          #-}
 {-# LANGUAGE DefaultSignatures     #-}
 {-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE MagicHash             #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
+{-# LANGUAGE UnboxedTuples         #-}
 {-# LANGUAGE UndecidableInstances  #-}
 -- |
 -- Module      : Data.Massiv.Core.Common
@@ -24,6 +27,8 @@
   , InnerSlice(..)
   , Manifest(..)
   , Mutable(..)
+  , State(..)
+  , WorldState
   , Ragged(..)
   , Nested(..)
   , NestedStruct
@@ -39,13 +44,16 @@
   , borderIndex
   , evaluateAt
   , module Data.Massiv.Core.Index
+  -- * Common Operations
+  , imapM_
   , module Data.Massiv.Core.Computation
   ) where
 
-import           Control.Monad.Primitive      (PrimMonad (..))
+import           Control.Monad.Primitive
 import           Data.Massiv.Core.Computation
 import           Data.Massiv.Core.Index
 import           Data.Typeable
+import           GHC.Prim
 
 -- | The array family. Representations @r@ describes how data is arranged or computed. All arrays
 -- have a common property that each index @ix@ always maps to the same unique element, even if that
@@ -147,6 +155,11 @@
   unsafeLinearIndexM :: Array r ix e -> Int -> e
 
 
+data State s = State (State# s)
+
+type WorldState = State RealWorld
+
+
 class Manifest r ix e => Mutable r ix e where
   data MArray s r ix e :: *
 
@@ -175,7 +188,37 @@
   unsafeLinearWrite :: PrimMonad m =>
                        MArray (PrimState m) r ix e -> Int -> e -> m ()
 
+  -- | Create new mutable array, leaving it's elements uninitialized. Size isn't validated
+  -- either.
+  unsafeNewA :: Applicative f => ix -> WorldState -> f (WorldState, MArray RealWorld r ix e)
+  unsafeNewA sz (State s#) =
+    case internal (unsafeNew sz :: IO (MArray RealWorld r ix e)) s# of
+      (# s'#, ma #) -> pure (State s'#, ma)
+  {-# INLINE unsafeNewA #-}
 
+  unsafeThawA :: Applicative m =>
+                 Array r ix e -> WorldState -> m (WorldState, MArray RealWorld r ix e)
+  unsafeThawA arr (State s#) =
+    case internal (unsafeThaw arr :: IO (MArray RealWorld r ix e)) s# of
+      (# s'#, ma #) -> pure (State s'#, ma)
+  {-# INLINE unsafeThawA #-}
+
+  unsafeFreezeA :: Applicative m =>
+                   Comp -> MArray RealWorld r ix e -> WorldState -> m (WorldState, Array r ix e)
+  unsafeFreezeA comp marr (State s#) =
+    case internal (unsafeFreeze comp marr :: IO (Array r ix e)) s# of
+      (# s'#, a #) -> pure (State s'#, a)
+  {-# INLINE unsafeFreezeA #-}
+
+  unsafeLinearWriteA :: Applicative m =>
+                        MArray RealWorld r ix e -> Int -> e -> WorldState -> m WorldState
+  unsafeLinearWriteA marr i val (State s#) =
+    case internal (unsafeLinearWrite marr i val :: IO ()) s# of
+      (# s'#, _ #) -> pure (State s'#)
+  {-# INLINE unsafeLinearWriteA #-}
+
+
+
 class Nested r ix e where
   fromNested :: NestedStruct r ix e -> Array r ix e
 
@@ -310,3 +353,21 @@
 -- errorImpossible loc =
 --   error $ "Please report this error. Impossible happend at: " ++ loc
 -- {-# NOINLINE errorImpossible #-}
+
+
+
+-- | Map a monadic index aware function over an array sequentially, while discarding the result.
+--
+-- ==== __Examples__
+--
+-- >>> imapM_ (curry print) $ range 10 15
+-- (0,10)
+-- (1,11)
+-- (2,12)
+-- (3,13)
+-- (4,14)
+--
+imapM_ :: (Source r ix a, Monad m) => (ix -> a -> m b) -> Array r ix a -> m ()
+imapM_ f !arr =
+  iterM_ zeroIndex (size arr) 1 (<) $ \ !ix -> f ix (unsafeIndex arr ix)
+{-# INLINE imapM_ #-}
diff --git a/src/Data/Massiv/Core/Index/Class.hs b/src/Data/Massiv/Core/Index/Class.hs
--- a/src/Data/Massiv/Core/Index/Class.hs
+++ b/src/Data/Massiv/Core/Index/Class.hs
@@ -21,20 +21,30 @@
 import           Data.Massiv.Core.Iterator
 import           GHC.TypeLits
 
+-- | A way to select Array dimension.
 newtype Dim = Dim Int deriving (Show, Eq, Ord, Num, Real, Integral, Enum)
 
+-- | Zero-dimension, i.e. a scalar. Can't really be used directly as there are no instances of
+-- `Index` for it, and is included for completeness.
 data Ix0 = Ix0 deriving (Eq, Ord, Show)
 
+-- | 1-dimensional index. Synonym for `Int` and `Data.Massiv.Core.Index.Ix.Ix1`.
 type Ix1T = Int
 
+-- | 2-dimensional index as tuple of `Int`s.
 type Ix2T = (Int, Int)
 
+-- | 3-dimensional index as 3-tuple of `Int`s.
 type Ix3T = (Int, Int, Int)
 
+-- | 4-dimensional index as 4-tuple of `Int`s.
 type Ix4T = (Int, Int, Int, Int)
 
+-- | 5-dimensional index as 5-tuple of `Int`s.
 type Ix5T = (Int, Int, Int, Int, Int)
 
+-- | This type family will always point to a type for a dimension that is one lower than the type
+-- argument.
 type family Lower ix :: *
 
 type instance Lower Ix1T = Ix0
@@ -43,34 +53,46 @@
 type instance Lower Ix4T = Ix3T
 type instance Lower Ix5T = Ix4T
 
-
+-- | This is bread and butter of multi-dimensional array indexing. It is unlikely that any of the
+-- functions in this class will be useful to a regular user, unless general algorithms are being
+-- implemented that do span multiple dimensions.
 class (Eq ix, Ord ix, Show ix, NFData ix) => Index ix where
   type Rank ix :: Nat
 
+  -- | Rank of an array that has this index type, i.e. what is the dimensionality.
   rank :: ix -> Dim
 
   -- | Total number of elements in an array of this size.
   totalElem :: ix -> Int
 
+  -- | Prepend a dimension to the index
   consDim :: Int -> Lower ix -> ix
 
+  -- | Take a dimension from the index from the outside
   unconsDim :: ix -> (Int, Lower ix)
 
+  -- | Apppend a dimension to the index
   snocDim :: Lower ix -> Int -> ix
 
+  -- | Take a dimension from the index from the inside
   unsnocDim :: ix -> (Lower ix, Int)
 
+  -- | Remove a dimension from the index
   dropDim :: ix -> Dim -> Maybe (Lower ix)
 
+  -- | Extract the value index has at specified dimension.
   getIndex :: ix -> Dim -> Maybe Int
 
+  -- | Set the value for an index at specified dimension.
   setIndex :: ix -> Dim -> Int -> Maybe ix
 
+  -- | Lift an `Int` to any index by replicating the value as many times as there are dimensions.
   pureIndex :: Int -> ix
 
   -- | Zip together two indices with a function
   liftIndex2 :: (Int -> Int -> Int) -> ix -> ix -> ix
 
+  -- | Index with all zeros
   zeroIndex :: ix
   zeroIndex = pureIndex 0
   {-# INLINE [1] zeroIndex #-}
@@ -91,17 +113,18 @@
       !(i0, ixL) = unconsDim ix
   {-# INLINE [1] isSafeIndex #-}
 
-  -- | Produce linear index from size and index
+  -- | Convert linear index from size and index
   toLinearIndex :: ix -- ^ Size
                 -> ix -- ^ Index
                 -> Int
-
   default toLinearIndex :: Index (Lower ix) => ix -> ix -> Int
   toLinearIndex !sz !ix = toLinearIndex szL ixL * n + i
     where !(szL, n) = unsnocDim sz
           !(ixL, i) = unsnocDim ix
   {-# INLINE [1] toLinearIndex #-}
 
+  -- | Convert linear index from size and index with an accumulator. Currently is useless and will
+  -- likley be removed in future versions.
   toLinearIndexAcc :: Int -> ix -> ix -> Int
   default toLinearIndexAcc :: Index (Lower ix) => Int -> ix -> ix -> Int
   toLinearIndexAcc !acc !sz !ix = toLinearIndexAcc (acc * n + i) szL ixL
@@ -109,13 +132,15 @@
           !(i, ixL) = unconsDim ix
   {-# INLINE [1] toLinearIndexAcc #-}
 
-  -- | Produce N Dim index from size and linear index
+  -- | Compute an index from size and linear index
   fromLinearIndex :: ix -> Int -> ix
   default fromLinearIndex :: Index (Lower ix) => ix -> Int -> ix
   fromLinearIndex sz k = consDim q ixL
     where !(q, ixL) = fromLinearIndexAcc (snd (unconsDim sz)) k
   {-# INLINE [1] fromLinearIndex #-}
 
+  -- | Compute an index from size and linear index using an accumulator, thus trying to optimize for
+  -- tail recursion while getting the index computed.
   fromLinearIndexAcc :: ix -> Int -> (Int, ix)
   default fromLinearIndexAcc :: Index (Lower ix) => ix -> Int -> (Int, ix)
   fromLinearIndexAcc ix' !k = (q, consDim r ixL)
@@ -124,7 +149,13 @@
           !(q, r) = quotRem kL m
   {-# INLINE [1] fromLinearIndexAcc #-}
 
-  repairIndex :: ix -> ix -> (Int -> Int -> Int) -> (Int -> Int -> Int) -> ix
+  -- | A way to make sure index is withing the bounds for the supplied size. Takes two functions
+  -- that will be invoked whenever index (2nd arg) is outsize the supplied size (1st arg)
+  repairIndex :: ix -- ^ Size
+              -> ix -- ^ Index
+              -> (Int -> Int -> Int) -- ^ Repair when below zero
+              -> (Int -> Int -> Int) -- ^ Repair when higher than size
+              -> ix
   default repairIndex :: Index (Lower ix)
     => ix -> ix -> (Int -> Int -> Int) -> (Int -> Int -> Int) -> ix
   repairIndex !sz !ix rBelow rOver =
@@ -133,16 +164,18 @@
           !(i, ixL) = unconsDim ix
   {-# INLINE [1] repairIndex #-}
 
+  -- | Iterator for the index. Same as `iterM`, but pure.
   iter :: ix -> ix -> Int -> (Int -> Int -> Bool) -> a -> (ix -> a -> a) -> a
   iter sIx eIx inc cond acc f =
     runIdentity $ iterM sIx eIx inc cond acc (\ix -> return . f ix)
   {-# INLINE iter #-}
 
+  -- | This function is what makes it possible to iterate over an array of any dimension.
   iterM :: Monad m =>
            ix -- ^ Start index
         -> ix -- ^ End index
         -> Int -- ^ Increment
-        -> (Int -> Int -> Bool) -- ^ Continue iteration while predicate is True (eg. until end of row)
+        -> (Int -> Int -> Bool) -- ^ Continue iterating while predicate is True (eg. until end of row)
         -> a -- ^ Initial value for an accumulator
         -> (ix -> a -> m a) -- ^ Accumulator function
         -> m a
@@ -157,6 +190,7 @@
       !(k1, eIxL) = unconsDim eIx
   {-# INLINE iterM #-}
 
+  -- | Same as `iterM`, but don't bother with accumulator and return value.
   iterM_ :: Monad m => ix -> ix -> Int -> (Int -> Int -> Bool) -> (ix -> m a) -> m ()
   default iterM_ :: (Index (Lower ix), Monad m)
     => ix -> ix -> Int -> (Int -> Int -> Bool) -> (ix -> m a) -> m ()
@@ -372,7 +406,7 @@
     (f i0 j0, f i1 j1, f i2 j2, f i3 j3, f i4 j4)
   {-# INLINE [1] liftIndex2 #-}
 
-
+-- | Helper function for throwing out of bounds errors
 errorIx :: (Show ix, Show ix') => String -> ix -> ix' -> a
 errorIx fName sz ix =
   error $
diff --git a/src/Data/Massiv/Core/Index/Ix.hs b/src/Data/Massiv/Core/Index/Ix.hs
--- a/src/Data/Massiv/Core/Index/Ix.hs
+++ b/src/Data/Massiv/Core/Index/Ix.hs
@@ -39,33 +39,51 @@
 
 infixr 5 :>, :.
 
+-- | Another type synonym for 1-dimensional index, i.e. `Int` and `Ix1T`. Provided here purely for
+-- consistency.
 type Ix1 = Int
 
+-- | This is a very handy pattern synonym to indicate that any arbitrary whole number is an `Int`,
+-- i.e. a 1-dimensional index: @(Ix1 i) == (i :: Int)@
 pattern Ix1 :: Int -> Ix1
 pattern Ix1 i = i
 
+-- | 2-dimensional index. This also a base index for higher dimensions.
 data Ix2 = (:.) {-# UNPACK #-} !Int {-# UNPACK #-} !Int
+
+-- | 2-dimensional index constructor. Useful when @TypeOperators@ extension isn't enabled, or simply
+-- infix notation is inconvenient. @(Ix2 i j) == (i :. j)@.
 pattern Ix2 :: Int -> Int -> Ix2
 pattern Ix2 i j = i :. j
 
+-- | 3-dimensional type synonym. Useful as a alternative to enabling @DataKinds@ and using type
+-- level Nats.
 type Ix3 = IxN 3
+
+-- | 3-dimensional index constructor. @(Ix3 i j k) == (i :> j :. k)@.
 pattern Ix3 :: Int -> Int -> Int -> Ix3
 pattern Ix3 i j k = i :> j :. k
 
+-- | 4-dimensional type synonym.
 type Ix4 = IxN 4
+-- | 4-dimensional index constructor. @(Ix4 i j k l) == (i :> j :> k :. l)@.
 pattern Ix4 :: Int -> Int -> Int -> Int -> Ix4
 pattern Ix4 i j k l = i :> j :> k :. l
 
+-- | 5-dimensional type synonym.
 type Ix5 = IxN 5
+-- | 5-dimensional index constructor.  @(Ix5 i j k l m) = (i :> j :> k :> l :. m)@.
 pattern Ix5 :: Int -> Int -> Int -> Int -> Int -> Ix5
 pattern Ix5 i j k l m = i :> j :> k :> l :. m
 
 
 #if __GLASGOW_HASKELL__ >= 800
 
+-- | n-dimensional index. Needs a base case, which is the `Ix2`.
 data IxN (n :: Nat) where
   (:>) :: {-# UNPACK #-} !Int -> !(Ix (n - 1)) -> IxN n
 
+-- | Define n-dimensional index by relating a general `IxN` with two few cases.
 type family Ix (n :: Nat) = r | r -> n where
   Ix 0 = Ix0
   Ix 1 = Ix1
@@ -200,35 +218,42 @@
 instance Ord (Ix (n - 1)) => Ord (IxN n) where
   compare (i1 :> ix1) (i2 :> ix2) = compare i1 i2 <> compare ix1 ix2
 
-
+-- | Convert a `Int` tuple to `Ix2`
 toIx2 :: Ix2T -> Ix2
 toIx2 (i, j) = i :. j
 {-# INLINE toIx2 #-}
 
+-- | Convert an `Ix2` to `Int` tuple
 fromIx2 :: Ix2 -> Ix2T
 fromIx2 (i :. j) = (i, j)
 {-# INLINE fromIx2 #-}
 
+-- | Convert a `Int` 3-tuple to `Ix3`
 toIx3 :: Ix3T -> Ix3
 toIx3 (i, j, k) = i :> j :. k
 {-# INLINE toIx3 #-}
 
+-- | Convert an `Ix3` to `Int` 3-tuple
 fromIx3 :: Ix3 -> Ix3T
 fromIx3 (i :> j :. k) = (i, j, k)
 {-# INLINE fromIx3 #-}
 
+-- | Convert a `Int` 4-tuple to `Ix4`
 toIx4 :: Ix4T -> Ix4
 toIx4 (i, j, k, l) = i :> j :> k :. l
 {-# INLINE toIx4 #-}
 
+-- | Convert an `Ix4` to `Int` 4-tuple
 fromIx4 :: Ix4 -> Ix4T
 fromIx4 (i :> j :> k :. l) = (i, j, k, l)
 {-# INLINE fromIx4 #-}
 
+-- | Convert a `Int` 5-tuple to `Ix5`
 toIx5 :: Ix5T -> Ix5
 toIx5 (i, j, k, l, m) = i :> j :> k :> l :. m
 {-# INLINE toIx5 #-}
 
+-- | Convert an `Ix5` to `Int` 5-tuple
 fromIx5 :: Ix5 -> Ix5T
 fromIx5 (i :> j :> k :> l :. m) = (i, j, k, l, m)
 {-# INLINE fromIx5 #-}
diff --git a/src/Data/Massiv/Core/Iterator.hs b/src/Data/Massiv/Core/Iterator.hs
--- a/src/Data/Massiv/Core/Iterator.hs
+++ b/src/Data/Massiv/Core/Iterator.hs
@@ -11,34 +11,50 @@
   ( loop
   , loopM
   , loopM_
+  , loopDeepM
   ) where
 
 
 -- | Efficient loop with an accumulator
 loop :: Int -> (Int -> Bool) -> (Int -> Int) -> a -> (Int -> a -> a) -> a
-loop !init' condition increment !initAcc f = go init' initAcc where
-  go !step !acc =
-    case condition step of
-      False -> acc
-      True  -> go (increment step) (f step acc)
+loop !init' condition increment !initAcc f = go init' initAcc
+  where
+    go !step !acc =
+      case condition step of
+        False -> acc
+        True -> go (increment step) (f step acc)
 {-# INLINE loop #-}
 
 
 -- | Very efficient monadic loop with an accumulator
 loopM :: Monad m => Int -> (Int -> Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a
-loopM !init' condition increment !initAcc f = go init' initAcc where
-  go !step !acc =
-    case condition step of
-      False -> return acc
-      True  -> f step acc >>= go (increment step)
+loopM !init' condition increment !initAcc f = go init' initAcc
+  where
+    go !step !acc =
+      case condition step of
+        False -> return acc
+        True -> f step acc >>= go (increment step)
 {-# INLINE loopM #-}
 
 
 -- | Efficient monadic loop. Result of each iteration is discarded.
 loopM_ :: Monad m => Int -> (Int -> Bool) -> (Int -> Int) -> (Int -> m a) -> m ()
-loopM_ !init' condition increment f = go init' where
-  go !step =
-    case condition step of
-      False -> return ()
-      True  -> f step >> go (increment step)
+loopM_ !init' condition increment f = go init'
+  where
+    go !step =
+      case condition step of
+        False -> return ()
+        True -> f step >> go (increment step)
 {-# INLINE loopM_ #-}
+
+
+-- | Less efficient monadic loop with an accumulator that reverses the direction of action
+-- application
+loopDeepM :: Monad m => Int -> (Int -> Bool) -> (Int -> Int) -> a -> (Int -> a -> m a) -> m a
+loopDeepM !init' condition increment !initAcc f = go init' initAcc
+  where
+    go !step !acc =
+      case condition step of
+        False -> return acc
+        True -> go (increment step) acc >>= f step
+{-# INLINE loopDeepM #-}
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
@@ -26,7 +26,7 @@
   ) where
 
 import           Control.Exception
-import           Control.Monad              (unless)
+import           Control.Monad              (unless, when)
 import           Data.Coerce
 import           Data.Foldable              (foldr')
 import           Data.Functor.Identity
@@ -125,8 +125,13 @@
   {-# INLINE uncons #-}
   flatten = id
   {-# INLINE flatten #-}
+  -- unsafeGenerateM !comp !k f = do
+  --   xs <- loopM (k - 1) (>= 0) (subtract 1) [] $ \i acc -> do
+  --     e <- f i
+  --     return (e:acc)
+  --   return $ LArray comp $ coerce xs
   unsafeGenerateM !comp !k f = do
-    xs <- loopM (k - 1) (>= 0) (subtract 1) [] $ \i acc -> do
+    xs <- loopDeepM 0 (< k) (+ 1) [] $ \i acc -> do
       e <- f i
       return (e:acc)
     return $ LArray comp $ coerce xs
@@ -174,11 +179,17 @@
             newX = LArray lComp x
         in Just (newX, newArr)
   {-# INLINE uncons #-}
-  unsafeGenerateM !comp !sz f = do
+  -- unsafeGenerateM Seq !sz f = do
+  --   let !(k, szL) = unconsDim sz
+  --   loopM (k - 1) (>= 0) (subtract 1) (empty Seq) $ \i acc -> do
+  --     e <- unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))
+  --     return (cons e acc)
+  unsafeGenerateM Seq !sz f = do
     let !(k, szL) = unconsDim sz
-    loopM (k - 1) (>= 0) (subtract 1) (empty comp) $ \i acc -> do
-      e <- unsafeGenerateM comp szL (\ !ixL -> f (consDim i ixL))
+    loopDeepM 0 (< k) (+ 1) (empty Seq) $ \i acc -> do
+      e <- unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))
       return (cons e acc)
+  unsafeGenerateM (ParOn wss) sz f = unsafeGenerateParM wss sz f
   {-# INLINE unsafeGenerateM #-}
   flatten arr = LArray {lComp = lComp arr, lData = coerce xs}
     where
@@ -206,6 +217,87 @@
       (coerce xs)
 
 
+-- unsafeGenerateParM ::
+--      (Elt LN ix e ~ Array LN (Lower ix) e, Index ix, Monad m, Ragged L (Lower ix) e)
+--   => [Int]
+--   -> ix
+--   -> (ix -> m e)
+--   -> m (Array L ix e)
+-- unsafeGenerateParM wws !sz f = do
+--   res <- sequence $ unsafePerformIO $ do
+--     let !(k, szL) = unconsDim sz
+--     resLs <- divideWork wws k $ \ !scheduler !chunkLength !totalLength !slackStart -> do
+--         loopM_ 0 (< slackStart) (+ chunkLength) $ \ !start -> do
+--           scheduleWork scheduler $ do
+--             res <- loopM start (< (start + chunkLength)) (+ 1) [] $ \i acc -> do
+--               return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+--             return $! sequence res
+--         when (slackStart < totalLength) $
+--           scheduleWork scheduler $ do
+--             res <- loopM (slackStart) (< totalLength) (+ 1) [] $ \i acc -> do
+--               return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+--             return $! sequence res
+--     return resLs
+--   return $ LArray (ParOn wws) $ List $ concat res
+-- {-# INLINE unsafeGenerateParM #-}
+
+unsafeGenerateParM ::
+     (Elt LN ix e ~ Array LN (Lower ix) e, Index ix, Monad m, Ragged L (Lower ix) e)
+  => [Int]
+  -> ix
+  -> (ix -> m e)
+  -> m (Array L ix e)
+unsafeGenerateParM wws !sz f = do
+  res <- sequence $ unsafePerformIO $ do
+    let !(k, szL) = unconsDim sz
+    resLs <- divideWork wws k $ \ !scheduler !chunkLength !totalLength !slackStart -> do
+        loopM_ 0 (< slackStart) (+ chunkLength) $ \ !start -> do
+          scheduleWork scheduler $ do
+            -- res <- loopM (start + chunkLength - 1) (>= start) (subtract 1) [] $ \i acc -> do
+            --   return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+            -- return $! sequence res
+            res <- loopDeepM start (< (start + chunkLength)) (+ 1) [] $ \i acc -> do
+              return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+            return $! sequence res
+        when (slackStart < totalLength) $
+          scheduleWork scheduler $ do
+            -- res <- loopM (totalLength - 1) (>= slackStart) (subtract 1) [] $ \i acc -> do
+            --   return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+            -- return $! sequence res
+            res <- loopDeepM slackStart (< totalLength) (+ 1) [] $ \i acc -> do
+              return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+            return $! sequence res
+    return resLs
+  return $ LArray (ParOn wws) $ List $ concat res
+{-# INLINE unsafeGenerateParM #-}
+
+
+
+-- unsafeGenerateParM ::
+--      (Elt LN ix e ~ Array LN (Lower ix) e, Index ix, Monad m, Ragged L (Lower ix) e)
+--   => [Int]
+--   -> ix
+--   -> (ix -> m e)
+--   -> m (Array L ix e)
+-- unsafeGenerateParM wws !sz f = do
+--   res <- sequence $ unsafePerformIO $ do
+--     let !(k, szL) = unconsDim sz
+--     resLs <- divideWork wws k $ \ !scheduler !chunkLength !totalLength !slackStart -> do
+--         when (slackStart < totalLength) $
+--           scheduleWork scheduler $ do
+--             res <- loopM (totalLength - 1) (>= slackStart) (subtract 1) [] $ \i acc -> do
+--               return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+--             return $! sequence res
+--         loopM_ slackStart (> 0) (subtract chunkLength) $ \ !start -> do
+--           let !end = start - chunkLength
+--           scheduleWork scheduler $ do
+--             res <- loopM (start - 1) (>= end) (subtract 1) [] $ \i acc -> do
+--               return (fmap lData (unsafeGenerateM Seq szL (\ !ixL -> f (consDim i ixL))):acc)
+--             return $! sequence res
+--     return resLs
+--   return $ LArray (ParOn wws) $ List $ concat res
+-- {-# INLINE unsafeGenerateParM #-}
+
 instance {-# OVERLAPPING #-} Construct L Ix1 e where
   getComp = lComp
   {-# INLINE getComp #-}
@@ -231,7 +323,7 @@
   unsafeMakeArray comp sz f = unsafeGenerateN comp sz f
   {-# INLINE unsafeMakeArray #-}
 
-
+ -- TODO: benchmark against using unsafeGenerateM directly
 unsafeGenerateN ::
   ( Index ix
   , Ragged r ix e
@@ -258,18 +350,6 @@
   unsafeMakeArray (getComp arr) (size arr) (unsafeIndex arr)
 {-# INLINE toListArray #-}
 
-
-
-
--- -- | Version of foldr that supports foldr/build list fusion implemented by GHC.
--- foldrFB :: (e -> b -> b) -> b -> Int -> (Int -> e) -> b
--- --foldrFB c n k f = loop (k - 1) (>= 0) (subtract 1) n $ \i acc -> f i `c` acc
--- foldrFB c n k f = go 0
---   where
---     go !i
---       | i == k = n
---       | otherwise = let !v = f i in v `c` go (i + 1)
--- {-# INLINE [0] foldrFB #-}
 
 
 instance {-# OVERLAPPING #-} (Ragged L ix e, Show e) => Show (Array L ix e) where
diff --git a/src/Data/Massiv/Core/Scheduler.hs b/src/Data/Massiv/Core/Scheduler.hs
--- a/src/Data/Massiv/Core/Scheduler.hs
+++ b/src/Data/Massiv/Core/Scheduler.hs
@@ -79,9 +79,9 @@
 uninitialized = error "Data.Array.Massiv.Scheduler: uncomputed job result"
 
 
--- | Execute some action that needs a resource. Perform different cleanup
--- actions depending if thataction resulted in an error or was successful. Sort
--- of like `bracket` and `bracketOnError` with info about exception combined.
+-- | Execute some action that needs a resource. Perform different cleanup actions depending if
+-- thataction resulted in an error or was successful. Sort of like `bracket` and `bracketOnError`
+-- with info about exception combined.
 bracketWithException :: forall a b c d .
   IO a -- ^ Acquire resource
   -> (a -> IO b) -- ^ Run after successfull execution
@@ -99,18 +99,16 @@
       _ <- uninterruptibleMask_ $ afterSuccess x
       return y
 
--- | Run arbitrary computations in parallel. A pool of workers is initialized,
--- unless Worker Stations list is empty and a global worker pool is currently
--- available. All of those workers will be stealing work that you can schedule
--- using `scheduleWork`. The order in which work is scheduled will be the same
--- as the order of the resuts of those computations, stored withing the
--- resulting array. Size of the array, which is also the first element in the
--- returned tuple, will match the number of times `scheduleWork` has been
--- invoked. This function blocks until all of the submitted jobs has finished or
--- one of them resulted in an exception, which will be re-thrown here.
+-- | Run arbitrary computations in parallel. A pool of workers is initialized, unless Worker
+-- Stations list is empty and a global worker pool is currently available. All of those workers will
+-- be stealing work that you can schedule using `scheduleWork`. The order in which work is scheduled
+-- will be the same as the order of the resuts of those computations, stored withing the resulting
+-- array. Size of the array, which is also the first element in the returned tuple, will match the
+-- number of times `scheduleWork` has been invoked. This function blocks until all of the submitted
+-- jobs has finished or one of them resulted in an exception, which will be re-thrown here.
 --
--- __Important__: In order to get work done truly in parallel, program needs to be
--- compiled with @-threaded@ GHC flag and executed with @+RTS -N@.
+-- __Important__: In order to get work done truly in parallel, program needs to be compiled with
+-- @-threaded@ GHC flag and executed with @+RTS -N@.
 --
 withScheduler :: [Int] -- ^ Worker Stations, i.e. capabilities. Empty list will
                        -- result in utilization of all available capabilities.
@@ -176,11 +174,10 @@
 divideWork_ wss sz submit = divideWork wss sz submit >> return ()
 
 
--- | Linearly (row-major first) and equally divide work among available
--- workers. Submit function will receive a `Scheduler`, length of each chunk,
--- total number of elements, as well as where chunks end and slack begins. Slack
--- work will get picked up by the first worker, that has finished working on his
--- chunk. Returns list with results in the same order that work was submitted
+-- | Linearly (row-major first) and equally divide work among available workers. Submit function
+-- will receive a `Scheduler`, length of each chunk, total number of elements, as well as where
+-- chunks end and slack begins. Slack work will get picked up by the first worker, that has finished
+-- working on his chunk. Returns list with results in the same order that work was submitted
 divideWork :: Index ix
            => [Int] -- ^ Worker Stations (capabilities)
            -> ix -- ^ Size
@@ -195,9 +192,8 @@
           !slackStart = chunkLength * numWorkers scheduler
       submit scheduler chunkLength totalLength slackStart
 
--- | Wait till workers finished with all submitted jobs, but raise an exception
--- if either of them has died. Raised exception is the same one that was the
--- cause of worker's death.
+-- | Wait till workers finished with all submitted jobs, but raise an exception if either of them
+-- has died. Raised exception is the same one that was the cause of worker's death.
 waitTillDone :: Scheduler a -> IO ()
 waitTillDone (Scheduler {..}) = readIORef jobsCountIORef >>= waitTill 0
   where
@@ -210,11 +206,10 @@
             Nothing  -> waitTill (jobsDone + 1) jobsCount
 
 
--- | Worker can either be doing work, waiting for a job, or going into
--- retirement. Temp workers are rarely in waiting state, unless there is simply
--- not enough work for all workers in the pool. Unlike temp workers, global
--- workers do spend quite a bit of time waiting for work and they are never
--- retired, but ruthlessly killed.
+-- | Worker can either be doing work, waiting for a job, or going into retirement. Temp workers are
+-- rarely in waiting state, unless there is simply not enough work for all workers in the
+-- pool. Unlike temp workers, global workers do spend quite a bit of time waiting for work and they
+-- are never retired, but ruthlessly killed.
 runWorker :: MVar [Job] -> IO ()
 runWorker jobsMVar = do
   jobs <- takeMVar jobsMVar
@@ -224,9 +219,8 @@
     []             -> runWorker jobsMVar
 
 
--- | Used whenever a pool of new workers is needed. If list is empty all
--- capabilities are utilized, otherwise each element in the list will be an
--- argument to `forkOn`.
+-- | Used whenever a pool of new workers is needed. If list is empty all capabilities are utilized,
+-- otherwise each element in the list will be an argument to `forkOn`.
 hireWorkers :: [Int] -> IO Workers
 hireWorkers wss = do
   wss' <-
@@ -246,11 +240,10 @@
           (unmask . putMVar workerJobDone . Just)
   workerThreadIds `deepseq` return Workers {..}
 
--- | Global workers are the most utilized ones, therefore they are rarily
--- restarted, in particular, only in case when one of them dies of an
--- exception. Weak reference is used so workers don't continue running after
--- MVar has been cleaned up by the GC. Each global worker has his own station,
--- i.e. global workers always span all available capabilities.
+-- | Global workers are the most utilized ones, therefore they are rarily restarted, in particular,
+-- only in case when one of them dies of an exception. Weak reference is used so workers don't
+-- continue running after MVar has been cleaned up by the GC. Each global worker has his own
+-- station, i.e. global workers always span all available capabilities.
 globalWorkersMVar :: MVar (Weak Workers)
 globalWorkersMVar = unsafePerformIO $ do
   workersMVar <- newEmptyMVar
@@ -260,8 +253,8 @@
 {-# NOINLINE globalWorkersMVar #-}
 
 
--- | Hire workers under weak pointers. Finilizer will kill all the
--- workers. These will be used as global workers
+-- | Hire workers under weak pointers. Finalizer will kill all the workers. These will be used as
+-- global workers
 hireWeakWorkers :: key -> IO (Weak Workers)
 hireWeakWorkers k = do
   workers <- hireWorkers []
diff --git a/tests/Data/Massiv/Array/MutableSpec.hs b/tests/Data/Massiv/Array/MutableSpec.hs
new file mode 100644
--- /dev/null
+++ b/tests/Data/Massiv/Array/MutableSpec.hs
@@ -0,0 +1,66 @@
+{-# LANGUAGE FlexibleContexts      #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MonoLocalBinds        #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+module Data.Massiv.Array.MutableSpec (spec) where
+
+import           Data.Massiv.CoreArbitrary as A
+import           Data.Proxy
+import           Data.Functor.Identity
+import           Test.Hspec
+import           Test.QuickCheck
+import           Test.QuickCheck.Function
+
+
+prop_MapMapM :: (Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int) =>
+                r -> Proxy ix -> Fun Int Int -> ArrTiny D ix Int -> Property
+prop_MapMapM r _ f (ArrTiny arr) =
+  computeAs r (A.map (apply f) arr) === runIdentity (A.mapM r (return . apply f) arr)
+
+prop_iMapiMapM :: (Show (Array r ix Int), Eq (Array r ix Int), Mutable r ix Int) =>
+                r -> Proxy ix -> Fun (ix, Int) Int -> ArrTiny D ix Int -> Property
+prop_iMapiMapM r _ f (ArrTiny arr) =
+  computeAs r (A.imap (curry (apply f)) arr) ===
+  runIdentity (A.imapM r (\ix e -> return $ apply f (ix, e)) arr)
+
+
+generateSpec :: Spec
+generateSpec = do
+  describe "map == mapM" $ do
+    describe "P" $ do
+      it "Ix1" $ property $ prop_MapMapM P (Proxy :: Proxy Ix1)
+      it "Ix2" $ property $ prop_MapMapM P (Proxy :: Proxy Ix2)
+      it "Ix3" $ property $ prop_MapMapM P (Proxy :: Proxy Ix3)
+    describe "U" $ do
+      it "Ix1" $ property $ prop_MapMapM U (Proxy :: Proxy Ix1)
+      it "Ix2" $ property $ prop_MapMapM U (Proxy :: Proxy Ix2)
+      it "Ix3" $ property $ prop_MapMapM U (Proxy :: Proxy Ix3)
+    describe "S" $ do
+      it "Ix1" $ property $ prop_MapMapM S (Proxy :: Proxy Ix1)
+      it "Ix2" $ property $ prop_MapMapM S (Proxy :: Proxy Ix2)
+      it "Ix3" $ property $ prop_MapMapM S (Proxy :: Proxy Ix3)
+    describe "B" $ do
+      it "Ix1" $ property $ prop_MapMapM B (Proxy :: Proxy Ix1)
+      it "Ix2" $ property $ prop_MapMapM B (Proxy :: Proxy Ix2)
+      it "Ix3" $ property $ prop_MapMapM B (Proxy :: Proxy Ix3)
+  describe "imap == imapM" $ do
+    describe "P" $ do
+      it "Ix1" $ property $ prop_iMapiMapM P (Proxy :: Proxy Ix1)
+      it "Ix2T" $ property $ prop_iMapiMapM P (Proxy :: Proxy Ix2T)
+      it "Ix3T" $ property $ prop_iMapiMapM P (Proxy :: Proxy Ix3T)
+    describe "U" $ do
+      it "Ix1" $ property $ prop_iMapiMapM U (Proxy :: Proxy Ix1)
+      it "Ix2T" $ property $ prop_iMapiMapM U (Proxy :: Proxy Ix2T)
+      it "Ix3T" $ property $ prop_iMapiMapM U (Proxy :: Proxy Ix3T)
+    describe "S" $ do
+      it "Ix1" $ property $ prop_iMapiMapM S (Proxy :: Proxy Ix1)
+      it "Ix2T" $ property $ prop_iMapiMapM S (Proxy :: Proxy Ix2T)
+      it "Ix3T" $ property $ prop_iMapiMapM S (Proxy :: Proxy Ix3T)
+    describe "B" $ do
+      it "Ix1" $ property $ prop_iMapiMapM B (Proxy :: Proxy Ix1)
+      it "Ix2T" $ property $ prop_iMapiMapM B (Proxy :: Proxy Ix2T)
+      it "Ix3T" $ property $ prop_iMapiMapM B (Proxy :: Proxy Ix3T)
+
+
+spec :: Spec
+spec = describe "GenerateM" generateSpec
diff --git a/tests/Data/Massiv/Array/Ops/ConstructSpec.hs b/tests/Data/Massiv/Array/Ops/ConstructSpec.hs
--- a/tests/Data/Massiv/Array/Ops/ConstructSpec.hs
+++ b/tests/Data/Massiv/Array/Ops/ConstructSpec.hs
@@ -40,7 +40,10 @@
   => Proxy ix
   -> Arr U ix Int
   -> Property
-prop_toFromList _ (Arr arr) = arr === fromLists' (getComp arr) (toLists arr :: [ListItem ix Int])
+prop_toFromList _ (Arr arr) = comp === comp' .&&. arr === arr'
+  where comp = getComp arr
+        arr' = fromLists' comp (toLists arr)
+        comp' = getComp arr'
 
 
 prop_excFromToListIx2 :: Comp -> [[Int]] -> Property
diff --git a/tests/Data/Massiv/CoreArbitrary.hs b/tests/Data/Massiv/CoreArbitrary.hs
--- a/tests/Data/Massiv/CoreArbitrary.hs
+++ b/tests/Data/Massiv/CoreArbitrary.hs
@@ -6,6 +6,7 @@
 {-# LANGUAGE UndecidableInstances  #-}
 module Data.Massiv.CoreArbitrary
   ( Arr(..)
+  , ArrTiny(..)
   , ArrIx(..)
   , ArrP(..)
   , ArrIxP(..)
@@ -31,6 +32,8 @@
 
 data Arr r ix e = Arr (Array r ix e)
 
+data ArrTiny r ix e = ArrTiny (Array r ix e)
+
 data ArrS r ix e = ArrS (Array r ix e)
 
 data ArrP r ix e = ArrP (Array r ix e)
@@ -42,6 +45,7 @@
 data ArrIxP r ix e = ArrIxP (Array r ix e) ix
 
 deriving instance (Show (Array r ix e)) => Show (Arr r ix e)
+deriving instance (Show (Array r ix e)) => Show (ArrTiny r ix e)
 deriving instance (Show (Array r ix e)) => Show (ArrS r ix e)
 deriving instance (Show (Array r ix e)) => Show (ArrP r ix e)
 deriving instance (Show (Array r ix e), Show ix) => Show (ArrIx r ix e)
@@ -62,6 +66,15 @@
     return $ makeArray comp sz func
 
 
+-- | Arbitrary small and possibly empty array. Computation strategy can be either `Seq` or `Par`.
+instance (CoArbitrary ix, Arbitrary ix, Typeable e, Construct r ix e, Arbitrary e) =>
+         Arbitrary (ArrTiny r ix e) where
+  arbitrary = do
+    SzZ sz <- arbitrary
+    func <- arbitrary
+    comp <- oneof [pure Seq, pure Par]
+    return $ ArrTiny $ makeArray comp (liftIndex (`mod` 10) sz) func
+
 -- | Arbitrary non-empty array. Computation strategy can be either `Seq` or `Par`.
 instance (CoArbitrary ix, Arbitrary ix, Typeable e, Construct r ix e, Arbitrary e) =>
          Arbitrary (Arr r ix e) where
@@ -70,6 +83,7 @@
     func <- arbitrary
     comp <- oneof [pure Seq, pure Par]
     return $ Arr $ makeArray comp sz func
+
 
 -- | Arbitrary non-empty array
 instance (CoArbitrary ix, Arbitrary ix, Typeable e, Construct r ix e, Arbitrary e) =>
diff --git a/tests/Spec.hs b/tests/Spec.hs
--- a/tests/Spec.hs
+++ b/tests/Spec.hs
@@ -2,6 +2,7 @@
 
 import           Data.Massiv.Array.DelayedSpec         as Delayed
 import           Data.Massiv.Array.Manifest.VectorSpec as Vector
+import           Data.Massiv.Array.MutableSpec         as Mutable
 import           Data.Massiv.Array.Ops.ConstructSpec   as Construct
 import           Data.Massiv.Array.Ops.FoldSpec        as Fold
 import           Data.Massiv.Array.Ops.SliceSpec       as Slice
@@ -27,6 +28,7 @@
       Fold.spec
       Slice.spec
       Transform.spec
-    Delayed.spec
-    Stencil.spec
-    Vector.spec
+    describe "Delayed" $ Delayed.spec
+    describe "Mutable" $ Mutable.spec
+    describe "Stencil" $ Stencil.spec
+    describe "Vector" $ Vector.spec
