    {-# LANGUAGE Unsafe #-}
    {-# LANGUAGE NoImplicitPrelude, RoleAnnotations #-}
    {-# OPTIONS_GHC -funbox-strict-fields #-}
    {-# OPTIONS_HADDOCK not-home #-}

    -----------------------------------------------------------------------------
    -- |
    -- 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

    -- ---------------------------------------------------------------------------
    -- | 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)

    -- 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
    -- | @since 4.1.0.0
    instance Eq (IOArray i e) where
      IOArray STArray RealWorld i e
    x == :: IOArray i e -> IOArray i e -> Bool
    == IOArray STArray RealWorld i e
    y = STArray RealWorld i e
    x STArray RealWorld i e -> STArray RealWorld i e -> Bool
    forall a. Eq a => a -> a -> Bool
    == STArray RealWorld i e
    y

    -- |Build a new 'IOArray'
    newIOArray :: Ix i => (i,i) -> e -> IO (IOArray i e)
    {-# INLINE newIOArray #-}
    newIOArray :: forall i e. Ix i => (i, i) -> e -> IO (IOArray i e)
    newIOArray (i, i)
    lu e
    initial  = ST RealWorld (IOArray i e) -> IO (IOArray i e)
    forall a. ST RealWorld a -> IO a
    stToIO (ST RealWorld (IOArray i e) -> IO (IOArray i e))
    -> ST RealWorld (IOArray i e) -> IO (IOArray i e)
    forall a b. (a -> b) -> a -> b
    $ do {STArray RealWorld i e
    marr <- (i, i) -> e -> ST RealWorld (STArray RealWorld i e)
    forall i e s. Ix i => (i, i) -> e -> ST s (STArray s i e)
    newSTArray (i, i)
    lu e
    initial; IOArray i e -> ST RealWorld (IOArray i e)
    forall a. a -> ST RealWorld a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (STArray RealWorld i e -> IOArray i e
    forall i e. STArray RealWorld i e -> IOArray i e
    IOArray STArray RealWorld i e
    marr)}

    -- | Read a value from an 'IOArray'
    unsafeReadIOArray  :: IOArray i e -> Int -> IO e
    {-# INLINE unsafeReadIOArray #-}
    unsafeReadIOArray :: forall i e. IOArray i e -> Int -> IO e
    unsafeReadIOArray (IOArray STArray RealWorld i e
    marr) Int
    i = ST RealWorld e -> IO e
    forall a. ST RealWorld a -> IO a
    stToIO (STArray RealWorld i e -> Int -> ST RealWorld e
    forall s i e. STArray s i e -> Int -> ST s e
    unsafeReadSTArray STArray RealWorld i e
    marr Int
    i)

    -- | Write a new value into an 'IOArray'
    unsafeWriteIOArray :: IOArray i e -> Int -> e -> IO ()
    {-# INLINE unsafeWriteIOArray #-}
    unsafeWriteIOArray :: forall i e. IOArray i e -> Int -> e -> IO ()
    unsafeWriteIOArray (IOArray STArray RealWorld i e
    marr) Int
    i e
    e = ST RealWorld () -> IO ()
    forall a. ST RealWorld a -> IO a
    stToIO (STArray RealWorld i e -> Int -> e -> ST RealWorld ()
    forall s i e. STArray s i e -> Int -> e -> ST s ()
    unsafeWriteSTArray STArray RealWorld i e
    marr Int
    i e
    e)

    -- | Read a value from an 'IOArray'
    readIOArray  :: Ix i => IOArray i e -> i -> IO e
    readIOArray :: forall i e. Ix i => IOArray i e -> i -> IO e
    readIOArray (IOArray STArray RealWorld i e
    marr) i
    i = ST RealWorld e -> IO e
    forall a. ST RealWorld a -> IO a
    stToIO (STArray RealWorld i e -> i -> ST RealWorld e
    forall i s e. Ix i => STArray s i e -> i -> ST s e
    readSTArray STArray RealWorld i e
    marr i
    i)

    -- | Write a new value into an 'IOArray'
    writeIOArray :: Ix i => IOArray i e -> i -> e -> IO ()
    writeIOArray :: forall i e. Ix i => IOArray i e -> i -> e -> IO ()
    writeIOArray (IOArray STArray RealWorld i e
    marr) i
    i e
    e = ST RealWorld () -> IO ()
    forall a. ST RealWorld a -> IO a
    stToIO (STArray RealWorld i e -> i -> e -> ST RealWorld ()
    forall i s e. Ix i => STArray s i e -> i -> e -> ST s ()
    writeSTArray STArray RealWorld i e
    marr i
    i e
    e)

    {-# INLINE boundsIOArray #-}
    boundsIOArray :: IOArray i e -> (i,i)
    boundsIOArray :: forall i e. IOArray i e -> (i, i)
    boundsIOArray (IOArray STArray RealWorld i e
    marr) = STArray RealWorld i e -> (i, i)
    forall s i e. STArray s i e -> (i, i)
    boundsSTArray STArray RealWorld i e
    marr