diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 0.5.9
+
+* Add `mallocCompute`, `mallocCopy` and `unsafeMallocMArray`
+* Fix `.><.`, `><.` and `.><` on empty matrices. Result is now guaranteed to be empty too.
+* Add `unwrapByteArrayOffset` and `unwrapMutableByteArrayOffset`
+* Add `fromByteArrayOffsetM` and `fromMutableByteArrayOffsetM`
+
 # 0.5.8
 
 * Improve loading of push arrays by adding `loadArrayWithSetM` and deprecating `defaultElement`.
diff --git a/massiv.cabal b/massiv.cabal
--- a/massiv.cabal
+++ b/massiv.cabal
@@ -1,5 +1,5 @@
 name:                massiv
-version:             0.5.8.0
+version:             0.5.9.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/Manifest.hs b/src/Data/Massiv/Array/Manifest.hs
--- a/src/Data/Massiv/Array/Manifest.hs
+++ b/src/Data/Massiv/Array/Manifest.hs
@@ -7,7 +7,7 @@
 {-# LANGUAGE TypeFamilies #-}
 -- |
 -- Module      : Data.Massiv.Array.Manifest
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -51,12 +51,16 @@
   , toByteArray
   , toByteArrayM
   , unwrapByteArray
+  , unwrapByteArrayOffset
   , fromByteArray
   , fromByteArrayM
+  , fromByteArrayOffsetM
   , toMutableByteArray
   , unwrapMutableByteArray
+  , unwrapMutableByteArrayOffset
   , fromMutableByteArray
   , fromMutableByteArrayM
+  , fromMutableByteArrayOffsetM
   -- *** Primitive Vector
   , toPrimitiveVector
   , toPrimitiveMVector
@@ -65,6 +69,8 @@
   -- * Storable
   , S(..)
   , Storable
+  , mallocCompute
+  , mallocCopy
   -- ** Conversion
   -- *** Primitive Vector
   , toStorableVector
@@ -91,6 +97,7 @@
   ) where
 
 import Control.Monad
+import Data.Massiv.Array.Mutable
 import Data.ByteString as S hiding (findIndex)
 import Data.ByteString.Builder
 import Data.ByteString.Internal
@@ -186,3 +193,27 @@
         else go (i + 1)
 {-# INLINE findIndex #-}
 
+
+-- | Very similar to @`computeAs` `S`@ except load the source array into memory allocated
+-- with @malloc@ on C heap. It can potentially be useful when iteroperating with some C
+-- programs.
+--
+-- @since 0.5.9
+mallocCompute :: forall r ix e. (Source r ix e, Storable e) => Array r ix e -> IO (Array S ix e)
+mallocCompute arr = do
+  let sz = size arr
+  marr <- unsafeMallocMArray sz
+  computeInto marr arr
+  unsafeFreeze (getComp arr) marr
+{-# INLINE mallocCompute #-}
+
+-- | Allocate memory on C heap with @malloc@ and copy the source array over.
+--
+-- @since 0.5.9
+mallocCopy :: forall ix e. (Index ix, Storable e) => Array S ix e -> IO (Array S ix e)
+mallocCopy arr = do
+  let sz = size arr
+  marr <- unsafeMallocMArray sz
+  unsafeArrayLinearCopy arr 0 marr 0 (SafeSz (totalElem sz))
+  unsafeFreeze (getComp arr) marr
+{-# INLINE mallocCopy #-}
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
@@ -28,12 +28,16 @@
   , toByteArray
   , toByteArrayM
   , unwrapByteArray
+  , unwrapByteArrayOffset
   , unwrapMutableByteArray
+  , unwrapMutableByteArrayOffset
   , fromByteArray
   , fromByteArrayM
+  , fromByteArrayOffsetM
   , toMutableByteArray
   , toMutableByteArrayM
   , fromMutableByteArrayM
+  , fromMutableByteArrayOffsetM
   , fromMutableByteArray
   , shrinkMutableByteArray
   , unsafeAtomicReadIntArray
@@ -48,6 +52,7 @@
   , unsafeAtomicXorIntArray
   ) where
 
+import Control.Monad
 import Control.DeepSeq (NFData(..), deepseq)
 import Control.Monad.Primitive (PrimMonad(..), primitive_)
 import Data.Massiv.Array.Delayed.Pull -- (eq, ord)
@@ -192,7 +197,8 @@
   {-# INLINE unsafeNew #-}
 
   initialize (MPArray sz o mba) =
-    fillByteArray mba o (totalElem sz * sizeOf (undefined :: e)) 0
+    let k = totalElem sz * sizeOf (undefined :: e)
+    in when (k > 0) $ fillByteArray mba o k 0
   {-# INLINE initialize #-}
 
   unsafeLinearRead _mpa@(MPArray _sz o ma) i =
@@ -311,11 +317,12 @@
 --
 -- @since 0.2.1
 toByteArray :: (Index ix, Prim e) => Array P ix e -> ByteArray
-toByteArray arr = fromMaybe (unwrapByteArray $ compute arr) $ toByteArrayM arr
+toByteArray arr = fromMaybe (unwrapByteArray $ clone 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.
+-- | /O(1)/ - Extract the internal `ByteArray`. This will ignore any possible slicing that
+-- has been applied to the array. Use `toByteArray` in order to preserve slicing or
+-- `unwrapByteArrayOffset` to get ahold of the offset
 --
 -- @since 0.5.0
 unwrapByteArray :: Array P ix e -> ByteArray
@@ -323,27 +330,44 @@
 {-# INLINE unwrapByteArray #-}
 
 
+-- | /O(1)/ - Extract potential linear offset into the underlying `ByteArray`, which can
+-- also be extracted with `unwrapByteArray`.
+--
+-- @since 0.5.9
+unwrapByteArrayOffset :: Array P ix e -> Int
+unwrapByteArrayOffset = pOffset
+{-# INLINE unwrapByteArrayOffset #-}
+
+
 -- | /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
+  pData <$ guardNumberOfElements pSize (Sz (elemsBA arr pData))
 {-# INLINE toByteArrayM #-}
 
 
--- | /O(1)/ - Construct a primitive array from the `ByteArray`. Will return `Nothing` if number of
--- elements doesn't match.
+-- | /O(1)/ - Construct a primitive array from the `ByteArray`. Will return `Nothing` if
+-- number of elements doesn't match.
 --
 -- @since 0.3.0
 fromByteArrayM :: (MonadThrow m, Index ix, Prim e) => Comp -> Sz ix -> ByteArray -> m (Array P ix e)
-fromByteArrayM comp sz ba =
-  guardNumberOfElements sz (Sz (elemsBA arr ba)) >> pure arr
-  where
-    arr = PArray comp sz 0 ba
+fromByteArrayM comp sz = fromByteArrayOffsetM comp sz 0
 {-# INLINE fromByteArrayM #-}
 
+-- | /O(1)/ - Construct a primitive array from the `ByteArray`. Will return `Nothing` if
+-- number of elements doesn't match.
+--
+-- @since 0.5.9
+fromByteArrayOffsetM ::
+     (MonadThrow m, Index ix, Prim e) => Comp -> Sz ix -> Int -> ByteArray -> m (Array P ix e)
+fromByteArrayOffsetM comp sz off ba =
+  arr <$ guardNumberOfElements sz (SafeSz (elemsBA arr ba - off))
+  where
+    arr = PArray comp sz off ba
+{-# INLINE fromByteArrayOffsetM #-}
+
 -- | /O(1)/ - Construct a flat Array from `ByteArray`
 --
 -- @since 0.4.0
@@ -360,9 +384,17 @@
 unwrapMutableByteArray (MPArray _ _ mba) = mba
 {-# INLINE unwrapMutableByteArray #-}
 
+-- | /O(1)/ - Extract the linear offset into underlying `MutableByteArray`, which can aslo
+-- be extracted with `unwrapMutableByteArray`.
+--
+-- @since 0.5.9
+unwrapMutableByteArrayOffset :: MArray s P ix e -> Int
+unwrapMutableByteArrayOffset (MPArray _ off _) = off
+{-# INLINE unwrapMutableByteArrayOffset #-}
+
 -- | /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.
+-- that the source at the resulting array are still pointing to the same location in memory.
 --
 -- @since 0.5.0
 toMutableByteArray ::
@@ -396,11 +428,21 @@
 -- @since 0.3.0
 fromMutableByteArrayM ::
      (MonadThrow m, Index ix, Prim e) => Sz ix -> MutableByteArray s -> m (MArray s P ix e)
-fromMutableByteArrayM sz mba =
-  marr <$ guardNumberOfElements sz (Sz (elemsMBA marr mba))
-  where
-    marr = MPArray sz 0 mba
+fromMutableByteArrayM sz = fromMutableByteArrayOffsetM sz 0
 {-# INLINE fromMutableByteArrayM #-}
+
+-- | /O(1)/ - Construct a primitive mutable array from the `MutableByteArray`. Will throw
+-- `SizeElementsMismatchException` if number of elements doesn't match.
+--
+-- @since 0.5.9
+fromMutableByteArrayOffsetM ::
+     (MonadThrow m, Index ix, Prim e) => Sz ix -> Ix1 -> MutableByteArray s -> m (MArray s P ix e)
+fromMutableByteArrayOffsetM sz off mba =
+  marr <$ guardNumberOfElements sz (SafeSz (elemsMBA marr mba - off))
+  where
+    marr = MPArray sz off mba
+{-# INLINE fromMutableByteArrayOffsetM #-}
+
 
 -- | /O(1)/ - Construct a flat Array from `MutableByteArray`
 --
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
@@ -25,6 +25,7 @@
   , fromStorableMVector
   , withPtr
   , unsafeWithPtr
+  , unsafeMallocMArray
   , unsafeArrayToForeignPtr
   , unsafeMArrayToForeignPtr
   , unsafeArrayFromForeignPtr
@@ -36,27 +37,29 @@
 import Control.DeepSeq (NFData(..), deepseq)
 import Control.Monad.IO.Unlift
 import Control.Monad.Primitive (unsafePrimToPrim)
-import Data.Massiv.Array.Delayed.Pull (eqArrays, compareArrays)
+import Data.Massiv.Array.Delayed.Pull (compareArrays, eqArrays)
 import Data.Massiv.Array.Manifest.Internal
-import Data.Massiv.Array.Manifest.Primitive (shrinkMutableByteArray)
-import Data.Primitive.ByteArray (MutableByteArray(..))
 import Data.Massiv.Array.Manifest.List as A
-import Data.Massiv.Vector.Stream as S (steps, isteps)
+import Data.Massiv.Array.Manifest.Primitive (shrinkMutableByteArray)
 import Data.Massiv.Array.Mutable
 import Data.Massiv.Core.Common
 import Data.Massiv.Core.List
 import Data.Massiv.Core.Operations
+import Data.Massiv.Vector.Stream as S (isteps, steps)
+import Data.Primitive.ByteArray (MutableByteArray(..))
 import qualified Data.Vector.Generic.Mutable as VGM
 import qualified Data.Vector.Storable as VS
 import qualified Data.Vector.Storable.Mutable as MVS
+import Foreign.ForeignPtr (withForeignPtr, newForeignPtr)
+import Foreign.Marshal.Array (advancePtr, copyArray)
+import Foreign.Marshal.Alloc
 import Foreign.Ptr
-import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..))
-import Foreign.ForeignPtr (withForeignPtr)
 import Foreign.Storable
-import Foreign.Marshal.Array (copyArray, advancePtr)
 import GHC.Exts as GHC (IsList(..))
+import GHC.ForeignPtr (ForeignPtr(..), ForeignPtrContents(..))
 import Prelude hiding (mapM)
 import System.IO.Unsafe (unsafePerformIO)
+import Control.Exception
 
 #include "massiv.h"
 
@@ -368,3 +371,19 @@
   MSArray sz (MVS.unsafeFromForeignPtr fp offset (unSz sz))
 {-# INLINE unsafeMArrayFromForeignPtr #-}
 
+
+-- | Allocate memory using @malloc@ on C heap, instead of on Haskell heap. Memory is left
+-- uninitialized
+--
+-- @since 0.5.9
+unsafeMallocMArray ::
+     forall ix e. (Index ix, Storable e)
+  => Sz ix
+  -> IO (MArray RealWorld S ix e)
+unsafeMallocMArray sz = do
+  let n = totalElem sz
+  foreignPtr <- mask_ $ do
+    ptr <- mallocBytes (sizeOf (undefined :: e) * n)
+    newForeignPtr finalizerFree ptr
+  pure $ MSArray sz (MVS.unsafeFromForeignPtr0 foreignPtr n)
+{-# INLINE unsafeMallocMArray #-}
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
@@ -450,9 +450,11 @@
   -> m (Vector D e)
 (.><) mm v
   | mCols /= n = throwM $ SizeMismatchException (size mm) (Sz2 n 1)
-  | otherwise = pure $ makeArray (getComp mm <> getComp v) (Sz1 mRows) $ \i ->
+  | mRows == 0 || mCols == 0 = pure $ setComp comp empty
+  | otherwise = pure $ makeArray comp (Sz1 mRows) $ \i ->
       unsafeDotProduct (unsafeLinearSlice (i * n) sz mm) v
   where
+    comp = getComp mm <> getComp v
     Sz2 mRows mCols = size mm
     sz@(Sz1 n) = size v
 {-# INLINE (.><) #-}
@@ -511,6 +513,7 @@
   -> m (Vector r e)
 multiplyVectorByMatrix v mm
   | mRows /= n = throwM $ SizeMismatchException (Sz2 1 n) (size mm)
+  | mRows == 0 || mCols == 0 = pure $ setComp comp empty
   | otherwise =
     pure $!
     unsafePerformIO $ do
@@ -619,11 +622,13 @@
   -> m (Matrix D e)
 multiplyMatricesTransposed arr1 arr2
   | n1 /= m2 = throwM $ SizeMismatchException (size arr1) (Sz2 m2 n2)
+  | isEmpty arr1 || isEmpty arr2 = pure $ setComp comp empty
   | otherwise =
     pure $
-    DArray (getComp arr1 <> getComp arr2) (SafeSz (m1 :. n2)) $ \(i :. j) ->
+    DArray comp (SafeSz (m1 :. n2)) $ \(i :. j) ->
       unsafeDotProduct (unsafeLinearSlice (i * n1) n arr1) (unsafeLinearSlice (j * n1) n arr2)
   where
+    comp = getComp arr1 <> getComp arr2
     n = SafeSz n1
     SafeSz (m1 :. n1) = size arr1
     SafeSz (n2 :. m2) = size arr2
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
@@ -60,6 +60,7 @@
   , unsafeLinearShrink
   , unsafeLinearGrow
     -- * Pointer access
+  , unsafeMallocMArray
   , unsafeWithPtr
   , unsafeArrayToForeignPtr
   , unsafeMArrayToForeignPtr
diff --git a/src/Data/Massiv/Core/Exception.hs b/src/Data/Massiv/Core/Exception.hs
--- a/src/Data/Massiv/Core/Exception.hs
+++ b/src/Data/Massiv/Core/Exception.hs
@@ -2,6 +2,14 @@
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE LambdaCase #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
+-- |
+-- Module      : Data.Massiv.Core.Exception
+-- Copyright   : (c) Alexey Kuleshevich 2019-2020
+-- License     : BSD3
+-- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>
+-- Stability   : experimental
+-- Portability : non-portable
+--
 module Data.Massiv.Core.Exception
   ( ImpossibleException(..)
   , throwImpossible
diff --git a/src/Data/Massiv/Core/Index.hs b/src/Data/Massiv/Core/Index.hs
--- a/src/Data/Massiv/Core/Index.hs
+++ b/src/Data/Massiv/Core/Index.hs
@@ -2,10 +2,10 @@
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE PatternSynonyms #-}
-{-# LANGUAGE TypeOperators #-}
+{-# LANGUAGE ExplicitNamespaces #-}
 -- |
 -- Module      : Data.Massiv.Core.Index
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>
 -- Stability   : experimental
diff --git a/src/Data/Massiv/Core/Index/Internal.hs b/src/Data/Massiv/Core/Index/Internal.hs
--- a/src/Data/Massiv/Core/Index/Internal.hs
+++ b/src/Data/Massiv/Core/Index/Internal.hs
@@ -12,15 +12,11 @@
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
-{-# LANGUAGE TypeSynonymInstances #-}
 {-# LANGUAGE UndecidableInstances #-}
 {-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
-#if __GLASGOW_HASKELL__ < 820
-{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
-#endif
 -- |
 -- Module      : Data.Massiv.Core.Index.Internal
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>
 -- Stability   : experimental
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
@@ -1,18 +1,18 @@
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE ConstraintKinds #-}
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE ScopedTypeVariables #-}
-{-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TypeFamilyDependencies #-}
 {-# LANGUAGE UndecidableInstances #-}
 -- |
 -- Module      : Data.Massiv.Core.Index.Ix
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
@@ -42,11 +42,11 @@
   , pattern Ix5
   , type Sz5
   , pattern Sz5
+  , HighIxN
   ) where
 
 import Control.Monad.Catch (MonadThrow(..))
 import Control.DeepSeq
-import Control.Monad (liftM)
 import Data.Massiv.Core.Index.Internal
 import Data.Proxy
 import qualified Data.Vector.Generic as V
@@ -216,15 +216,7 @@
   fromInteger = pureIndex . fromInteger
   {-# INLINE [1] fromInteger #-}
 
-
-instance {-# OVERLAPPABLE #-} ( 1 <= n
-                              , 4 <= n
-                              , KnownNat n
-                              , KnownNat (n - 1)
-                              , Index (Ix (n - 1))
-                              , IxN (n - 1) ~ Ix (n - 1)
-                              ) =>
-                              Num (IxN n) where
+instance {-# OVERLAPPABLE #-} HighIxN n => Num (IxN n) where
   (+) = liftIndex2 (+)
   {-# INLINE [1] (+) #-}
   (-) = liftIndex2 (-)
@@ -254,14 +246,7 @@
   maxBound = pureIndex maxBound
   {-# INLINE maxBound #-}
 
-instance {-# OVERLAPPABLE #-} ( 1 <= n
-                              , 4 <= n
-                              , KnownNat n
-                              , KnownNat (n - 1)
-                              , Index (Ix (n - 1))
-                              , IxN (n - 1) ~ Ix (n - 1)
-                              ) =>
-                              Bounded (IxN n) where
+instance {-# OVERLAPPABLE #-} HighIxN n => Bounded (IxN n) where
   minBound = pureIndex minBound
   {-# INLINE minBound #-}
   maxBound = pureIndex maxBound
@@ -387,14 +372,11 @@
     repairIndex (SafeSz n) i rBelow rOver :> repairIndex (SafeSz szL) ixL rBelow rOver
   {-# INLINE [1] repairIndex #-}
 
-instance {-# OVERLAPPABLE #-} ( 1 <= n
-                              , 4 <= n
-                              , KnownNat n
-                              , KnownNat (n - 1)
-                              , Index (Ix (n - 1))
-                              , IxN (n - 1) ~ Ix (n - 1)
-                              ) =>
-                              Index (IxN n) where
+-- | Constraint synonym that encapsulates all constraints needed for dimension 4 and higher.
+type HighIxN n
+   = (4 <= n, KnownNat n, KnownNat (n - 1), Index (Ix (n - 1)), IxN (n - 1) ~ Ix (n - 1))
+
+instance {-# OVERLAPPABLE #-} HighIxN n => Index (IxN n) where
   type Dimensions (IxN n) = n
   dimensions _ = fromInteger $ natVal (Proxy :: Proxy n)
   {-# INLINE [1] dimensions #-}
@@ -454,11 +436,11 @@
   {-# INLINE basicUnsafeSlice #-}
   basicOverlaps (MV_Ix2 mvec) (MV_Ix2 mvec') = VM.basicOverlaps mvec mvec'
   {-# INLINE basicOverlaps #-}
-  basicUnsafeNew len = MV_Ix2 `liftM` VM.basicUnsafeNew len
+  basicUnsafeNew len = MV_Ix2 <$> VM.basicUnsafeNew len
   {-# INLINE basicUnsafeNew #-}
-  basicUnsafeReplicate len (i :. j) = MV_Ix2 `liftM` VM.basicUnsafeReplicate len (i, j)
+  basicUnsafeReplicate len (i :. j) = MV_Ix2 <$> VM.basicUnsafeReplicate len (i, j)
   {-# INLINE basicUnsafeReplicate #-}
-  basicUnsafeRead (MV_Ix2 mvec) idx = uncurry (:.) `liftM` VM.basicUnsafeRead mvec idx
+  basicUnsafeRead (MV_Ix2 mvec) idx = uncurry (:.) <$> VM.basicUnsafeRead mvec idx
   {-# INLINE basicUnsafeRead #-}
   basicUnsafeWrite (MV_Ix2 mvec) idx (i :. j) = VM.basicUnsafeWrite mvec idx (i, j)
   {-# INLINE basicUnsafeWrite #-}
@@ -470,7 +452,7 @@
   {-# INLINE basicUnsafeCopy #-}
   basicUnsafeMove (MV_Ix2 mvec) (MV_Ix2 mvec') = VM.basicUnsafeMove mvec mvec'
   {-# INLINE basicUnsafeMove #-}
-  basicUnsafeGrow (MV_Ix2 mvec) len = MV_Ix2 `liftM` VM.basicUnsafeGrow mvec len
+  basicUnsafeGrow (MV_Ix2 mvec) len = MV_Ix2 <$> VM.basicUnsafeGrow mvec len
   {-# INLINE basicUnsafeGrow #-}
 #if MIN_VERSION_vector(0,11,0)
   basicInitialize (MV_Ix2 mvec) = VM.basicInitialize mvec
@@ -481,15 +463,15 @@
 newtype instance VU.Vector Ix2 = V_Ix2 (VU.Vector (Int, Int))
 
 instance V.Vector VU.Vector Ix2 where
-  basicUnsafeFreeze (MV_Ix2 mvec) = V_Ix2 `liftM` V.basicUnsafeFreeze mvec
+  basicUnsafeFreeze (MV_Ix2 mvec) = V_Ix2 <$> V.basicUnsafeFreeze mvec
   {-# INLINE basicUnsafeFreeze #-}
-  basicUnsafeThaw (V_Ix2 vec) = MV_Ix2 `liftM` V.basicUnsafeThaw vec
+  basicUnsafeThaw (V_Ix2 vec) = MV_Ix2 <$> V.basicUnsafeThaw vec
   {-# INLINE basicUnsafeThaw #-}
   basicLength (V_Ix2 vec) = V.basicLength vec
   {-# INLINE basicLength #-}
   basicUnsafeSlice idx len (V_Ix2 vec) = V_Ix2 (V.basicUnsafeSlice idx len vec)
   {-# INLINE basicUnsafeSlice #-}
-  basicUnsafeIndexM (V_Ix2 vec) idx = uncurry (:.) `liftM` V.basicUnsafeIndexM vec idx
+  basicUnsafeIndexM (V_Ix2 vec) idx = uncurry (:.) <$> V.basicUnsafeIndexM vec idx
   {-# INLINE basicUnsafeIndexM #-}
   basicUnsafeCopy (MV_Ix2 mvec) (V_Ix2 vec) = V.basicUnsafeCopy mvec vec
   {-# INLINE basicUnsafeCopy #-}
diff --git a/src/Data/Massiv/Core/Index/Stride.hs b/src/Data/Massiv/Core/Index/Stride.hs
--- a/src/Data/Massiv/Core/Index/Stride.hs
+++ b/src/Data/Massiv/Core/Index/Stride.hs
@@ -1,13 +1,9 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE PatternSynonyms #-}
-
-#if __GLASGOW_HASKELL__ < 820
-{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
-#endif
 -- |
 -- Module      : Data.Massiv.Core.Index.Stride
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
diff --git a/src/Data/Massiv/Core/Index/Tuple.hs b/src/Data/Massiv/Core/Index/Tuple.hs
--- a/src/Data/Massiv/Core/Index/Tuple.hs
+++ b/src/Data/Massiv/Core/Index/Tuple.hs
@@ -6,7 +6,7 @@
 {-# LANGUAGE TypeFamilies #-}
 -- |
 -- Module      : Data.Massiv.Core.Index.Tuple
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <alexey@kuleshevi.ch>
 -- Stability   : experimental
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
@@ -1,7 +1,7 @@
 {-# LANGUAGE BangPatterns #-}
 -- |
 -- Module      : Data.Massiv.Core.Iterator
--- Copyright   : (c) Alexey Kuleshevich 2018-2019
+-- Copyright   : (c) Alexey Kuleshevich 2018-2020
 -- License     : BSD3
 -- Maintainer  : Alexey Kuleshevich <lehins@yandex.ru>
 -- Stability   : experimental
