{-# 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 x :: STArray RealWorld i e
x == :: IOArray i e -> IOArray i e -> Bool
== IOArray y :: 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 :: (i, i) -> e -> IO (IOArray i e)
newIOArray lu :: (i, i)
lu initial :: 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 (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 :: IOArray i e -> Int -> IO e
unsafeReadIOArray (IOArray marr :: STArray RealWorld i e
marr) i :: 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 :: IOArray i e -> Int -> e -> IO ()
unsafeWriteIOArray (IOArray marr :: STArray RealWorld i e
marr) i :: Int
i e :: 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 :: IOArray i e -> i -> IO e
readIOArray (IOArray marr :: STArray RealWorld i e
marr) i :: 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 :: IOArray i e -> i -> e -> IO ()
writeIOArray (IOArray marr :: STArray RealWorld i e
marr) i :: i
i e :: 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 :: IOArray i e -> (i, i)
boundsIOArray (IOArray marr :: 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