diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.2.1.0
+version:             0.2.2.0
 synopsis:            Massiv (Массив) is an Array Library.
 description:         Multi-dimensional Arrays with fusion, stencils and parallel computation.
 homepage:            https://github.com/lehins/massiv
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,5 +1,6 @@
 {-# LANGUAGE FlexibleContexts      #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RankNTypes            #-}
 {-# LANGUAGE ScopedTypeVariables   #-}
 {-# LANGUAGE TypeFamilies          #-}
 {-# LANGUAGE TypeOperators         #-}
@@ -18,6 +19,8 @@
   , new
   , thaw
   , freeze
+  , withMArray
+  , withMArrayST
   , read
   , read'
   , write
@@ -45,12 +48,11 @@
 
 import           Control.Monad                       (unless)
 import           Control.Monad.Primitive             (PrimMonad (..))
+import           Control.Monad.ST
 import           Data.Massiv.Array.Manifest.Internal
 import           Data.Massiv.Array.Unsafe
 import           Data.Massiv.Core.Common
-import           GHC.Prim
 
-
 -- | Initialize a new mutable array. Negative size will result in an empty array.
 new :: (Mutable r ix e, PrimMonad m) => ix -> m (MArray (PrimState m) r ix e)
 new sz = unsafeNewZero (liftIndex (max 0) sz)
@@ -66,6 +68,32 @@
 freeze comp marr = clone <$> unsafeFreeze comp marr
 {-# INLINE freeze #-}
 
+
+-- | Create a copy of a pure array, mutate it in place and return its frozen version.
+--
+-- @since 0.2.2
+withMArray ::
+     (Mutable r ix e, PrimMonad m)
+  => Array r ix e
+  -> (MArray (PrimState m) r ix e -> m a)
+  -> m (Array r ix e)
+withMArray arr action = do
+  marr <- thaw arr
+  _ <- action marr
+  unsafeFreeze (getComp arr) marr
+{-# INLINE withMArray #-}
+
+
+-- | Same as `withMArray` but in `ST`.
+--
+-- @since 0.2.2
+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 $ withMArray arr f
+{-# INLINE withMArrayST #-}
 
 -- | /O(1)/ - Lookup an element in the mutable array. Return `Nothing` when index is out of bounds.
 read :: (Mutable r ix e, PrimMonad m) =>
diff --git a/src/Data/Massiv/Array/Numeric.hs b/src/Data/Massiv/Array/Numeric.hs
--- a/src/Data/Massiv/Array/Numeric.hs
+++ b/src/Data/Massiv/Array/Numeric.hs
@@ -65,7 +65,6 @@
 import           Data.Massiv.Array.Manifest.Internal (compute)
 import           Data.Massiv.Array.Ops.Fold         as A
 import           Data.Massiv.Array.Ops.Map          as A
-import           Data.Massiv.Array.Ops.Slice        as A
 import           Data.Massiv.Array.Ops.Transform    as A
 import           Data.Massiv.Core
 import           Data.Massiv.Core.Common
@@ -135,13 +134,12 @@
     show (size arr1) ++ " and " ++ show (size arr2)
   | otherwise =
     DArray (getComp arr1 <> getComp arr2) (m1 :. n2) $ \(i :. j) ->
-      A.sum ((arr1' !> i) .* (arr2' !> j))
+      A.foldlS (+) 0 (A.zipWith (*) (unsafeOuterSlice arr1 i) (unsafeOuterSlice arr2' j))
   where
     (m1 :. n1) = size arr1
     (m2 :. n2) = size arr2
-    arr1' = setComp Seq arr1
     arr2' :: Array r2 Ix2 e
-    arr2' = setComp Seq $ compute $ transpose arr2
+    arr2' = compute $ transpose arr2
 {-# INLINE multArrs #-}
 
 
