diff --git a/Data/Array.hs b/Data/Array.hs
--- a/Data/Array.hs
+++ b/Data/Array.hs
@@ -54,8 +54,6 @@
   ) where
 
 import Data.Ix
-import Data.Typeable ()
-
 import GHC.Arr  -- Most of the hard work is done here
 
 {- $intro
diff --git a/Data/Array/Base.hs b/Data/Array/Base.hs
--- a/Data/Array/Base.hs
+++ b/Data/Array/Base.hs
@@ -1,6 +1,16 @@
-{-# LANGUAGE BangPatterns, CPP, RankNTypes, MagicHash, UnboxedTuples, MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveDataTypeable, UnliftedFFITypes #-}
-{-# LANGUAGE RoleAnnotations #-}
-{-# OPTIONS_HADDOCK hide #-}
+{-# LANGUAGE
+    BangPatterns
+  , CPP
+  , RankNTypes
+  , MagicHash
+  , UnboxedTuples
+  , MultiParamTypeClasses
+  , FlexibleInstances
+  , FlexibleContexts
+  , UnliftedFFITypes
+  , RoleAnnotations
+ #-}
+{-# OPTIONS_HADDOCK not-home #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -15,31 +25,45 @@
 -- Basis for IArray and MArray.  Not intended for external consumption;
 -- use IArray or MArray instead.
 --
+-- = WARNING
+--
+-- This module is considered __internal__.
+--
+-- The Package Versioning Policy __does not apply__.
+--
+-- The contents of this module may change __in any way whatsoever__
+-- and __without any warning__ between minor versions of this package.
+--
+-- Authors importing this module are expected to track development
+-- closely.
 -----------------------------------------------------------------------------
 
 module Data.Array.Base where
 
 import Control.Monad.ST.Lazy ( strictToLazyST )
 import qualified Control.Monad.ST.Lazy as Lazy (ST)
-import Data.Ix ( Ix, range, index, rangeSize )
+import Data.Ix ( Ix, range, index, inRange, rangeSize )
 import Foreign.C.Types
 import Foreign.StablePtr
 
 import Data.Char
-import GHC.Arr          ( STArray )
+import GHC.Arr          ( STArray, unsafeIndex )
 import qualified GHC.Arr as Arr
 import qualified GHC.Arr as ArrST
 import GHC.ST           ( ST(..), runST )
 import GHC.Base         ( IO(..), divInt# )
 import GHC.Exts
 import GHC.Ptr          ( nullPtr, nullFunPtr )
+import GHC.Show         ( appPrec )
 import GHC.Stable       ( StablePtr(..) )
+import GHC.Read         ( expectP, parens, Read(..) )
 import GHC.Int          ( Int8(..),  Int16(..),  Int32(..),  Int64(..) )
 import GHC.Word         ( Word8(..), Word16(..), Word32(..), Word64(..) )
 import GHC.IO           ( stToIO )
 import GHC.IOArray      ( IOArray(..),
                           newIOArray, unsafeReadIOArray, unsafeWriteIOArray )
-import Data.Typeable
+import Text.Read.Lex    ( Lexeme(Ident) )
+import Text.ParserCombinators.ReadPrec ( prec, ReadPrec, step )
 
 #include "MachDeps.h"
 
@@ -170,35 +194,26 @@
     let n = safeRangeSize (l,u)
     in unsafeArray (l,u) (zip [0 .. n - 1] es)
 
-{-# INLINE listArrayST #-}
+{-# INLINE genArray #-}
+-- | Constructs an immutable array using a generator function.
+--
+-- @since 0.5.6.0
+genArray :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
+genArray (l,u) f = listArray (l,u) $ map f $ range (l,u)
+
+{-# INLINE listArrayST #-}   -- See Note [Inlining and fusion]
 listArrayST :: Ix i => (i,i) -> [e] -> ST s (STArray s i e)
-listArrayST (l,u) es = do
-    marr <- newArray_ (l,u)
-    let n = safeRangeSize (l,u)
-    let fillFromList i xs | i == n    = return ()
-                          | otherwise = case xs of
-            []   -> return ()
-            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
-    fillFromList 0 es
-    return marr
+listArrayST = newListArray
 
 {-# RULES
 "listArray/Array" listArray =
     \lu es -> runST (listArrayST lu es >>= ArrST.unsafeFreezeSTArray)
     #-}
 
-{-# INLINE listUArrayST #-}
+{-# INLINE listUArrayST #-}   -- See Note [Inlining and fusion]
 listUArrayST :: (MArray (STUArray s) e (ST s), Ix i)
              => (i,i) -> [e] -> ST s (STUArray s i e)
-listUArrayST (l,u) es = do
-    marr <- newArray_ (l,u)
-    let n = safeRangeSize (l,u)
-    let fillFromList i xs | i == n    = return ()
-                          | otherwise = case xs of
-            []   -> return ()
-            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
-    fillFromList 0 es
-    return marr
+listUArrayST = newListArray
 
 -- I don't know how to write a single rule for listUArrayST, because
 -- the type looks like constrained over 's', which runST doesn't
@@ -259,11 +274,23 @@
     #-}
 
 {-# INLINE (!) #-}
--- | Returns the element of an immutable array at the specified index.
+-- | Returns the element of an immutable array at the specified index,
+-- or throws an exception if the index is out of bounds.
 (!) :: (IArray a e, Ix i) => a i e -> i -> e
 (!) arr i = case bounds arr of
               (l,u) -> unsafeAt arr $ safeIndex (l,u) (numElements arr) i
 
+{-# INLINE (!?) #-}
+-- | Returns 'Just' the element of an immutable array at the specified index,
+-- or 'Nothing' if the index is out of bounds.
+--
+-- @since 0.5.6.0
+(!?) :: (IArray a e, Ix i) => a i e -> i -> Maybe e
+(!?) arr i = let b = bounds arr in
+             if inRange b i
+             then Just $ unsafeAt arr $ unsafeIndex b i
+             else Nothing
+
 {-# INLINE indices #-}
 -- | Returns a list of all the valid indices in an array.
 indices :: (IArray a e, Ix i) => a i e -> [i]
@@ -359,6 +386,94 @@
 ixmap (l,u) f arr =
     array (l,u) [(i, arr ! f i) | i <- range (l,u)]
 
+-- | Lazy right-associative fold.
+--
+-- @since 0.5.8.0
+foldrArray :: (IArray a e, Ix i) => (e -> b -> b) -> b -> a i e -> b
+foldrArray f z = \a ->
+    let !n = numElements a
+        go i | i >= n = z
+             | otherwise = f (unsafeAt a i) (go (i+1))
+    in go 0
+{-# INLINE foldrArray #-}
+
+-- | Strict accumulating left-associative fold.
+--
+-- @since 0.5.8.0
+foldlArray' :: (IArray a e, Ix i) => (b -> e -> b) -> b -> a i e -> b
+foldlArray' f z0 = \a ->
+    let !n = numElements a
+        go !z i | i >= n = z
+                | otherwise = go (f z (unsafeAt a i)) (i+1)
+    in go z0 0
+{-# INLINE foldlArray' #-}
+
+-- | Lazy left-associative fold.
+--
+-- @since 0.5.8.0
+foldlArray :: (IArray a e, Ix i) => (b -> e -> b) -> b -> a i e -> b
+foldlArray f z = \a ->
+    let !n = numElements a
+        go i | i < 0 = z
+             | otherwise = f (go (i-1)) (unsafeAt a i)
+    in go (n-1)
+{-# INLINE foldlArray #-}
+
+-- | Strict accumulating right-associative fold.
+--
+-- @since 0.5.8.0
+foldrArray' :: (IArray a e, Ix i) => (e -> b -> b) -> b -> a i e -> b
+foldrArray' f z0 = \a ->
+    let !n = numElements a
+        go i !z | i < 0 = z
+                | otherwise = go (i-1) (f (unsafeAt a i) z)
+    in go (n-1) z0
+{-# INLINE foldrArray' #-}
+
+-- | Map elements to applicative actions, sequence them left-to-right, and
+-- discard the results.
+--
+-- @since 0.5.8.0
+traverseArray_
+    :: (IArray a e, Ix i, Applicative f) => (e -> f b) -> a i e -> f ()
+traverseArray_ f = foldrArray (\x z -> f x *> z) (pure ())
+{-# INLINE traverseArray_ #-}
+
+-- | @forArray_@ is 'traverseArray_' with its arguments flipped.
+--
+-- @since 0.5.8.0
+forArray_ :: (IArray a e, Ix i, Applicative f) => a i e -> (e -> f b) -> f ()
+forArray_ = flip traverseArray_
+{-# INLINE forArray_ #-}
+
+-- | Strict accumulating left-associative monadic fold.
+--
+-- @since 0.5.8.0
+foldlArrayM'
+     :: (IArray a e, Ix i, Monad m) => (b -> e -> m b) -> b -> a i e -> m b
+foldlArrayM' f z0 = \a ->
+    let !n = numElements a
+        go !z i | i >= n = pure z
+                | otherwise = do
+                    z' <- f z (unsafeAt a i)
+                    go z' (i+1)
+    in go z0 0
+{-# INLINE foldlArrayM' #-}
+
+-- | Strict accumulating right-associative monadic fold.
+--
+-- @since 0.5.8.0
+foldrArrayM'
+    :: (IArray a e, Ix i, Monad m) => (e -> b -> m b) -> b -> a i e -> m b
+foldrArrayM' f z0 = \a ->
+    let !n = numElements a
+        go i !z | i < 0 = pure z
+                | otherwise = do
+                    z' <- f (unsafeAt a i) z
+                    go (i-1) z'
+    in go (n-1) z0
+{-# INLINE foldrArrayM' #-}
+
 -----------------------------------------------------------------------------
 -- Normal polymorphic arrays
 
@@ -398,7 +513,6 @@
 -- "Data.Array.Unboxed" instead of "Data.Array").
 --
 data UArray i e = UArray !i !i !Int ByteArray#
-                  deriving Typeable
 -- There are class-based invariants on both parameters. See also #9220.
 type role UArray nominal nominal
 
@@ -471,7 +585,7 @@
 {-# RULES "cmpUArray/Int" cmpUArray = cmpIntUArray #-}
 
 -----------------------------------------------------------------------------
--- Showing IArrays
+-- Showing and Reading IArrays
 
 {-# SPECIALISE
     showsIArray :: (IArray UArray e, Ix i, Show i, Show e) =>
@@ -480,12 +594,24 @@
 
 showsIArray :: (IArray a e, Ix i, Show i, Show e) => Int -> a i e -> ShowS
 showsIArray p a =
-    showParen (p > 9) $
+    showParen (p > appPrec) $
     showString "array " .
     shows (bounds a) .
     showChar ' ' .
     shows (assocs a)
 
+{-# SPECIALISE
+    readIArray :: (IArray UArray e, Ix i, Read i, Read e) =>
+                   ReadPrec (UArray i e)
+  #-}
+
+readIArray :: (IArray a e, Ix i, Read i, Read e) => ReadPrec (a i e)
+readIArray = parens $ prec appPrec $
+               do expectP (Ident "array")
+                  theBounds <- step readPrec
+                  vals   <- step readPrec
+                  return (array theBounds vals)
+
 -----------------------------------------------------------------------------
 -- Flat unboxed arrays: instances
 
@@ -638,7 +764,7 @@
 
 -- bogus StablePtr value for initialising a UArray of StablePtr.
 nullStablePtr :: StablePtr a
-nullStablePtr = StablePtr (unsafeCoerce# 0#)
+nullStablePtr = StablePtr (unsafeCoerce# nullAddr#)
 
 instance IArray UArray Int8 where
     {-# INLINE bounds #-}
@@ -777,6 +903,9 @@
 instance (Ix ix, Show ix, Show e, IArray UArray e) => Show (UArray ix e) where
     showsPrec = showsIArray
 
+instance (Ix ix, Read ix, Read e, IArray UArray e) => Read (UArray ix e) where
+    readPrec = readIArray
+
 -----------------------------------------------------------------------------
 -- Mutable arrays
 
@@ -796,24 +925,27 @@
 in which the mutable array will be manipulated.
 -}
 class (Monad m) => MArray a e m where
-
-    -- | Returns the bounds of the array
+    -- | Returns the bounds of the array (lowest,highest).
     getBounds      :: Ix i => a i e -> m (i,i)
-    -- | Returns the number of elements in the array
+    -- | Returns the number of elements in the array.
     getNumElements :: Ix i => a i e -> m Int
 
     -- | Builds a new array, with every element initialised to the supplied
-    -- value.
+    -- value. The first and second element of the tuple specifies the lowest
+    -- and highest index, respectively.
     newArray    :: Ix i => (i,i) -> e -> m (a i e)
 
     -- | Builds a new array, with every element initialised to an
     -- undefined value. In a monadic context in which operations must
     -- be deterministic (e.g. the ST monad), the array elements are
     -- initialised to a fixed but undefined value, such as zero.
+    -- The first and second element of the tuple specifies the lowest
+    -- and highest index, respectively.
     newArray_ :: Ix i => (i,i) -> m (a i e)
 
     -- | Builds a new array, with every element initialised to an undefined
-    -- value.
+    -- value. The first and second element of the tuple specifies the lowest
+    -- and highest index, respectively.
     unsafeNewArray_ :: Ix i => (i,i) -> m (a i e)
 
     unsafeRead  :: Ix i => a i e -> Int -> m e
@@ -850,6 +982,8 @@
     -- default initialisation with undefined values if we *do* know the
     -- initial value and it is constant for all elements.
 
+    {-# MINIMAL getBounds, getNumElements, (newArray | unsafeNewArray_), unsafeRead, unsafeWrite #-}
+
 instance MArray IOArray e IO where
     {-# INLINE getBounds #-}
     getBounds (IOArray marr) = stToIO $ getBounds marr
@@ -859,21 +993,41 @@
     unsafeRead  = unsafeReadIOArray
     unsafeWrite = unsafeWriteIOArray
 
-{-# INLINE newListArray #-}
+{-# INLINE newListArray #-}   -- See Note [Inlining and fusion]
 -- | Constructs a mutable array from a list of initial elements.
 -- The list gives the elements of the array in ascending order
--- beginning with the lowest index.
+-- beginning with the lowest index. The first and second element
+-- of the tuple specifies the lowest and highest index, respectively.
 newListArray :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
 newListArray (l,u) es = do
     marr <- newArray_ (l,u)
     let n = safeRangeSize (l,u)
-    let fillFromList i xs | i == n    = return ()
-                          | otherwise = case xs of
-            []   -> return ()
-            y:ys -> unsafeWrite marr i y >> fillFromList (i+1) ys
-    fillFromList 0 es
+        f x k i
+            | i == n    = return ()
+            | otherwise = unsafeWrite marr i x >> k (i+1)
+    foldr f (\ !_i -> return ()) es 0
+    -- The bang above is important for GHC for unbox the Int.
     return marr
 
+{-# INLINE newGenArray #-}
+-- | Constructs a mutable array using a generator function.
+-- It invokes the generator function in ascending order of the indices.
+--
+-- @since 0.5.6.0
+newGenArray :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
+newGenArray bnds f = do
+    let n = safeRangeSize bnds
+    marr <- unsafeNewArray_ bnds
+    let g ix k i
+            | i == n    = return ()
+            | otherwise = do
+                x <- f ix
+                unsafeWrite marr i x
+                k (i+1)
+    foldr g (\ !_i -> return ()) (range bnds) 0
+    -- The bang above is important for GHC for unbox the Int.
+    return marr
+
 {-# INLINE readArray #-}
 -- | Read an element from a mutable array
 readArray :: (MArray a e m, Ix i) => a i e -> i -> m e
@@ -890,6 +1044,31 @@
   n <- getNumElements marr
   unsafeWrite marr (safeIndex (l,u) n i) e
 
+{-# INLINE modifyArray #-}
+-- | Modify an element in a mutable array
+--
+-- @since 0.5.6.0
+modifyArray :: (MArray a e m, Ix i) => a i e -> i -> (e -> e) -> m ()
+modifyArray marr i f = do
+  (l,u) <- getBounds marr
+  n <- getNumElements marr
+  let idx = safeIndex (l,u) n i
+  x <- unsafeRead marr idx
+  unsafeWrite marr idx (f x)
+
+{-# INLINE modifyArray' #-}
+-- | Modify an element in a mutable array. Strict in the written element.
+--
+-- @since 0.5.6.0
+modifyArray' :: (MArray a e m, Ix i) => a i e -> i -> (e -> e) -> m ()
+modifyArray' marr i f = do
+  (l,u) <- getBounds marr
+  n <- getNumElements marr
+  let idx = safeIndex (l,u) n i
+  x <- unsafeRead marr idx
+  let !x' = f x
+  unsafeWrite marr idx x'
+
 {-# INLINE getElems #-}
 -- | Return a list of all the elements of a mutable array
 getElems :: (MArray a e m, Ix i) => a i e -> m [e]
@@ -933,6 +1112,70 @@
               | i' <- range (l',u')]
     return marr'
 
+-- | Strict accumulating left-associative fold.
+--
+-- @since 0.5.8.0
+foldlMArray' :: (MArray a e m, Ix i) => (b -> e -> b) -> b -> a i e -> m b
+foldlMArray' f = foldlMArrayM' (\z x -> pure (f z x))
+{-# INLINE foldlMArray' #-}
+
+-- | Strict accumulating right-associative fold.
+--
+-- @since 0.5.8.0
+foldrMArray' :: (MArray a e m, Ix i) => (e -> b -> b) -> b -> a i e -> m b
+foldrMArray' f = foldrMArrayM' (\x z -> pure (f x z))
+{-# INLINE foldrMArray' #-}
+
+-- | Strict accumulating left-associative monadic fold.
+--
+-- @since 0.5.8.0
+foldlMArrayM' :: (MArray a e m, Ix i) => (b -> e -> m b) -> b -> a i e -> m b
+foldlMArrayM' f z0 = \a -> do
+    !n <- getNumElements a
+    let go !z i | i >= n = pure z
+                | otherwise = do
+                    x <- unsafeRead a i
+                    z' <- f z x
+                    go z' (i+1)
+    go z0 0
+{-# INLINE foldlMArrayM' #-}
+
+-- | Strict accumulating right-associative monadic fold.
+--
+-- @since 0.5.8.0
+foldrMArrayM' :: (MArray a e m, Ix i) => (e -> b -> m b) -> b -> a i e -> m b
+foldrMArrayM' f z0 = \a -> do
+    !n <- getNumElements a
+    let go i !z | i < 0 = pure z
+                | otherwise = do
+                    x <- unsafeRead a i
+                    z' <- f x z
+                    go (i-1) z'
+    go (n-1) z0
+{-# INLINE foldrMArrayM' #-}
+
+-- | Map elements to monadic actions, sequence them left-to-right, and discard
+-- the results.
+--
+-- @since 0.5.8.0
+mapMArrayM_ :: (MArray a e m, Ix i) => (e -> m b) -> a i e -> m ()
+mapMArrayM_ f = \a -> do
+    !n <- getNumElements a
+    let go i | i >= n = pure ()
+             | otherwise = do
+                 x <- unsafeRead a i
+                 _ <- f x
+                 go (i+1)
+    go 0
+{-# INLINE mapMArrayM_ #-}
+
+-- | @forMArrayM_@ is 'mapMArrayM_' with its arguments flipped.
+--
+-- @since 0.5.8.0
+forMArrayM_ :: (MArray a e m, Ix i) => a i e -> (e -> m b) -> m ()
+forMArrayM_ = flip mapMArrayM_
+{-# INLINE forMArrayM_ #-}
+
 -----------------------------------------------------------------------------
 -- Polymorphic non-strict mutable arrays (ST monad)
 
@@ -979,7 +1222,6 @@
 -- don\'t use 'STUArray' if you require the non-strictness that
 -- 'STArray' provides.
 data STUArray s i e = STUArray !i !i !Int (MutableByteArray# s)
-                      deriving Typeable
 -- The "ST" parameter must be nominal for the safety of the ST trick.
 -- The other parameters have class constraints. See also #9220.
 type role STUArray nominal nominal nominal
@@ -1323,8 +1565,15 @@
 
 bOOL_SCALE, wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int#
 bOOL_SCALE n# =
-    -- + 7 to handle case where n is not divisible by 8
-    (n# +# 7#) `uncheckedIShiftRA#` 3#
+    -- Round the number of bits up to the next whole-word-aligned number
+    -- of bytes to avoid ghc#23132; the addition can signed-overflow but
+    -- that's OK because it will not unsigned-overflow and the logical
+    -- right-shift brings us back in-bounds
+#if SIZEOF_HSWORD == 4
+    ((n# +# 31#) `uncheckedIShiftRL#` 5#) `uncheckedIShiftL#` 2#
+#elif SIZEOF_HSWORD == 8
+    ((n# +# 63#) `uncheckedIShiftRL#` 6#) `uncheckedIShiftL#` 3#
+#endif
 wORD_SCALE   n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSWORD
 dOUBLE_SCALE n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSDOUBLE
 fLOAT_SCALE  n# = safe_scale scale# n# where !(I# scale#) = SIZEOF_HSFLOAT
@@ -1370,18 +1619,14 @@
   -- use the safe array creation function here.
   return (listArray (l,u) es)
 
-#if __GLASGOW_HASKELL__ >= 711
 freezeSTUArray :: STUArray s i e -> ST s (UArray i e)
-#else
-freezeSTUArray :: Ix i => STUArray s i e -> ST s (UArray i e)
-#endif
 freezeSTUArray (STUArray l u n marr#) = ST $ \s1# ->
-    case sizeofMutableByteArray# marr#  of { n# ->
-    case newByteArray# n# s1#           of { (# s2#, marr'# #) ->
+    case getSizeofMutableByteArray# marr# s1# of { (# s2#, n# #) ->
+    case newByteArray# n# s2#           of { (# s3#, marr'# #) ->
     case memcpy_freeze marr'# marr# (fromIntegral (I# n#)) of { IO m ->
-    case unsafeCoerce# m s2#            of { (# s3#, _ #) ->
-    case unsafeFreezeByteArray# marr'# s3# of { (# s4#, arr# #) ->
-    (# s4#, UArray l u n arr# #) }}}}}
+    case unsafeCoerce# m s3#            of { (# s4#, _ #) ->
+    case unsafeFreezeByteArray# marr'# s4# of { (# s5#, arr# #) ->
+    (# s5#, UArray l u n arr# #) }}}}}
 
 foreign import ccall unsafe "memcpy"
     memcpy_freeze :: MutableByteArray# s -> MutableByteArray# s -> CSize
@@ -1449,11 +1694,7 @@
               | i <- [0 .. n - 1]]
     return marr
 
-#if __GLASGOW_HASKELL__ >= 711
 thawSTUArray :: UArray i e -> ST s (STUArray s i e)
-#else
-thawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
-#endif
 thawSTUArray (UArray l u n arr#) = ST $ \s1# ->
     case sizeofByteArray# arr#          of { n# ->
     case newByteArray# n# s1#           of { (# s2#, marr# #) ->
@@ -1513,11 +1754,7 @@
 unsafeThaw = thaw
 
 {-# INLINE unsafeThawSTUArray #-}
-#if __GLASGOW_HASKELL__ >= 711
 unsafeThawSTUArray :: UArray i e -> ST s (STUArray s i e)
-#else
-unsafeThawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
-#endif
 unsafeThawSTUArray (UArray l u n marr#) =
     return (STUArray l u n (unsafeCoerce# marr#))
 
@@ -1527,11 +1764,7 @@
     #-}
 
 {-# INLINE unsafeThawIOArray #-}
-#if __GLASGOW_HASKELL__ >= 711
 unsafeThawIOArray :: Arr.Array ix e -> IO (IOArray ix e)
-#else
-unsafeThawIOArray :: Ix ix => Arr.Array ix e -> IO (IOArray ix e)
-#endif
 unsafeThawIOArray arr = stToIO $ do
     marr <- ArrST.unsafeThawSTArray arr
     return (IOArray marr)
@@ -1540,11 +1773,7 @@
 "unsafeThaw/IOArray"  unsafeThaw = unsafeThawIOArray
     #-}
 
-#if __GLASGOW_HASKELL__ >= 711
 thawIOArray :: Arr.Array ix e -> IO (IOArray ix e)
-#else
-thawIOArray :: Ix ix => Arr.Array ix e -> IO (IOArray ix e)
-#endif
 thawIOArray arr = stToIO $ do
     marr <- ArrST.thawSTArray arr
     return (IOArray marr)
@@ -1553,11 +1782,7 @@
 "thaw/IOArray"  thaw = thawIOArray
     #-}
 
-#if __GLASGOW_HASKELL__ >= 711
 freezeIOArray :: IOArray ix e -> IO (Arr.Array ix e)
-#else
-freezeIOArray :: Ix ix => IOArray ix e -> IO (Arr.Array ix e)
-#endif
 freezeIOArray (IOArray marr) = stToIO (ArrST.freezeSTArray marr)
 
 {-# RULES
@@ -1565,11 +1790,7 @@
     #-}
 
 {-# INLINE unsafeFreezeIOArray #-}
-#if __GLASGOW_HASKELL__ >= 711
 unsafeFreezeIOArray :: IOArray ix e -> IO (Arr.Array ix e)
-#else
-unsafeFreezeIOArray :: Ix ix => IOArray ix e -> IO (Arr.Array ix e)
-#endif
 unsafeFreezeIOArray (IOArray marr) = stToIO (ArrST.unsafeFreezeSTArray marr)
 
 {-# RULES
@@ -1582,3 +1803,13 @@
 
 castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
 castSTUArray (STUArray l u n marr#) = return (STUArray l u n marr#)
+
+--------------------------------------------------------------------------------
+
+-- Note [Inlining and fusion]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Many functions in this module are marked INLINE because they consume their
+-- input with `foldr`. By inlining them, it is possible that the `foldr` will
+-- meet a `build` from the call site, and beneficial fusion will take place.
+-- That is, they become "good consumers". See array issue #8 for data showing
+-- the perf improvement that comes with fusion.
diff --git a/Data/Array/IArray.hs b/Data/Array/IArray.hs
--- a/Data/Array/IArray.hs
+++ b/Data/Array/IArray.hs
@@ -29,13 +29,25 @@
     array,      -- :: (IArray a e, Ix i) => (i,i) -> [(i, e)] -> a i e
     listArray,  -- :: (IArray a e, Ix i) => (i,i) -> [e] -> a i e
     accumArray, -- :: (IArray a e, Ix i) => (e -> e' -> e) -> e -> (i,i) -> [(i, e')] -> a i e
+    genArray,   -- :: (IArray a e, Ix i) => (i,i) -> (i -> e) -> a i e
 
     -- * Accessing arrays
     (!),        -- :: (IArray a e, Ix i) => a i e -> i -> e
+    (!?),       -- :: (IArray a e, Ix i) => a i e -> i -> Maybe e
     bounds,     -- :: (HasBounds a, Ix i) => a i e -> (i,i)
     indices,    -- :: (HasBounds a, Ix i) => a i e -> [i]
     elems,      -- :: (IArray a e, Ix i) => a i e -> [e]
     assocs,     -- :: (IArray a e, Ix i) => a i e -> [(i, e)]
+
+    -- * Array folds
+    foldrArray,
+    foldlArray',
+    foldlArray,
+    foldrArray',
+    traverseArray_,
+    forArray_,
+    foldlArrayM',
+    foldrArrayM',
 
     -- * Incremental array updates
     (//),       -- :: (IArray a e, Ix i) => a i e -> [(i, e)] -> a i e
diff --git a/Data/Array/IO.hs b/Data/Array/IO.hs
--- a/Data/Array/IO.hs
+++ b/Data/Array/IO.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE MagicHash, UnliftedFFITypes #-}
+{-# LANGUAGE MagicHash, Trustworthy, UnliftedFFITypes #-}
 
 -----------------------------------------------------------------------------
 -- |
diff --git a/Data/Array/IO/Internals.hs b/Data/Array/IO/Internals.hs
--- a/Data/Array/IO/Internals.hs
+++ b/Data/Array/IO/Internals.hs
@@ -1,8 +1,10 @@
-{-# LANGUAGE DeriveDataTypeable, FlexibleInstances, MultiParamTypeClasses,
-             CPP #-}
-{-# LANGUAGE RoleAnnotations #-}
+{-# LANGUAGE
+    FlexibleInstances
+  , MultiParamTypeClasses
+  , RoleAnnotations
+ #-}
 
-{-# OPTIONS_HADDOCK hide #-}
+{-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.IO.Internal
@@ -15,6 +17,18 @@
 --
 -- Mutable boxed and unboxed arrays in the IO monad.
 --
+-- = WARNING
+--
+-- This module is considered __internal__.
+--
+-- The Package Versioning Policy __does not apply__.
+--
+-- The contents of this module may change __in any way whatsoever__
+-- and __without any warning__ between minor versions of this package.
+--
+-- Authors importing this module are expected to track development
+-- closely.
+--
 -----------------------------------------------------------------------------
 
 module Data.Array.IO.Internals (
@@ -27,15 +41,11 @@
 
 import Data.Int
 import Data.Word
-import Data.Typeable
 
 import Control.Monad.ST         ( RealWorld, stToIO )
 import Foreign.Ptr              ( Ptr, FunPtr )
 import Foreign.StablePtr        ( StablePtr )
 
-#if __GLASGOW_HASKELL__ < 711
-import Data.Ix
-#endif
 import Data.Array.Base
 
 import GHC.IOArray (IOArray(..))
@@ -52,7 +62,6 @@
 --    are supported: see "Data.Array.MArray" for a list of instances.
 --
 newtype IOUArray i e = IOUArray (STUArray RealWorld i e)
-                       deriving Typeable
 -- Both parameters have class-based invariants. See also #9220.
 type role IOUArray nominal nominal
 
@@ -374,11 +383,7 @@
     return (IOUArray marr')
 
 {-# INLINE unsafeThawIOUArray #-}
-#if __GLASGOW_HASKELL__ >= 711
 unsafeThawIOUArray :: UArray ix e -> IO (IOUArray ix e)
-#else
-unsafeThawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
-#endif
 unsafeThawIOUArray arr = stToIO $ do
     marr <- unsafeThawSTUArray arr
     return (IOUArray marr)
@@ -387,11 +392,7 @@
 "unsafeThaw/IOUArray" unsafeThaw = unsafeThawIOUArray
     #-}
 
-#if __GLASGOW_HASKELL__ >= 711
 thawIOUArray :: UArray ix e -> IO (IOUArray ix e)
-#else
-thawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
-#endif
 thawIOUArray arr = stToIO $ do
     marr <- thawSTUArray arr
     return (IOUArray marr)
@@ -401,22 +402,14 @@
     #-}
 
 {-# INLINE unsafeFreezeIOUArray #-}
-#if __GLASGOW_HASKELL__ >= 711
 unsafeFreezeIOUArray :: IOUArray ix e -> IO (UArray ix e)
-#else
-unsafeFreezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
-#endif
 unsafeFreezeIOUArray (IOUArray marr) = stToIO (unsafeFreezeSTUArray marr)
 
 {-# RULES
 "unsafeFreeze/IOUArray" unsafeFreeze = unsafeFreezeIOUArray
     #-}
 
-#if __GLASGOW_HASKELL__ >= 711
 freezeIOUArray :: IOUArray ix e -> IO (UArray ix e)
-#else
-freezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
-#endif
 freezeIOUArray (IOUArray marr) = stToIO (freezeSTUArray marr)
 
 {-# RULES
diff --git a/Data/Array/IO/Safe.hs b/Data/Array/IO/Safe.hs
--- a/Data/Array/IO/Safe.hs
+++ b/Data/Array/IO/Safe.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE Safe #-}
 
 -----------------------------------------------------------------------------
 -- |
diff --git a/Data/Array/MArray.hs b/Data/Array/MArray.hs
--- a/Data/Array/MArray.hs
+++ b/Data/Array/MArray.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, Trustworthy #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -27,10 +27,21 @@
     newArray,     -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
     newArray_,    -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
     newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+    newGenArray,  -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
 
     -- * Reading and writing mutable arrays
     readArray,    -- :: (MArray a e m, Ix i) => a i e -> i -> m e
     writeArray,   -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
+    modifyArray,
+    modifyArray',
+
+    -- * Array folds
+    foldlMArray',
+    foldrMArray',
+    mapMArrayM_,
+    forMArrayM_,
+    foldlMArrayM',
+    foldrMArrayM',
 
     -- * Derived arrays
     mapArray,     -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
diff --git a/Data/Array/MArray/Safe.hs b/Data/Array/MArray/Safe.hs
--- a/Data/Array/MArray/Safe.hs
+++ b/Data/Array/MArray/Safe.hs
@@ -29,10 +29,19 @@
     newArray,     -- :: (MArray a e m, Ix i) => (i,i) -> e -> m (a i e)
     newArray_,    -- :: (MArray a e m, Ix i) => (i,i) -> m (a i e)
     newListArray, -- :: (MArray a e m, Ix i) => (i,i) -> [e] -> m (a i e)
+    newGenArray,  -- :: (MArray a e m, Ix i) => (i,i) -> (i -> m e) -> m (a i e)
 
     -- * Reading and writing mutable arrays
     readArray,    -- :: (MArray a e m, Ix i) => a i e -> i -> m e
     writeArray,   -- :: (MArray a e m, Ix i) => a i e -> i -> e -> m ()
+
+    -- * Array folds
+    foldlMArray',
+    foldrMArray',
+    mapMArrayM_,
+    forMArrayM_,
+    foldlMArrayM',
+    foldrMArrayM',
 
     -- * Derived arrays
     mapArray,     -- :: (MArray a e' m, MArray a e m, Ix i) => (e' -> e) -> a i e' -> m (a i e)
diff --git a/Data/Array/ST.hs b/Data/Array/ST.hs
--- a/Data/Array/ST.hs
+++ b/Data/Array/ST.hs
@@ -1,5 +1,4 @@
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE RankNTypes, Trustworthy #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.ST
@@ -38,11 +37,7 @@
 -- the array before returning it - it uses 'unsafeFreeze' internally, but
 -- this wrapper is a safe interface to that function.
 --
-#if __GLASGOW_HASKELL__ >= 711
 runSTArray :: (forall s . ST s (STArray s i e)) -> Array i e
-#else
-runSTArray :: Ix i => (forall s . ST s (STArray s i e)) -> Array i e
-#endif
 runSTArray st = runST (st >>= unsafeFreezeSTArray)
 
 -- | A safe way to create and work with an unboxed mutable array before
@@ -51,11 +46,7 @@
 -- 'unsafeFreeze' internally, but this wrapper is a safe interface to
 -- that function.
 --
-#if __GLASGOW_HASKELL__ >= 711
 runSTUArray :: (forall s . ST s (STUArray s i e)) -> UArray i e
-#else
-runSTUArray :: Ix i => (forall s . ST s (STUArray s i e)) -> UArray i e
-#endif
 runSTUArray st = runST (st >>= unsafeFreezeSTUArray)
 
 
diff --git a/Data/Array/ST/Safe.hs b/Data/Array/ST/Safe.hs
--- a/Data/Array/ST/Safe.hs
+++ b/Data/Array/ST/Safe.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE Safe #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.ST.Safe
diff --git a/Data/Array/Storable.hs b/Data/Array/Storable.hs
--- a/Data/Array/Storable.hs
+++ b/Data/Array/Storable.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE Trustworthy #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.Storable
diff --git a/Data/Array/Storable/Internals.hs b/Data/Array/Storable/Internals.hs
--- a/Data/Array/Storable/Internals.hs
+++ b/Data/Array/Storable/Internals.hs
@@ -1,5 +1,5 @@
 {-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RoleAnnotations #-}
-{-# OPTIONS_HADDOCK hide #-}
+{-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.Storable.Internals
@@ -13,6 +13,18 @@
 -- Actual implementation of "Data.Array.Storable".
 --
 -- @since 0.4.0.0
+--
+-- = WARNING
+--
+-- This module is considered __internal__.
+--
+-- The Package Versioning Policy __does not apply__.
+--
+-- The contents of this module may change __in any way whatsoever__
+-- and __without any warning__ between minor versions of this package.
+--
+-- Authors importing this module are expected to track development
+-- closely.
 -----------------------------------------------------------------------------
 
 module Data.Array.Storable.Internals (
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -81,3 +81,4 @@
   be a definition of the Haskell 98 Foreign Function Interface.
 
 -----------------------------------------------------------------------------
+
diff --git a/Setup.hs b/Setup.hs
--- a/Setup.hs
+++ b/Setup.hs
@@ -4,3 +4,4 @@
 
 main :: IO ()
 main = defaultMain
+
diff --git a/array.cabal b/array.cabal
--- a/array.cabal
+++ b/array.cabal
@@ -1,15 +1,15 @@
+cabal-version: >= 1.10
 name:          array
-version:       0.5.2.0
+version:       0.5.8.0
+
 -- NOTE: Don't forget to update ./changelog.md
 license:       BSD3
 license-file:  LICENSE
 maintainer:    libraries@haskell.org
-bug-reports:   http://ghc.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29&keywords=array
+bug-reports:   https://gitlab.haskell.org/ghc/packages/array/issues
 synopsis:      Mutable and immutable arrays
 category:      Data Structures
 build-type:    Simple
-cabal-version: >=1.10
-tested-with:   GHC==8.2.1, GHC==8.0.2, GHC==7.10.3, GHC==7.8.4
 description:
     In addition to providing the "Data.Array" module
     <http://www.haskell.org/onlinereport/haskell2010/haskellch14.html as specified in the Haskell 2010 Language Report>,
@@ -21,14 +21,13 @@
 
 source-repository head
   type:     git
-  location: http://git.haskell.org/packages/array.git
+  location: http://gitlab.haskell.org/ghc/packages/array.git
 
 library
   default-language: Haskell2010
   other-extensions:
       BangPatterns,
       CPP,
-      DeriveDataTypeable,
       FlexibleContexts,
       FlexibleInstances,
       MagicHash,
@@ -37,7 +36,7 @@
       Trustworthy,
       UnboxedTuples,
       UnliftedFFITypes
-  build-depends: base >= 4.7 && < 4.11
+  build-depends: base >= 4.9 && < 4.21
   ghc-options: -Wall
   exposed-modules:
       Data.Array
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,61 @@
 # Changelog for [`array` package](http://hackage.haskell.org/package/array)
 
+## 0.5.8.0 *Aug 2024*
+
+### Added
+
+  * Folds for arrays: `foldrArray`, `foldlArray'`, `foldlArray`, `foldrArray'`,
+    `traverseArray_`, `forArray_`, `foldlArrayM'`, `foldrArrayM'`.
+  * Folds for mutable arrays: `foldlMArray'`, `foldrMArray'`, `mapMArrayM_`,
+    `forMArrayM_`, `foldlMArrayM'`, `foldrMArrayM'`.
+
+### Fixed
+
+  * Fix a build error that the package can't be buildable before `base-4.14`.
+
+## 0.5.7.0  *April 2024*
+
+### Changed
+
+  * `MArray` now has a `MINIMAL` pragma
+  * Optimisation of `newListArray` and `newGenArray`
+
+## 0.5.6.0  *July 2023*
+
+### Changed
+
+  * `listArray` and `newListArray` are now good consumers of the input list
+  * Bump base bound to `<4.20`
+
+### Added
+
+  * Add the `genArray` and `newGenArray` function
+  * Add `Data.Array.MArray.modifyArray` and `Data.Array.MArray.modifyArray'`
+    These are also exposed from `Data.Array.IO`, `Data.Array.ST`, and
+    `Data.Array.Storable`.
+  * Add `Data.Array.IArray.(!?)`
+
+### Fixed
+
+  * Array docs regarding constructing arrays
+  * Update note [Inlining and fusion]
+  * Unboxed Bool arrays no longer cause spurious alarms
+    when used with `-fcheck-prim-bounds`
+  * Replace Haddock hide pragma with not-home to make the Haddocks more readable
+
+## 0.5.5.0  *February 2022*
+
+  * Compatibility with GHC's new JavaScript backend.
+
+## 0.5.4.0  *July 2019*
+
+  * Add a `Read` instance for `UArray`
+
+## 0.5.3.0  *Oct 2018*
+
+  * Bundled with GHC 8.6.2
+  * Drop support for GHC versions prior to GHC 8.0
+
 ## 0.5.2.0  *Jul 2017*
 
   * Bundled with GHC 8.2.1
