diff --git a/Data/Array.hs b/Data/Array.hs
--- a/Data/Array.hs
+++ b/Data/Array.hs
@@ -54,19 +54,7 @@
   ) where
 
 import Data.Ix
-import Data.Typeable ()
-
-#ifdef __GLASGOW_HASKELL__
 import GHC.Arr  -- Most of the hard work is done here
-#endif
-
-#ifdef __HUGS__
-import Hugs.Array
-#endif
-
-#ifdef __NHC__
-import Array    -- Haskell'98 arrays
-#endif
 
 {- $intro
 Haskell provides indexable /arrays/, which may be thought of as functions
diff --git a/Data/Array/Base.hs b/Data/Array/Base.hs
--- a/Data/Array/Base.hs
+++ b/Data/Array/Base.hs
@@ -1,11 +1,16 @@
-{-# OPTIONS_GHC -XBangPatterns -fno-warn-unused-imports #-}
-{-# OPTIONS_HADDOCK hide #-}
--- XXX With a GHC 6.9 we get a spurious
--- Data/Array/Base.hs:26:0:
---     Warning: Module `Data.Ix' is imported, but nothing from it is used,
---                except perhaps instances visible in `Data.Ix'
---              To suppress this warning, use: import Data.Ix()
--- The -fno-warn-unused-imports works around that bug
+{-# LANGUAGE
+    BangPatterns
+  , CPP
+  , RankNTypes
+  , MagicHash
+  , UnboxedTuples
+  , MultiParamTypeClasses
+  , FlexibleInstances
+  , FlexibleContexts
+  , UnliftedFFITypes
+  , RoleAnnotations
+ #-}
+{-# OPTIONS_HADDOCK not-home #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -20,61 +25,47 @@
 -- 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.
 -----------------------------------------------------------------------------
 
--- #hide
 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
 
-#ifdef __GLASGOW_HASKELL__
 import Data.Char
 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
-import GHC.Word         ( Word(..) )
-import GHC.Ptr          ( Ptr(..), FunPtr(..), nullPtr, nullFunPtr )
-import GHC.Float        ( Float(..), Double(..) )
+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(..) )
-#if __GLASGOW_HASKELL__ >= 611
-import GHC.IO           ( IO(..), stToIO )
+import GHC.IO           ( stToIO )
 import GHC.IOArray      ( IOArray(..),
                           newIOArray, unsafeReadIOArray, unsafeWriteIOArray )
-#else
-import GHC.IOBase       ( IO(..), IOArray(..), stToIO,
-                          newIOArray, unsafeReadIOArray, unsafeWriteIOArray )
-#endif
-#else
-import Data.Int
-import Data.Word
-import Foreign.Ptr
-#endif
-
-#ifdef __HUGS__
-import Data.Bits
-import Foreign.Storable
-import qualified Hugs.Array as Arr
-import qualified Hugs.ST as ArrST
-import Hugs.Array ( unsafeIndex )
-import Hugs.IOArray
-import Hugs.ST ( STArray, ST(..), runST )
-import Hugs.ByteArray
-#endif
-
-import Data.Typeable
-#include "Typeable.h"
+import Text.Read.Lex    ( Lexeme(Ident) )
+import Text.ParserCombinators.ReadPrec ( prec, ReadPrec, step )
 
-#ifdef __GLASGOW_HASKELL__
 #include "MachDeps.h"
-#endif
 
 -----------------------------------------------------------------------------
 -- Class of immutable arrays
@@ -203,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
@@ -252,7 +234,6 @@
 -- calls seem to be floated out, then floated back into the middle
 -- of listUArrayST, so I was not able to do this.
 
-#ifdef __GLASGOW_HASKELL__
 type ListUArray e = forall i . Ix i => (i,i) -> [e] -> UArray i e
 
 {-# RULES
@@ -291,14 +272,25 @@
 "listArray/UArray/Word64"    listArray
    = (\lu es -> runST (listUArrayST lu es >>= unsafeFreezeSTUArray)) :: ListUArray Word64
     #-}
-#endif
 
 {-# 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]
@@ -308,8 +300,7 @@
 -- | Returns a list of all the elements of an array, in the same order
 -- as their indices.
 elems :: (IArray a e, Ix i) => a i e -> [e]
-elems arr = case bounds arr of
-    (_l, _u) -> [unsafeAt arr i | i <- [0 .. numElements arr - 1]]
+elems arr = [unsafeAt arr i | i <- [0 .. numElements arr - 1]]
 
 {-# INLINE assocs #-}
 -- | Returns the contents of an array as a list of associations.
@@ -395,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
 
@@ -433,14 +512,9 @@
 -- get the benefits of unboxed arrays (don\'t forget to import
 -- "Data.Array.Unboxed" instead of "Data.Array").
 --
-#ifdef __GLASGOW_HASKELL__
 data UArray i e = UArray !i !i !Int ByteArray#
-#endif
-#ifdef __HUGS__
-data UArray i e = UArray !i !i !Int !ByteArray
-#endif
-
-INSTANCE_TYPEABLE2(UArray,uArrayTc,"UArray")
+-- There are class-based invariants on both parameters. See also #9220.
+type role UArray nominal nominal
 
 {-# INLINE unsafeArrayUArray #-}
 unsafeArrayUArray :: (MArray (STUArray s) e (ST s), Ix i)
@@ -452,15 +526,9 @@
 
 {-# INLINE unsafeFreezeSTUArray #-}
 unsafeFreezeSTUArray :: STUArray s i e -> ST s (UArray i e)
-#if __GLASGOW_HASKELL__
 unsafeFreezeSTUArray (STUArray l u n marr#) = ST $ \s1# ->
     case unsafeFreezeByteArray# marr# s1# of { (# s2#, arr# #) ->
     (# s2#, UArray l u n arr# #) }
-#elif __HUGS__
-unsafeFreezeSTUArray (STUArray l u n marr) = do
-    arr <- unsafeFreezeMutableByteArray marr
-    return (UArray l u n arr)
-#endif
 
 {-# INLINE unsafeReplaceUArray #-}
 unsafeReplaceUArray :: (MArray (STUArray s) e (ST s), Ix i)
@@ -517,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) =>
@@ -526,20 +594,27 @@
 
 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
 
-#ifdef __HUGS__
-unsafeAtBArray :: Storable e => UArray i e -> Int -> e
-unsafeAtBArray (UArray _ _ _ arr) = readByteArray arr
-#endif
-
 instance IArray UArray Bool where
     {-# INLINE bounds #-}
     bounds (UArray l u _ _) = (l,u)
@@ -547,16 +622,11 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies False)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
-    unsafeAt (UArray _ _ _ arr#) (I# i#) =
-        (indexWordArray# arr# (bOOL_INDEX i#) `and#` bOOL_BIT i#)
-        `neWord#` int2Word# 0#
-#endif
-#ifdef __HUGS__
-    unsafeAt (UArray _ _ _ arr) i =
-        testBit (readByteArray arr (bOOL_INDEX i)::BitSet) (bOOL_SUBINDEX i)
-#endif
+    unsafeAt (UArray _ _ _ arr#) (I# i#) = isTrue#
+        ((indexWordArray# arr# (bOOL_INDEX i#) `and#` bOOL_BIT i#)
+        `neWord#` int2Word# 0#)
+
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -572,12 +642,7 @@
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies '\0')
     {-# INLINE unsafeAt #-}
-#ifdef __GLASGOW_HASKELL__
     unsafeAt (UArray _ _ _ arr#) (I# i#) = C# (indexWideCharArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -592,13 +657,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = I# (indexIntArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -613,13 +673,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = W# (indexWordArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -635,12 +690,7 @@
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies nullPtr)
     {-# INLINE unsafeAt #-}
-#ifdef __GLASGOW_HASKELL__
     unsafeAt (UArray _ _ _ arr#) (I# i#) = Ptr (indexAddrArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -655,13 +705,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies nullFunPtr)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = FunPtr (indexAddrArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -676,13 +721,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = F# (indexFloatArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -697,13 +737,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = D# (indexDoubleArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -718,13 +753,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies nullStablePtr)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = StablePtr (indexStablePtrArray# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -734,12 +764,7 @@
 
 -- bogus StablePtr value for initialising a UArray of StablePtr.
 nullStablePtr :: StablePtr a
-#ifdef __GLASGOW_HASKELL__
-nullStablePtr = StablePtr (unsafeCoerce# 0#)
-#endif
-#ifdef __HUGS__
-nullStablePtr = castPtrToStablePtr nullPtr
-#endif
+nullStablePtr = StablePtr (unsafeCoerce# nullAddr#)
 
 instance IArray UArray Int8 where
     {-# INLINE bounds #-}
@@ -748,13 +773,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = I8# (indexInt8Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -769,13 +789,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = I16# (indexInt16Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -790,13 +805,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = I32# (indexInt32Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -811,13 +821,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = I64# (indexInt64Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -832,13 +837,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = W8# (indexWord8Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -853,13 +853,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = W16# (indexWord16Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -874,13 +869,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = W32# (indexWord32Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -895,13 +885,8 @@
     numElements (UArray _ _ n _) = n
     {-# INLINE unsafeArray #-}
     unsafeArray lu ies = runST (unsafeArrayUArray lu ies 0)
-#ifdef __GLASGOW_HASKELL__
     {-# INLINE unsafeAt #-}
     unsafeAt (UArray _ _ _ arr#) (I# i#) = W64# (indexWord64Array# arr# i#)
-#endif
-#ifdef __HUGS__
-    unsafeAt = unsafeAtBArray
-#endif
     {-# INLINE unsafeReplace #-}
     unsafeReplace arr ies = runST (unsafeReplaceUArray arr ies)
     {-# INLINE unsafeAccum #-}
@@ -918,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
 
@@ -937,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
@@ -991,35 +982,52 @@
     -- 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
-#if defined(__HUGS__)
-    getBounds   = return . boundsIOArray
-    getNumElements = return . getNumElementsIOArray
-#elif defined(__GLASGOW_HASKELL__)
     {-# INLINE getBounds #-}
     getBounds (IOArray marr) = stToIO $ getBounds marr
     {-# INLINE getNumElements #-}
     getNumElements (IOArray marr) = stToIO $ getNumElements marr
-#endif
     newArray    = newIOArray
     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
@@ -1036,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]
@@ -1079,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)
 
@@ -1106,10 +1203,6 @@
     {-# INLINE unsafeWrite #-}
     unsafeWrite arr i e = strictToLazyST (ArrST.unsafeWriteSTArray arr i e)
 
-#ifdef __HUGS__
-INSTANCE_TYPEABLE3(STArray,sTArrayTc,"STArray")
-#endif
-
 -----------------------------------------------------------------------------
 -- Flat unboxed mutable arrays (ST monad)
 
@@ -1128,26 +1221,15 @@
 -- element type.  However, 'STUArray' is strict in its elements - so
 -- don\'t use 'STUArray' if you require the non-strictness that
 -- 'STArray' provides.
-#ifdef __GLASGOW_HASKELL__
 data STUArray s i e = STUArray !i !i !Int (MutableByteArray# s)
-#endif
-#ifdef __HUGS__
-data STUArray s i e = STUArray !i !i !Int !(MutableByteArray s)
-#endif
-
-INSTANCE_TYPEABLE3(STUArray,stUArrayTc,"STUArray")
+-- 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
 
-#ifdef __GLASGOW_HASKELL__
 instance Eq (STUArray s i e) where
     STUArray _ _ _ arr1# == STUArray _ _ _ arr2# =
-        sameMutableByteArray# arr1# arr2#
-#endif
-#ifdef __HUGS__
-instance Eq (STUArray s i e) where
-    STUArray _ _ _ arr1 == STUArray _ _ _ arr2 = arr1 == arr2
-#endif
+        isTrue# (sameMutableByteArray# arr1# arr2#)
 
-#ifdef __GLASGOW_HASKELL__
 {-# INLINE unsafeNewArraySTUArray_ #-}
 unsafeNewArraySTUArray_ :: Ix i
                         => (i,i) -> (Int# -> Int#) -> ST s (STUArray s i e)
@@ -1166,17 +1248,13 @@
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE newArray #-}
     newArray (l,u) initialValue = ST $ \s1# ->
-        case safeRangeSize (l,u)            of { n@(I# n#) ->
-        case newByteArray# (bOOL_SCALE n#) s1# of { (# s2#, marr# #) ->
-        case bOOL_WORD_SCALE n#         of { n'# ->
-        let loop i# s3# | i# ==# n'# = s3#
-                        | otherwise  =
-                case writeWordArray# marr# i# e# s3# of { s4# ->
-                loop (i# +# 1#) s4# } in
-        case loop 0# s2#                of { s3# ->
+        case safeRangeSize (l,u)                   of { n@(I# n#) ->
+        case bOOL_SCALE n#                         of { nbytes# ->
+        case newByteArray# nbytes# s1#             of { (# s2#, marr# #) ->
+        case setByteArray# marr# 0# nbytes# e# s2# of { s3# ->
         (# s3#, STUArray l u n marr# #) }}}}
       where
-        !(W# e#) = if initialValue then maxBound else 0
+        !(I# e#) = if initialValue then 0xff else 0x0
     {-# INLINE unsafeNewArray_ #-}
     unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) bOOL_SCALE
     {-# INLINE newArray_ #-}
@@ -1184,7 +1262,7 @@
     {-# INLINE unsafeRead #-}
     unsafeRead (STUArray _ _ _ marr#) (I# i#) = ST $ \s1# ->
         case readWordArray# marr# (bOOL_INDEX i#) s1# of { (# s2#, e# #) ->
-        (# s2#, (e# `and#` bOOL_BIT i#) `neWord#` int2Word# 0# #) }
+        (# s2#, isTrue# ((e# `and#` bOOL_BIT i#) `neWord#` int2Word# 0#) :: Bool #) }
     {-# INLINE unsafeWrite #-}
     unsafeWrite (STUArray _ _ _ marr#) (I# i#) e = ST $ \s1# ->
         case bOOL_INDEX i#              of { j# ->
@@ -1200,7 +1278,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 4#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 4#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds (chr 0)
     {-# INLINE unsafeRead #-}
@@ -1362,7 +1440,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 2#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 2#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1380,7 +1458,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 4#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 4#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1398,7 +1476,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 8#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 8#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1434,7 +1512,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 2#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 2#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1452,7 +1530,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 4#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 4#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1470,7 +1548,7 @@
     {-# INLINE getNumElements #-}
     getNumElements (STUArray _ _ n _) = return n
     {-# INLINE unsafeNewArray_ #-}
-    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (*# 8#)
+    unsafeNewArray_ (l,u) = unsafeNewArraySTUArray_ (l,u) (safe_scale 8#)
     {-# INLINE newArray_ #-}
     newArray_ arrBounds = newArray arrBounds 0
     {-# INLINE unsafeRead #-}
@@ -1485,16 +1563,33 @@
 -----------------------------------------------------------------------------
 -- Translation between elements and bytes
 
-bOOL_SCALE, bOOL_WORD_SCALE,
-  wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int#
-bOOL_SCALE n# = (n# +# last#) `uncheckedIShiftRA#` 3#
-  where !(I# last#) = SIZEOF_HSWORD * 8 - 1
-bOOL_WORD_SCALE n# = bOOL_INDEX (n# +# last#)
-  where !(I# last#) = SIZEOF_HSWORD * 8 - 1
-wORD_SCALE   n# = scale# *# n# where !(I# scale#) = SIZEOF_HSWORD
-dOUBLE_SCALE n# = scale# *# n# where !(I# scale#) = SIZEOF_HSDOUBLE
-fLOAT_SCALE  n# = scale# *# n# where !(I# scale#) = SIZEOF_HSFLOAT
+bOOL_SCALE, wORD_SCALE, dOUBLE_SCALE, fLOAT_SCALE :: Int# -> Int#
+bOOL_SCALE n# =
+    -- 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
 
+safe_scale :: Int# -> Int# -> Int#
+safe_scale scale# n#
+  | not overflow = res#
+  | otherwise    = error $ "Data.Array.Base.safe_scale: Overflow; scale: "
+    ++ show (I# scale#) ++ ", n: " ++ show (I# n#)
+  where
+    !res# = scale# *# n#
+    !overflow = isTrue# (maxN# `divInt#` scale# <# n#)
+    !(I# maxN#) = maxBound
+{-# INLINE safe_scale #-}
+
+-- | The index of the word which the given @Bool@ array elements falls within.
 bOOL_INDEX :: Int# -> Int#
 #if SIZEOF_HSWORD == 4
 bOOL_INDEX i# = i# `uncheckedIShiftRA#` 5#
@@ -1507,192 +1602,7 @@
     where !(W# mask#) = SIZEOF_HSWORD * 8 - 1
 bOOL_NOT_BIT n# = bOOL_BIT n# `xor#` mb#
     where !(W# mb#) = maxBound
-#endif /* __GLASGOW_HASKELL__ */
 
-#ifdef __HUGS__
-newMBArray_ :: (Ix i, Storable e) => (i,i) -> ST s (STUArray s i e)
-newMBArray_ = makeArray undefined
-  where
-    makeArray :: (Ix i, Storable e) => e -> (i,i) -> ST s (STUArray s i e)
-    makeArray dummy (l,u) = do
-        let n = safeRangeSize (l,u)
-        marr <- newMutableByteArray (n * sizeOf dummy)
-        return (STUArray l u n marr)
-
-unsafeReadMBArray :: Storable e => STUArray s i e -> Int -> ST s e
-unsafeReadMBArray (STUArray _ _ _ marr) = readMutableByteArray marr
-
-unsafeWriteMBArray :: Storable e => STUArray s i e -> Int -> e -> ST s ()
-unsafeWriteMBArray (STUArray _ _ _ marr) = writeMutableByteArray marr
-
-getBoundsMBArray :: Storable e => STUArray s i e -> ST s (i, i)
-getBoundsMBArray (STUArray l u _ _) = return (l,u)
-
-getNumElementsMBArray :: Storable e => STUArray s i e -> ST s Int
-getNumElementsMBArray (STUArray _ _ n _) = return n
-
-instance MArray (STUArray s) Bool (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ (l,u) = do
-        let n = rangeSize (l,u)
-        marr <- newMutableByteArray (bOOL_SCALE n)
-        return (STUArray l u n marr)
-    newArray_ bounds = unsafeNewArray_ bounds
-    unsafeRead (STUArray _ _ _ marr) i = do
-        let ix = bOOL_INDEX i
-            bit = bOOL_SUBINDEX i
-        w <- readMutableByteArray marr ix
-        return (testBit (w::BitSet) bit)
-    unsafeWrite (STUArray _ _ _ marr) i e = do
-        let ix = bOOL_INDEX i
-            bit = bOOL_SUBINDEX i
-        w <- readMutableByteArray marr ix
-        writeMutableByteArray marr ix
-            (if e then setBit (w::BitSet) bit else clearBit w bit)
-
-instance MArray (STUArray s) Char (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Int (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Word (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) (Ptr a) (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) (FunPtr a) (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Float (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Double (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) (StablePtr a) (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Int8 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Int16 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Int32 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Int64 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Word8 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Word16 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Word32 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-instance MArray (STUArray s) Word64 (ST s) where
-    getBounds = getBoundsMBArray
-    getNumElements = getNumElementsMBArray
-    unsafeNewArray_ = newMBArray_
-    newArray_  = unsafeNewArray_
-    unsafeRead = unsafeReadMBArray
-    unsafeWrite = unsafeWriteMBArray
-
-type BitSet = Word8
-
-bitSetSize = bitSize (0::BitSet)
-
-bOOL_SCALE :: Int -> Int
-bOOL_SCALE n = (n + bitSetSize - 1) `div` bitSetSize
-
-bOOL_INDEX :: Int -> Int
-bOOL_INDEX i = i `div` bitSetSize
-
-bOOL_SUBINDEX :: Int -> Int
-bOOL_SUBINDEX i = i `mod` bitSetSize
-#endif /* __HUGS__ */
-
 -----------------------------------------------------------------------------
 -- Freezing
 
@@ -1709,15 +1619,14 @@
   -- use the safe array creation function here.
   return (listArray (l,u) es)
 
-#ifdef __GLASGOW_HASKELL__
-freezeSTUArray :: Ix i => STUArray s i e -> ST s (UArray i e)
+freezeSTUArray :: STUArray s i e -> ST s (UArray i e)
 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
@@ -1727,7 +1636,6 @@
 "freeze/STArray"  freeze = ArrST.freezeSTArray
 "freeze/STUArray" freeze = freezeSTUArray
     #-}
-#endif /* __GLASGOW_HASKELL__ */
 
 -- In-place conversion of mutable arrays to immutable ones places
 -- a proof obligation on the user: no other parts of your code can
@@ -1786,8 +1694,7 @@
               | i <- [0 .. n - 1]]
     return marr
 
-thawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
-#if __GLASGOW_HASKELL__
+thawSTUArray :: UArray i e -> ST s (STUArray s i e)
 thawSTUArray (UArray l u n arr#) = ST $ \s1# ->
     case sizeofByteArray# arr#          of { n# ->
     case newByteArray# n# s1#           of { (# s2#, marr# #) ->
@@ -1803,11 +1710,6 @@
 "thaw/STArray"  thaw = ArrST.thawSTArray
 "thaw/STUArray" thaw = thawSTUArray
     #-}
-#elif __HUGS__
-thawSTUArray (UArray l u n arr) = do
-    marr <- thawByteArray arr
-    return (STUArray l u n marr)
-#endif
 
 -- In-place conversion of immutable arrays to mutable ones places
 -- a proof obligation on the user: no other parts of your code can
@@ -1851,9 +1753,8 @@
 unsafeThaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
 unsafeThaw = thaw
 
-#ifdef __GLASGOW_HASKELL__
 {-# INLINE unsafeThawSTUArray #-}
-unsafeThawSTUArray :: Ix i => UArray i e -> ST s (STUArray s i e)
+unsafeThawSTUArray :: UArray i e -> ST s (STUArray s i e)
 unsafeThawSTUArray (UArray l u n marr#) =
     return (STUArray l u n (unsafeCoerce# marr#))
 
@@ -1863,7 +1764,7 @@
     #-}
 
 {-# INLINE unsafeThawIOArray #-}
-unsafeThawIOArray :: Ix ix => Arr.Array ix e -> IO (IOArray ix e)
+unsafeThawIOArray :: Arr.Array ix e -> IO (IOArray ix e)
 unsafeThawIOArray arr = stToIO $ do
     marr <- ArrST.unsafeThawSTArray arr
     return (IOArray marr)
@@ -1872,7 +1773,7 @@
 "unsafeThaw/IOArray"  unsafeThaw = unsafeThawIOArray
     #-}
 
-thawIOArray :: Ix ix => Arr.Array ix e -> IO (IOArray ix e)
+thawIOArray :: Arr.Array ix e -> IO (IOArray ix e)
 thawIOArray arr = stToIO $ do
     marr <- ArrST.thawSTArray arr
     return (IOArray marr)
@@ -1881,7 +1782,7 @@
 "thaw/IOArray"  thaw = thawIOArray
     #-}
 
-freezeIOArray :: Ix ix => IOArray ix e -> IO (Arr.Array ix e)
+freezeIOArray :: IOArray ix e -> IO (Arr.Array ix e)
 freezeIOArray (IOArray marr) = stToIO (ArrST.freezeSTArray marr)
 
 {-# RULES
@@ -1889,22 +1790,26 @@
     #-}
 
 {-# INLINE unsafeFreezeIOArray #-}
-unsafeFreezeIOArray :: Ix ix => IOArray ix e -> IO (Arr.Array ix e)
+unsafeFreezeIOArray :: IOArray ix e -> IO (Arr.Array ix e)
 unsafeFreezeIOArray (IOArray marr) = stToIO (ArrST.unsafeFreezeSTArray marr)
 
 {-# RULES
 "unsafeFreeze/IOArray"  unsafeFreeze = unsafeFreezeIOArray
     #-}
-#endif /* __GLASGOW_HASKELL__ */
 
 -- | Casts an 'STUArray' with one element type into one with a
 -- different element type.  All the elements of the resulting array
 -- are undefined (unless you know what you\'re doing...).
 
 castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
-#if __GLASGOW_HASKELL__
 castSTUArray (STUArray l u n marr#) = return (STUArray l u n marr#)
-#elif __HUGS__
-castSTUArray (STUArray l u n marr) = return (STUArray l u n marr)
-#endif
 
+--------------------------------------------------------------------------------
+
+-- 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,5 +1,5 @@
-{-# OPTIONS_GHC -#include "HsBase.h" #-}
-{-# OPTIONS_GHC -w #-} --tmp
+{-# LANGUAGE MagicHash, Trustworthy, UnliftedFFITypes #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.IO
@@ -20,7 +20,6 @@
 
     -- * @IO@ arrays with unboxed elements
     IOUArray,            -- instance of: Eq, Typeable
-    castIOUArray,        -- :: IOUArray i a -> IO (IOUArray i b)
 
     -- * Overloaded mutable array interface
     module Data.Array.MArray,
@@ -31,29 +30,17 @@
   ) where
 
 import Data.Array.Base
-import Data.Array.IO.Internals hiding ( castIOUArray )
-import qualified Data.Array.Unsafe as U ( castIOUArray )
+import Data.Array.IO.Internals
 import Data.Array.MArray
 import System.IO.Error
 
-#ifdef __GLASGOW_HASKELL__
 import Foreign
 import Foreign.C
 
 import GHC.Exts  (MutableByteArray#, RealWorld)
-import GHC.Arr
-import GHC.IORef
 import GHC.IO.Handle
-import GHC.IO.Buffer
 import GHC.IO.Exception
 
-#else
-import Data.Char
-import Data.Word ( Word8 )
-import System.IO
-#endif
-
-#ifdef __GLASGOW_HASKELL__
 -- ---------------------------------------------------------------------------
 -- hGetArray
 
@@ -77,7 +64,7 @@
       -- allocate a separate area of memory and copy.
       allocaBytes count $ \p -> do
         r <- hGetBuf handle p count
-        memcpy_ba_ptr ptr p (fromIntegral r)
+        _ <- memcpy_ba_ptr ptr p (fromIntegral r)
         return r
 
 foreign import ccall unsafe "memcpy"
@@ -100,7 +87,7 @@
       -- as in hGetArray, we would like to use the array directly, but
       -- we can't be sure that the MutableByteArray# is pinned.
      allocaBytes count $ \p -> do
-       memcpy_ptr_ba p raw (fromIntegral count)
+       _ <- memcpy_ptr_ba p raw (fromIntegral count)
        hPutBuf handle p count
 
 foreign import ccall unsafe "memcpy"
@@ -114,52 +101,3 @@
         ioException (ioeSetErrorString
                      (mkIOError InvalidArgument fn (Just handle) Nothing)
                      ("illegal buffer size " ++ showsPrec 9 (sz::Int) []))
-
-#else /* !__GLASGOW_HASKELL__ */
-hGetArray :: Handle -> IOUArray Int Word8 -> Int -> IO Int
-hGetArray handle arr count = do
-        bds <- getBounds arr
-        if count < 0 || count > rangeSize bds
-           then illegalBufferSize handle "hGetArray" count
-           else get 0
- where
-  get i | i == count = return i
-        | otherwise = do
-                error_or_c <- try (hGetChar handle)
-                case error_or_c of
-                    Left ex
-                        | isEOFError ex -> return i
-                        | otherwise -> ioError ex
-                    Right c -> do
-                        unsafeWrite arr i (fromIntegral (ord c))
-                        get (i+1)
-
-hPutArray :: Handle -> IOUArray Int Word8 -> Int -> IO ()
-hPutArray handle arr count = do
-        bds <- getBounds arr
-        if count < 0 || count > rangeSize bds
-           then illegalBufferSize handle "hPutArray" count
-           else put 0
- where
-  put i | i == count = return ()
-        | otherwise = do
-                w <- unsafeRead arr i
-                hPutChar handle (chr (fromIntegral w))
-                put (i+1)
-
-illegalBufferSize :: Handle -> String -> Int -> IO a
-illegalBufferSize _ fn sz = ioError $
-        userError (fn ++ ": illegal buffer size " ++ showsPrec 9 (sz::Int) [])
-#endif /* !__GLASGOW_HASKELL__ */
-
-
-{-# DEPRECATED castIOUArray
-              "Please import from Data.Array.Unsafe instead; This will be removed in the next release"
- #-}
--- | Casts an 'IOUArray' with one element type into one with a
--- different element type.  All the elements of the resulting array
--- are undefined (unless you know what you\'re doing...).
-{-# INLINE castIOUArray #-}
-castIOUArray :: IOUArray i a -> IO (IOUArray i b)
-castIOUArray = U.castIOUArray
-
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,9 +1,14 @@
-{-# OPTIONS_HADDOCK hide #-}
-{-# OPTIONS_GHC -#include "HsBase.h" #-}
+{-# LANGUAGE
+    FlexibleInstances
+  , MultiParamTypeClasses
+  , RoleAnnotations
+ #-}
+
+{-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.IO.Internal
--- Copyright   :  (c) The University of Glasgow 2001
+-- Copyright   :  (c) The University of Glasgow 2001-2012
 -- License     :  BSD-style (see the file libraries/base/LICENSE)
 --
 -- Maintainer  :  libraries@haskell.org
@@ -12,43 +17,39 @@
 --
 -- 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.
+--
 -----------------------------------------------------------------------------
 
--- #hide
 module Data.Array.IO.Internals (
     IOArray(..),         -- instance of: Eq, Typeable
     IOUArray(..),        -- instance of: Eq, Typeable
     castIOUArray,        -- :: IOUArray ix a -> IO (IOUArray ix b)
-#ifdef __GLASGOW_HASKELL__
     unsafeThawIOUArray,
-#endif
+    unsafeFreezeIOUArray
   ) where
 
 import Data.Int
 import Data.Word
-import Data.Typeable
 
 import Control.Monad.ST         ( RealWorld, stToIO )
 import Foreign.Ptr              ( Ptr, FunPtr )
 import Foreign.StablePtr        ( StablePtr )
 
-import Data.Ix
 import Data.Array.Base
 
-#ifdef __HUGS__
-import Hugs.IOArray
-#endif
-
-#ifdef __GLASGOW_HASKELL__
-#if __GLASGOW_HASKELL__ >= 611
 import GHC.IOArray (IOArray(..))
-#else
-import GHC.IOBase (IOArray(..))
-#endif
-#endif /* __GLASGOW_HASKELL__ */
 
-#include "Typeable.h"
-
 -----------------------------------------------------------------------------
 -- Flat unboxed mutable arrays (IO monad)
 
@@ -61,8 +62,8 @@
 --    are supported: see "Data.Array.MArray" for a list of instances.
 --
 newtype IOUArray i e = IOUArray (STUArray RealWorld i e)
-
-INSTANCE_TYPEABLE2(IOUArray,iOUArrayTc,"IOUArray")
+-- Both parameters have class-based invariants. See also #9220.
+type role IOUArray nominal nominal
 
 instance Eq (IOUArray i e) where
     IOUArray s1 == IOUArray s2  =  s1 == s2
@@ -381,9 +382,8 @@
     marr' <- castSTUArray marr
     return (IOUArray marr')
 
-#ifdef __GLASGOW_HASKELL__
 {-# INLINE unsafeThawIOUArray #-}
-unsafeThawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
+unsafeThawIOUArray :: UArray ix e -> IO (IOUArray ix e)
 unsafeThawIOUArray arr = stToIO $ do
     marr <- unsafeThawSTUArray arr
     return (IOUArray marr)
@@ -392,7 +392,7 @@
 "unsafeThaw/IOUArray" unsafeThaw = unsafeThawIOUArray
     #-}
 
-thawIOUArray :: Ix ix => UArray ix e -> IO (IOUArray ix e)
+thawIOUArray :: UArray ix e -> IO (IOUArray ix e)
 thawIOUArray arr = stToIO $ do
     marr <- thawSTUArray arr
     return (IOUArray marr)
@@ -402,18 +402,16 @@
     #-}
 
 {-# INLINE unsafeFreezeIOUArray #-}
-unsafeFreezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
+unsafeFreezeIOUArray :: IOUArray ix e -> IO (UArray ix e)
 unsafeFreezeIOUArray (IOUArray marr) = stToIO (unsafeFreezeSTUArray marr)
 
 {-# RULES
 "unsafeFreeze/IOUArray" unsafeFreeze = unsafeFreezeIOUArray
     #-}
 
-freezeIOUArray :: Ix ix => IOUArray ix e -> IO (UArray ix e)
+freezeIOUArray :: IOUArray ix e -> IO (UArray ix e)
 freezeIOUArray (IOUArray marr) = stToIO (freezeSTUArray marr)
 
 {-# RULES
 "freeze/IOUArray" freeze = freezeIOUArray
     #-}
-#endif /* __GLASGOW_HASKELL__ */
-
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,6 +1,5 @@
-{-# LANGUAGE Trustworthy #-}
-{-# OPTIONS_GHC -#include "HsBase.h" #-}
-{-# OPTIONS_GHC -w #-} --tmp
+{-# LANGUAGE Safe #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.IO.Safe
@@ -15,6 +14,7 @@
 -- .
 -- Safe API only of "Data.Array.IO".
 --
+-- @since 0.4.0.0
 -----------------------------------------------------------------------------
 
 module Data.Array.IO.Safe (
diff --git a/Data/Array/MArray.hs b/Data/Array/MArray.hs
--- a/Data/Array/MArray.hs
+++ b/Data/Array/MArray.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP, Trustworthy #-}
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.MArray
@@ -25,11 +27,22 @@
     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)
     mapIndices,   -- :: (MArray a e m, Ix i, Ix j) => (i,i) -> (i -> j) -> a j e -> m (a i e)
@@ -41,87 +54,11 @@
 
     -- * Conversions between mutable and immutable arrays
     freeze,       -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
-    unsafeFreeze, -- :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
     thaw,         -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
-    unsafeThaw,   -- :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
   ) where
 
 import Data.Ix
-import Data.Array.Base hiding ( unsafeFreeze, unsafeThaw )
-import qualified Data.Array.Base as U ( unsafeFreeze, unsafeThaw )
+import Data.Array.Base
 #ifdef __HADDOCK__
 import Data.Array.IArray
 #endif
-
-{-# DEPRECATED unsafeFreeze, unsafeThaw
-              "Please import from Data.Array.Unsafe instead; This will be removed in the next release"
- #-}
-
-{- |
-   Converts an mutable array into an immutable array.  The
-   implementation may either simply cast the array from
-   one type to the other without copying the array, or it
-   may take a full copy of the array.
-
-   Note that because the array is possibly not copied, any subsequent
-   modifications made to the mutable version of the array may be
-   shared with the immutable version.  It is safe to use, therefore, if
-   the mutable version is never modified after the freeze operation.
-
-   The non-copying implementation is supported between certain pairs
-   of array types only; one constraint is that the array types must
-   have identical representations.  In GHC, The following pairs of
-   array types have a non-copying O(1) implementation of
-   'unsafeFreeze'.  Because the optimised versions are enabled by
-   specialisations, you will need to compile with optimisation (-O) to
-   get them.
-
-     * 'Data.Array.IO.IOUArray' -> 'Data.Array.Unboxed.UArray'
-
-     * 'Data.Array.ST.STUArray' -> 'Data.Array.Unboxed.UArray'
-
-     * 'Data.Array.IO.IOArray' -> 'Data.Array.Array'
-
-     * 'Data.Array.ST.STArray' -> 'Data.Array.Array'
--}
-{-# INLINE unsafeFreeze #-}
-unsafeFreeze :: (Ix i, MArray a e m, IArray b e) => a i e -> m (b i e)
-unsafeFreeze = U.unsafeFreeze
-
-{- |
-   Converts an immutable array into a mutable array.  The
-   implementation may either simply cast the array from
-   one type to the other without copying the array, or it
-   may take a full copy of the array.
-
-   Note that because the array is possibly not copied, any subsequent
-   modifications made to the mutable version of the array may be
-   shared with the immutable version.  It is only safe to use,
-   therefore, if the immutable array is never referenced again in this
-   thread, and there is no possibility that it can be also referenced
-   in another thread.  If you use an unsafeThaw/write/unsafeFreeze
-   sequence in a multi-threaded setting, then you must ensure that
-   this sequence is atomic with respect to other threads, or a garbage
-   collector crash may result (because the write may be writing to a
-   frozen array).
-
-   The non-copying implementation is supported between certain pairs
-   of array types only; one constraint is that the array types must
-   have identical representations.  In GHC, The following pairs of
-   array types have a non-copying O(1) implementation of
-   'unsafeThaw'.  Because the optimised versions are enabled by
-   specialisations, you will need to compile with optimisation (-O) to
-   get them.
-
-     * 'Data.Array.Unboxed.UArray' -> 'Data.Array.IO.IOUArray'
-
-     * 'Data.Array.Unboxed.UArray' -> 'Data.Array.ST.STUArray'
-
-     * 'Data.Array.Array'  -> 'Data.Array.IO.IOArray'
-
-     * 'Data.Array.Array'  -> 'Data.Array.ST.STArray'
--}
-{-# INLINE unsafeThaw #-}
-unsafeThaw :: (Ix i, IArray a e, MArray b e m) => a i e -> m (b i e)
-unsafeThaw = U.unsafeThaw
-
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
@@ -1,4 +1,4 @@
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE CPP, Trustworthy #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.MArray.Safe
@@ -15,6 +15,7 @@
 -- .
 -- Safe API only of "Data.Array.MArray".
 --
+-- @since 0.4.0.0
 -----------------------------------------------------------------------------
 
 module Data.Array.MArray.Safe (
@@ -28,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,3 +1,4 @@
+{-# LANGUAGE RankNTypes, Trustworthy #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.ST
@@ -20,7 +21,6 @@
    -- * Unboxed arrays
    STUArray,            -- instance of: Eq, MArray
    runSTUArray,
-   castSTUArray,        -- :: STUArray s i a -> ST s (STUArray s i b)
 
    -- * Overloaded mutable array interface
    module Data.Array.MArray,
@@ -28,26 +28,16 @@
 
 import Data.Array.Base  ( STUArray, UArray, unsafeFreezeSTUArray )
 import Data.Array.MArray
-import qualified Data.Array.Unsafe as U ( castSTUArray )
 import Control.Monad.ST ( ST, runST )
 
-#ifdef __HUGS__
-import Hugs.Array       ( Array )
-import Hugs.ST          ( STArray, unsafeFreezeSTArray )
-#endif
-
-#ifdef __GLASGOW_HASKELL__
 import GHC.Arr          ( STArray, Array, unsafeFreezeSTArray )
-#endif
 
 -- | A safe way to create and work with a mutable array before returning an
 -- immutable array for later perusal.  This function avoids copying
 -- the array before returning it - it uses 'unsafeFreeze' internally, but
 -- this wrapper is a safe interface to that function.
 --
-runSTArray :: (Ix i)
-           => (forall s . ST s (STArray s i e))
-           -> Array i e
+runSTArray :: (forall s . ST s (STArray s i e)) -> Array i e
 runSTArray st = runST (st >>= unsafeFreezeSTArray)
 
 -- | A safe way to create and work with an unboxed mutable array before
@@ -56,9 +46,7 @@
 -- 'unsafeFreeze' internally, but this wrapper is a safe interface to
 -- that function.
 --
-runSTUArray :: (Ix i)
-           => (forall s . ST s (STUArray s i e))
-           -> UArray i e
+runSTUArray :: (forall s . ST s (STUArray s i e)) -> UArray i e
 runSTUArray st = runST (st >>= unsafeFreezeSTUArray)
 
 
@@ -73,15 +61,3 @@
 -- unsafeFreezeSTUArray directly in the defn of runSTUArray above, but
 -- this essentially constrains us to a single unsafeFreeze for all STUArrays
 -- (in theory we might have a different one for certain element types).
-
-{-# DEPRECATED castSTUArray
-              "Please import from Data.Array.Unsafe instead; This will be removed in the next release"
- #-}
-
--- | Casts an 'STUArray' with one element type into one with a
--- different element type.  All the elements of the resulting array
--- are undefined (unless you know what you\'re doing...).
-{-# INLINE castSTUArray #-}
-castSTUArray :: STUArray s ix a -> ST s (STUArray s ix b)
-castSTUArray = U.castSTUArray
-
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
@@ -13,6 +13,7 @@
 --
 -- Safe API only of "Data.Array.ST".
 --
+-- @since 0.4.0.0
 -----------------------------------------------------------------------------
 
 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
@@ -34,25 +35,7 @@
     withStorableArray,  -- :: StorableArray i e -> (Ptr e -> IO a) -> IO a
 
     touchStorableArray, -- :: StorableArray i e -> IO ()
-
-    unsafeForeignPtrToStorableArray
   ) where
 
-import Foreign hiding (newArray)
-
 import Data.Array.MArray
-import Data.Array.Storable.Internals hiding ( unsafeForeignPtrToStorableArray )
-import qualified Data.Array.Unsafe as U ( unsafeForeignPtrToStorableArray )
-
-{-# DEPRECATED unsafeForeignPtrToStorableArray
-              "Please import from Data.Array.Unsafe instead; This will be removed in the next release"
- #-}
-
--- |Construct a 'StorableArray' from an arbitrary 'ForeignPtr'.  It is
--- the caller's responsibility to ensure that the 'ForeignPtr' points to
--- an area of memory sufficient for the specified bounds.
-{-# INLINE unsafeForeignPtrToStorableArray #-}
-unsafeForeignPtrToStorableArray
-   :: Ix i => ForeignPtr e -> (i,i) -> IO (StorableArray i e)
-unsafeForeignPtrToStorableArray = U.unsafeForeignPtrToStorableArray
-
+import Data.Array.Storable.Internals
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,4 +1,5 @@
-{-# OPTIONS_HADDOCK hide #-}
+{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, RoleAnnotations #-}
+{-# OPTIONS_HADDOCK not-home #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  Data.Array.Storable.Internals
@@ -11,9 +12,21 @@
 --
 -- 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.
 -----------------------------------------------------------------------------
 
--- #hide
 module Data.Array.Storable.Internals (
     StorableArray(..),
     withStorableArray,
@@ -27,6 +40,8 @@
 
 -- |The array type
 data StorableArray i e = StorableArray !i !i Int !(ForeignPtr e)
+-- Both parameters have class-based invariants. See also #9220.
+type role StorableArray nominal nominal
 
 instance Storable e => MArray StorableArray e IO where
     getBounds (StorableArray l u _ _) = return (l,u)
diff --git a/Data/Array/Storable/Safe.hs b/Data/Array/Storable/Safe.hs
--- a/Data/Array/Storable/Safe.hs
+++ b/Data/Array/Storable/Safe.hs
@@ -20,6 +20,7 @@
 --
 -- Safe API only of "Data.Array.Storable".
 --
+-- @since 0.4.0.0
 -----------------------------------------------------------------------------
 
 module Data.Array.Storable.Safe (
diff --git a/Data/Array/Unsafe.hs b/Data/Array/Unsafe.hs
--- a/Data/Array/Unsafe.hs
+++ b/Data/Array/Unsafe.hs
@@ -11,6 +11,7 @@
 -- Contains the various unsafe operations that can be performed
 -- on arrays.
 --
+-- @since 0.4.0.0
 -----------------------------------------------------------------------------
 
 module Data.Array.Unsafe (
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,30 +1,45 @@
-name:       array
-version:    0.4.0.1
-license:    BSD3
-license-file:    LICENSE
+cabal-version: >= 1.10
+name:          array
+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://hackage.haskell.org/trac/ghc/newticket?component=libraries%20%28other%29
-synopsis:   Mutable and immutable arrays
-category:   Data Structures
+bug-reports:   https://gitlab.haskell.org/ghc/packages/array/issues
+synopsis:      Mutable and immutable arrays
+category:      Data Structures
+build-type:    Simple
 description:
-    This package defines the classes @IArray@ of immutable arrays and
-    @MArray@ of arrays mutable within appropriate monads, as well as
-    some instances of these classes.
-cabal-version: >=1.6
-build-type: Simple
-extra-source-files: include/Typeable.h
+    In addition to providing the "Data.Array" module
+    <http://www.haskell.org/onlinereport/haskell2010/haskellch14.html as specified in the Haskell 2010 Language Report>,
+    this package also defines the classes 'IArray' of
+    immutable arrays and 'MArray' of arrays mutable within appropriate
+    monads, as well as some instances of these classes.
 
+extra-source-files: changelog.md
+
 source-repository head
-    type:     git
-    location: http://darcs.haskell.org/packages/array.git/
+  type:     git
+  location: http://gitlab.haskell.org/ghc/packages/array.git
 
 library
-  build-depends: base >= 4.2 && < 5
+  default-language: Haskell2010
+  other-extensions:
+      BangPatterns,
+      CPP,
+      FlexibleContexts,
+      FlexibleInstances,
+      MagicHash,
+      MultiParamTypeClasses,
+      RankNTypes,
+      Trustworthy,
+      UnboxedTuples,
+      UnliftedFFITypes
+  build-depends: base >= 4.9 && < 4.21
+  ghc-options: -Wall
   exposed-modules:
       Data.Array
-  extensions: CPP
-  if !impl(nhc98)
-    exposed-modules:
       Data.Array.Base
       Data.Array.IArray
       Data.Array.IO
@@ -39,18 +54,3 @@
       Data.Array.Storable.Internals
       Data.Array.Unboxed
       Data.Array.Unsafe
-    extensions:
-      MultiParamTypeClasses,
-      FlexibleContexts,
-      FlexibleInstances,
-      TypeSynonymInstances
-  if impl(ghc)
-    extensions:
-      DeriveDataTypeable,
-      StandaloneDeriving,
-      Rank2Types,
-      MagicHash,
-      UnboxedTuples,
-      ForeignFunctionInterface,
-      UnliftedFFITypes
-  include-dirs: include
diff --git a/changelog.md b/changelog.md
new file mode 100644
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,101 @@
+# 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
+  * Overflow check in `unsafeNewArray` (#229)
+  * Fix and simplify handling of `Bool` arrays
+  * Export `unsafeFreezeIOUArray` from `Data.Array.IO.Internals`
+  * Drop support for GHC versions prior to GHC 7.8
+
+## 0.5.1.1  *Apr 2016*
+
+  * Bundled with GHC 8.0.1
+  * Use `@since` syntax in Haddock comments
+  * Don't needlessly call `bounds` in `Data.Array.Base.elems` (#10014)
+
+## 0.5.1.0  *Mar 2015*
+
+  * Bundled with GHC 7.10.1
+  * Add role annotations for GHC >= 7.8 (#9220)
+
+## 0.5.0.0  *Nov 2013*
+
+  * Update to Cabal 1.10 format
+  * Remove NHC and Hugs specific code
+  * Remove deprecated function exports `Data.Array.IO.castIOUArray`,
+    `Data.Array.MArray.unsafeFreeze`, `Data.Array.MArray.unsafeThaw`,
+    and `Data.Array.ST.castSTUArray`; These functions are still
+    available from the `Data.Array.Unsafe` module.
+
+## 0.4.0.1  *Sep 2012*
+
+  * Bundled with GHC 7.6.1
+  * Fix inline rule shadowing warnings
+
+## 0.4.0.0  *Feb 2012*
+
+  * Bundled with GHC 7.4.1
+  * Add support for SafeHaskell
+  * New `Data.Array.IO.Safe` module
+  * New `Data.Array.MArray.safe` module
+  * New `Data.Array.ST.safe` module
+  * New `Data.Array.Storable.Internals` module
+  * New `Data.Array.Storable.Safe` module
+  * New `Data.Array.Unsafe` module
diff --git a/include/Typeable.h b/include/Typeable.h
deleted file mode 100644
--- a/include/Typeable.h
+++ /dev/null
@@ -1,59 +0,0 @@
-{- --------------------------------------------------------------------------
-// Macros to help make Typeable instances.
-//
-// INSTANCE_TYPEABLEn(tc,tcname,"tc") defines
-//
-//	instance Typeable/n/ tc
-//	instance Typeable a => Typeable/n-1/ (tc a)
-//	instance (Typeable a, Typeable b) => Typeable/n-2/ (tc a b)
-//	...
-//	instance (Typeable a1, ..., Typeable an) => Typeable (tc a1 ... an)
-// --------------------------------------------------------------------------
--}
-
-#ifndef TYPEABLE_H
-#define TYPEABLE_H
-
-#ifdef __GLASGOW_HASKELL__
-
---  // For GHC, we can use DeriveDataTypeable + StandaloneDeriving to
---  // generate the instances.
-
-#define INSTANCE_TYPEABLE0(tycon,tcname,str) deriving instance Typeable tycon
-#define INSTANCE_TYPEABLE1(tycon,tcname,str) deriving instance Typeable1 tycon
-#define INSTANCE_TYPEABLE2(tycon,tcname,str) deriving instance Typeable2 tycon
-#define INSTANCE_TYPEABLE3(tycon,tcname,str) deriving instance Typeable3 tycon
-
-#else /* !__GLASGOW_HASKELL__ */
-
-#define INSTANCE_TYPEABLE0(tycon,tcname,str) \
-tcname :: TyCon; \
-tcname = mkTyCon str; \
-instance Typeable tycon where { typeOf _ = mkTyConApp tcname [] }
-
-#define INSTANCE_TYPEABLE1(tycon,tcname,str) \
-tcname = mkTyCon str; \
-instance Typeable1 tycon where { typeOf1 _ = mkTyConApp tcname [] }; \
-instance Typeable a => Typeable (tycon a) where { typeOf = typeOfDefault }
-
-#define INSTANCE_TYPEABLE2(tycon,tcname,str) \
-tcname = mkTyCon str; \
-instance Typeable2 tycon where { typeOf2 _ = mkTyConApp tcname [] }; \
-instance Typeable a => Typeable1 (tycon a) where { \
-  typeOf1 = typeOf1Default }; \
-instance (Typeable a, Typeable b) => Typeable (tycon a b) where { \
-  typeOf = typeOfDefault }
-
-#define INSTANCE_TYPEABLE3(tycon,tcname,str) \
-tcname = mkTyCon str; \
-instance Typeable3 tycon where { typeOf3 _ = mkTyConApp tcname [] }; \
-instance Typeable a => Typeable2 (tycon a) where { \
-  typeOf2 = typeOf2Default }; \
-instance (Typeable a, Typeable b) => Typeable1 (tycon a b) where { \
-  typeOf1 = typeOf1Default }; \
-instance (Typeable a, Typeable b, Typeable c) => Typeable (tycon a b c) where { \
-  typeOf = typeOfDefault }
-
-#endif /* !__GLASGOW_HASKELL__ */
-
-#endif
