    {-# LANGUAGE Unsafe #-}
    {-# LANGUAGE NoImplicitPrelude, AutoDeriveTypeable, RoleAnnotations #-}
    {-# OPTIONS_GHC -funbox-strict-fields #-}
    {-# OPTIONS_HADDOCK hide #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  GHC.IOArray
    -- Copyright   :  (c) The University of Glasgow 2008
    -- License     :  see libraries/base/LICENSE
    --
    -- Maintainer  :  cvs-ghc@haskell.org
    -- Stability   :  internal
    -- Portability :  non-portable (GHC Extensions)
    --
    -- The IOArray type
    --
    -----------------------------------------------------------------------------

    module GHC.IOArray (
            IOArray(..),
            newIOArray, unsafeReadIOArray, unsafeWriteIOArray,
            readIOArray, writeIOArray,
            boundsIOArray
        ) where

    import GHC.Base
    import GHC.IO
    import GHC.Arr
    import Data.Typeable.Internal

    -- ---------------------------------------------------------------------------
    -- | An 'IOArray' is a mutable, boxed, non-strict array in the 'IO' monad.
    -- The type arguments are as follows:
    --
    --  * @i@: the index type of the array (should be an instance of 'Ix')
    --
    --  * @e@: the element type of the array.
    --
    --

    newtype IOArray i e = IOArray (STArray RealWorld i e) deriving( Typeable )

    -- index type should have a nominal role due to Ix class. See also #9220.
    type role IOArray nominal representational

    -- explicit instance because Haddock can't figure out a derived one
    instance Eq (IOArray i e) where
      IOArray x == IOArray y = x == y

    -- |Build a new 'IOArray'
    newIOArray :: Ix i => (i,i) -> e -> IO (IOArray i e)
    {-# INLINE newIOArray #-}
    newIOArray lu initial  = stToIO $ do {marr <- newSTArray lu initial; return (IOArray marr)}

    -- | Read a value from an 'IOArray'
    unsafeReadIOArray  :: Ix i => IOArray i e -> Int -> IO e
    {-# INLINE unsafeReadIOArray #-}
    unsafeReadIOArray (IOArray marr) i = stToIO (unsafeReadSTArray marr i)

    -- | Write a new value into an 'IOArray'
    unsafeWriteIOArray :: Ix i => IOArray i e -> Int -> e -> IO ()
    {-# INLINE unsafeWriteIOArray #-}
    unsafeWriteIOArray (IOArray marr) i e = stToIO (unsafeWriteSTArray marr i e)

    -- | Read a value from an 'IOArray'
    readIOArray  :: Ix i => IOArray i e -> i -> IO e
    readIOArray (IOArray marr) i = stToIO (readSTArray marr i)

    -- | Write a new value into an 'IOArray'
    writeIOArray :: Ix i => IOArray i e -> i -> e -> IO ()
    writeIOArray (IOArray marr) i e = stToIO (writeSTArray marr i e)

    {-# INLINE boundsIOArray #-}
    boundsIOArray :: IOArray i e -> (i,i)
    boundsIOArray (IOArray marr) = boundsSTArray marr