diff --git a/Z-Data.cabal b/Z-Data.cabal
--- a/Z-Data.cabal
+++ b/Z-Data.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.4
 name:               Z-Data
-version:            1.2.1.0
+version:            1.3.0.0
 synopsis:           Array, vector and text
 description:        This package provides array, slice and text operations
 license:            BSD-3-Clause
diff --git a/Z/Data/Array/Base.hs b/Z/Data/Array/Base.hs
--- a/Z/Data/Array/Base.hs
+++ b/Z/Data/Array/Base.hs
@@ -416,11 +416,7 @@
         copySmallMutableArray marr' 0 marr 0 (sizeofSmallMutableArray marr)
         return marr'
     {-# INLINE resizeMutableArr #-}
-#if MIN_VERSION_base(4,14,0)
     shrinkMutableArr = shrinkSmallMutableArray
-#else
-    shrinkMutableArr _ _ = return ()
-#endif
     {-# INLINE shrinkMutableArr #-}
 
     sameMutableArr (SmallMutableArray smarr1#) (SmallMutableArray smarr2#) =
diff --git a/Z/Data/Builder/Numeric.hs b/Z/Data/Builder/Numeric.hs
--- a/Z/Data/Builder/Numeric.hs
+++ b/Z/Data/Builder/Numeric.hs
@@ -144,8 +144,8 @@
     ensureN (max 21 width) (\ (MutablePrimArray mba#) i ->
         if x < 0
         then let !x' = (fromIntegral (complement x) :: Word64) + 1
-             in (c_int_dec x' (-1) width pad (MBA# mba#) i)
-        else c_int_dec (fromIntegral x) (if posSign then 1 else 0) width pad (MBA# mba#) i)
+             in (c_int_dec x' (-1) width pad mba# i)
+        else c_int_dec (fromIntegral x) (if posSign then 1 else 0) width pad mba# i)
   where
     pad = case padding of NoPadding          -> 0
                           RightSpacePadding  -> 1
@@ -765,7 +765,7 @@
     (MutableByteArray pBuf) <- newByteArray GRISU3_DOUBLE_BUF_LEN
     (len, (e, success)) <- allocPrimUnsafe $ \ pLen ->
         allocPrimUnsafe $ \ pE ->
-            c_grisu3 (realToFrac d) (MBA# pBuf) pLen pE
+            c_grisu3 (realToFrac d) pBuf pLen pE
     if success == 0 -- grisu3 fail
     then pure (floatToDigits 10 d)
     else do
@@ -789,7 +789,7 @@
     (MutableByteArray pBuf) <- newByteArray GRISU3_SINGLE_BUF_LEN
     (len, (e, success)) <- allocPrimUnsafe $ \ pLen ->
         allocPrimUnsafe $ \ pE ->
-            c_grisu3_sp (realToFrac d) (MBA# pBuf) pLen pE
+            c_grisu3_sp (realToFrac d) pBuf pLen pE
     if success == 0 -- grisu3 fail
     then pure (floatToDigits 10 d)
     else do
diff --git a/Z/Data/CBytes.hs b/Z/Data/CBytes.hs
--- a/Z/Data/CBytes.hs
+++ b/Z/Data/CBytes.hs
@@ -192,10 +192,10 @@
 -- | Poke 'CBytes' until a \\NUL terminator(or to the end of the array if there's none).
 peekMBACBytes :: MBA# Word8 -> Int -> IO CBytes
 {-# INLINE peekMBACBytes #-}
-peekMBACBytes mba@(MBA# mba#) i = do
+peekMBACBytes mba# i = do
     b <- getSizeofMutableByteArray (MutableByteArray mba#)
     let rest = b-i
-    l <- c_memchr mba i 0 rest
+    l <- c_memchr mba# i 0 rest
     let l' = if l == -1 then rest else l
     mpa <- newPrimArray (l'+1)
     copyMutablePrimArray mpa 0 (MutablePrimArray mba#) i l'
@@ -207,14 +207,14 @@
 -- | Poke 'CBytes' with \\NUL terminator.
 pokeMBACBytes :: MBA# Word8 -> Int -> CBytes -> IO ()
 {-# INLINE pokeMBACBytes #-}
-pokeMBACBytes (MBA# mba#) i (CBytes pa) = do
+pokeMBACBytes mba# i (CBytes pa) = do
         let l = sizeofPrimArray pa
         copyPrimArray (MutablePrimArray mba# :: MutablePrimArray RealWorld Word8) i pa 0 l
 
 -- | Index a 'CBytes' until a \\NUL terminator(or to the end of the array if there's none).
 indexBACBytes :: BA# Word8 -> Int -> CBytes
 {-# INLINE indexBACBytes #-}
-indexBACBytes (BA# ba#) i = runST (do
+indexBACBytes ba# i = runST (do
     let b = sizeofByteArray (ByteArray ba#)
         rest = b-i
         l = V.c_memchr ba# i 0 rest
@@ -611,8 +611,8 @@
                                         \ (_, b) -> return (empty, b)
                          | otherwise = do
     mba@(MutablePrimArray mba#) <- newPrimArray n :: IO (MutablePrimArray RealWorld Word8)
-    a <- fill (MBA# mba#)
-    l <- fromIntegral <$> c_memchr (MBA# mba#) 0 0 n
+    a <- fill mba#
+    l <- fromIntegral <$> c_memchr mba# 0 0 n
     let l' = if l == -1 then n-1 else l
     shrinkMutablePrimArray mba (l'+1)
     writePrimArray mba l' 0
@@ -634,7 +634,7 @@
                    | otherwise = do
     mba@(MutablePrimArray mba#) <- newPinnedPrimArray n :: IO (MutablePrimArray RealWorld Word8)
     a <- withMutablePrimArrayContents mba (fill . castPtr)
-    l <- fromIntegral <$> c_memchr (MBA# mba#) 0 0 n
+    l <- fromIntegral <$> c_memchr mba# 0 0 n
     let l' = if l == -1 then n-1 else l
     shrinkMutablePrimArray mba (l'+1)
     writePrimArray mba l' 0
diff --git a/Z/Data/Text/Regex.hs b/Z/Data/Text/Regex.hs
--- a/Z/Data/Text/Regex.hs
+++ b/Z/Data/Text/Regex.hs
@@ -117,7 +117,7 @@
     (cp, r) <- newCPtrUnsafe (\ mba# ->
         withPrimVectorUnsafe
             (T.getUTF8Bytes t)
-            (hs_re2_compile_pattern_default (MBA# mba#)))
+            (hs_re2_compile_pattern_default mba#))
         p_hs_re2_delete_pattern
 
     when (r == nullPtr) (throwIO (InvalidRegexPattern t callStack))
@@ -133,7 +133,7 @@
 regexOpts RegexOpts{..} t = unsafePerformIO $ do
     (cp, r) <- newCPtrUnsafe ( \ mba# ->
         withPrimVectorUnsafe (T.getUTF8Bytes t) $ \ p o l ->
-            hs_re2_compile_pattern (MBA# mba#) p o l
+            hs_re2_compile_pattern mba# p o l
                 (fromBool posix_syntax  )
                 (fromBool longest_match )
                 max_mem
diff --git a/Z/Data/Vector/Base64.hs b/Z/Data/Vector/Base64.hs
--- a/Z/Data/Vector/Base64.hs
+++ b/Z/Data/Vector/Base64.hs
@@ -54,7 +54,7 @@
 base64EncodeBuilder (V.PrimVector arr s l) =
     B.writeN (base64EncodeLength l) (\ (MutablePrimArray mba#) i -> do
         withPrimArrayUnsafe arr $ \ parr _ ->
-            hs_base64_encode (MBA# mba#) i parr s l)
+            hs_base64_encode mba# i parr s l)
 
 -- | Text version of 'base64Encode'.
 base64EncodeText :: V.Bytes -> T.Text
diff --git a/Z/Data/Vector/Hex.hs b/Z/Data/Vector/Hex.hs
--- a/Z/Data/Vector/Hex.hs
+++ b/Z/Data/Vector/Hex.hs
@@ -82,8 +82,8 @@
     B.writeN (l `unsafeShiftL` 1) (\ (MutablePrimArray mba#) i -> do
         withPrimArrayUnsafe arr $ \ parr _ ->
             if upper
-            then hs_hex_encode_upper (MBA# mba#) i parr s l
-            else hs_hex_encode (MBA# mba#) i parr s l)
+            then hs_hex_encode_upper mba# i parr s l
+            else hs_hex_encode mba# i parr s l)
 
 -- | Text version of 'hexEncode'.
 hexEncodeText :: Bool   -- ^ uppercase?
diff --git a/Z/Foreign.hs b/Z/Foreign.hs
--- a/Z/Foreign.hs
+++ b/Z/Foreign.hs
@@ -1,6 +1,3 @@
-#if __GLASGOW_HASKELL__ >= 810
-{-# LANGUAGE UnliftedNewtypes #-}
-#endif
 {-|
 Module      : Z.Foreign
 Description : Use PrimArray \/ PrimVector with FFI
@@ -79,11 +76,7 @@
   , pinPrimArray
   , pinPrimVector
     -- ** Pointer helpers
-#if __GLASGOW_HASKELL__ >= 810
   , BA# (..), MBA# (..), BAArray# (..)
-#else
-  , BA#, pattern BA#, MBA#, pattern MBA#, BAArray#, pattern BAArray#
-#endif
   , clearMBA
   , clearPtr
   , castPtr
@@ -142,13 +135,9 @@
 -- So it's users' responsibility to make sure the array content is not mutated (a const pointer type may help).
 --
 -- USE THIS TYPE WITH UNSAFE FFI CALL ONLY. A 'ByteArray#' COULD BE MOVED BY GC DURING SAFE FFI CALL.
-#if __GLASGOW_HASKELL__ >= 810
-newtype BA# a = BA# ByteArray#
-#else
 type BA# a = ByteArray#
 pattern BA# :: ByteArray# -> BA# a
 pattern BA# ba = ba
-#endif
 
 -- | Type alias for 'MutableByteArray#' 'RealWorld'.
 --
@@ -159,13 +148,9 @@
 -- <https://github.com/ghc/ghc/blob/master/compiler/GHC/StgToCmm/Foreign.hs#L542 Note [Unlifted boxed arguments to foreign calls]>
 --
 -- USE THIS TYPE WITH UNSAFE FFI CALL ONLY. A 'MutableByteArray#' COULD BE MOVED BY GC DURING SAFE FFI CALL.
-#if __GLASGOW_HASKELL__ >= 810
-newtype MBA# a = MBA# (MutableByteArray# RealWorld)
-#else
 type MBA# a = MutableByteArray# RealWorld
 pattern MBA# :: MutableByteArray# RealWorld -> MBA# a
 pattern MBA# mba = mba
-#endif
 
 -- | Type alias for 'ArrayArray#'.
 --
@@ -198,13 +183,9 @@
 -- -- by the type system in this example since ArrayArray is untyped.
 -- foreign import ccall unsafe "sum_first" sumFirst :: BAArray# Int -> Int -> IO CInt
 -- @
-#if __GLASGOW_HASKELL__ >= 810
-newtype BAArray# a = BAArray# ArrayArray#
-#else
 type BAArray# a = ArrayArray#
 pattern BAArray# :: ArrayArray# -> BAArray# a
 pattern BAArray# baa = baa
-#endif
 
 -- | Clear 'MBA#' with given length to zero.
 clearMBA :: MBA# a
diff --git a/Z/Foreign/CPtr.hs b/Z/Foreign/CPtr.hs
--- a/Z/Foreign/CPtr.hs
+++ b/Z/Foreign/CPtr.hs
@@ -118,18 +118,10 @@
 -- so it may be optimized away, 'withCPtrForever' solves that.
 --
 withCPtrForever :: CPtr a -> (Ptr a -> IO b) -> IO b
-#if MIN_VERSION_base(4,15,0)
 {-# INLINABLE withCPtrForever #-}
 withCPtrForever (CPtr pa@(PrimArray ba#)) f = IO $ \ s ->
     case f (indexPrimArray pa 0) of
         IO action# -> keepAlive# ba# s action#
-#else
-{-# NOINLINE withCPtrForever #-}
-withCPtrForever (CPtr pa@(PrimArray ba#)) f = do
-    r <- f (indexPrimArray pa 0)
-    primitive_ (touch# ba#)
-    return r
-#endif
 
 -- | Pass a list of 'CPtr Foo' as @foo**@. USE THIS FUNCTION WITH UNSAFE FFI ONLY!
 withCPtrsUnsafe :: forall a b. [CPtr a] -> (BA# (Ptr a) -> Int -> IO b) -> IO b
@@ -139,7 +131,7 @@
     foldM_ (\ !i (CPtr pa) ->
         writePrimArray mpa i (indexPrimArray pa 0) >> return (i+1)) 0 cptrs
     (PrimArray ba#) <- unsafeFreezePrimArray mpa
-    r <- f (BA# ba#) len
+    r <- f ba# len
     primitive_ (touch# cptrs)
     return r
   where len = length cptrs
