    {-# LANGUAGE CPP, MagicHash, Rank2Types #-}
    {- |
       Module      :  Control.Monad.ST.Trans
       Copyright   :  Josef Svenningsson 2008-2017
                      (c) The University of Glasgow, 1994-2000
       License     :  BSD

       Maintainer  :  josef.svenningsson@gmail.com, Andreas Abel
       Stability   :  stable
       Portability :  non-portable (GHC Extensions)

       This library provides a monad transformer version of the ST monad.

       Warning! This monad transformer should not be used with monads that
       can contain multiple answers, like the list monad. The reason is that
       the state token will be duplicated across the different answers and
       this causes Bad Things to happen (such as loss of referential
       transparency). Safe monads include the monads @'State'@, @'Reader'@, @'Writer'@,
       @'Maybe'@ and combinations of their corresponding monad transformers.

    -}
    module Control.Monad.ST.Trans(
          -- * The ST Monad Transformer
          STT,
          runST,
          runSTT,
          -- * Mutable references
          STRef,
          newSTRef,
          readSTRef,
          writeSTRef,
          -- * Mutable arrays
          STArray,
          newSTArray,
          readSTArray,
          writeSTArray,
          boundsSTArray,
          numElementsSTArray,
          freezeSTArray,
          thawSTArray,
          runSTArray,
          -- * Unsafe Operations
          unsafeReadSTArray,
          unsafeWriteSTArray,
          unsafeFreezeSTArray,
          unsafeThawSTArray,
          unsafeIOToSTT,
          unsafeSTToIO,
          unsafeSTTToIO,
          unsafeSTRefToIORef,
          unsafeIORefToSTRef
          ) where

    import GHC.Base            (realWorld#)
    import GHC.Arr             (Ix, Array(..))
    import qualified GHC.Arr as STArray

    #if __GLASGOW_HASKELL__ <= 708
    import Control.Applicative (Applicative)
    #endif

    import Control.Monad.ST.Trans.Internal

    import Data.Array.ST       (STArray, newArray, readArray, writeArray)
    import Data.IORef          (IORef)
    import Data.STRef          (STRef)
    import qualified Data.STRef as STRef

    import System.IO.Unsafe    (unsafePerformIO)
    import Unsafe.Coerce       (unsafeCoerce)

    {-# INLINE newSTRef #-}
    -- | Create a new reference
    newSTRef :: (Applicative m) => a -> STT s m (STRef s a)
    newSTRef :: forall (m :: * -> *) a s. Applicative m => a -> STT s m (STRef s a)
    newSTRef a
    i = ST s (STRef s a) -> STT s m (STRef s a)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (a -> ST s (STRef s a)
    forall a s. a -> ST s (STRef s a)
    STRef.newSTRef a
    i)

    {-# INLINE readSTRef #-}
    -- | Reads the value of a reference
    readSTRef :: (Applicative m) => STRef s a -> STT s m a
    readSTRef :: forall (m :: * -> *) s a. Applicative m => STRef s a -> STT s m a
    readSTRef STRef s a
    ref = ST s a -> STT s m a
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STRef s a -> ST s a
    forall s a. STRef s a -> ST s a
    STRef.readSTRef STRef s a
    ref)

    {-# INLINE writeSTRef #-}
    -- | Modifies the value of a reference
    writeSTRef :: (Applicative m) => STRef s a -> a -> STT s m ()
    writeSTRef :: forall (m :: * -> *) s a.
    Applicative m =>
    STRef s a -> a -> STT s m ()
    writeSTRef STRef s a
    ref a
    a = ST s () -> STT s m ()
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STRef s a -> a -> ST s ()
    forall s a. STRef s a -> a -> ST s ()
    STRef.writeSTRef STRef s a
    ref a
    a)

    {-# DEPRECATED runST "Use runSTT instead" #-}
    {-# NOINLINE runST #-}
    -- | Executes a computation in the 'STT' monad transformer
    runST :: Monad m => (forall s. STT s m a) -> m a
    runST :: forall (m :: * -> *) a. Monad m => (forall s. STT s m a) -> m a
    runST forall s. STT s m a
    m = let (STT State# s -> m (STTRet s a)
    f) = STT s m a
    forall s. STT s m a
    m
     -- the parenthesis is needed because of a bug in the parser of GHC
              in do (STTRet _st a) <- ( State# RealWorld -> m (STTRet RealWorld a)
    forall {s}. State# s -> m (STTRet s a)
    f State# RealWorld
    realWorld# )
                    return a

    {-# NOINLINE runSTT #-}
    -- | Executes a computation in the 'STT' monad transformer
    runSTT :: Monad m => (forall s. STT s m a) -> m a
    runSTT :: forall (m :: * -> *) a. Monad m => (forall s. STT s m a) -> m a
    runSTT forall s. STT s m a
    m = let (STT State# s -> m (STTRet s a)
    f) = STT s m a
    forall s. STT s m a
    m
               in do (STTRet _st a) <- ( State# RealWorld -> m (STTRet RealWorld a)
    forall {s}. State# s -> m (STTRet s a)
    f State# RealWorld
    realWorld# )
                     return a

    -- Mutable arrays.

    {-# INLINE newSTArray #-}
    -- | Creates a new mutable array
    newSTArray :: (Ix i, Applicative m) =>
                  (i,i) -> e -> STT s m (STArray s i e)
    newSTArray :: forall i (m :: * -> *) e s.
    (Ix i, Applicative m) =>
    (i, i) -> e -> STT s m (STArray s i e)
    newSTArray (i, i)
    bnds e
    i = ST s (STArray s i e) -> STT s m (STArray s i e)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST ((i, i) -> e -> ST s (STArray s i e)
    forall i. Ix i => (i, i) -> e -> ST s (STArray s i e)
    forall (a :: * -> * -> *) e (m :: * -> *) i.
    (MArray a e m, Ix i) =>
    (i, i) -> e -> m (a i e)
    newArray (i, i)
    bnds e
    i)

    {-# INLINE boundsSTArray #-}
    -- | Returns the lowest and highest indices of the array
    boundsSTArray :: STArray s i e -> (i,i)
    boundsSTArray :: forall s i e. STArray s i e -> (i, i)
    boundsSTArray = STArray s i e -> (i, i)
    forall s i e. STArray s i e -> (i, i)
    STArray.boundsSTArray

    {-# INLINE numElementsSTArray #-}
    -- | Returns the number of elements in the array
    numElementsSTArray :: STArray s i e -> Int
    numElementsSTArray :: forall s i e. STArray s i e -> Int
    numElementsSTArray = STArray s i e -> Int
    forall s i e. STArray s i e -> Int
    STArray.numElementsSTArray

    {-# INLINE readSTArray #-}
    -- | Retrieves an element from the array
    readSTArray :: (Ix i, Applicative m) =>
                   STArray s i e -> i -> STT s m e
    readSTArray :: forall i (m :: * -> *) s e.
    (Ix i, Applicative m) =>
    STArray s i e -> i -> STT s m e
    readSTArray STArray s i e
    arr i
    i = ST s e -> STT s m e
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> i -> ST s e
    forall (a :: * -> * -> *) e (m :: * -> *) i.
    (MArray a e m, Ix i) =>
    a i e -> i -> m e
    readArray STArray s i e
    arr i
    i)

    {-# INLINE unsafeReadSTArray #-}
    unsafeReadSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
        Applicative m) =>
                         STArray s i e -> Int -> STT s m e
    unsafeReadSTArray :: forall (m :: * -> *) s i e.
    Applicative m =>
    STArray s i e -> Int -> STT s m e
    unsafeReadSTArray STArray s i e
    arr Int
    i = ST s e -> STT s m e
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> Int -> ST s e
    forall s i e. STArray s i e -> Int -> ST s e
    STArray.unsafeReadSTArray STArray s i e
    arr Int
    i)

    {-# INLINE writeSTArray #-}
    -- | Modifies an element in the array
    writeSTArray :: (Ix i, Applicative m) =>
                    STArray s i e -> i -> e -> STT s m ()
    writeSTArray :: forall i (m :: * -> *) s e.
    (Ix i, Applicative m) =>
    STArray s i e -> i -> e -> STT s m ()
    writeSTArray STArray s i e
    arr i
    i e
    e = ST s () -> STT s m ()
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> i -> e -> ST s ()
    forall (a :: * -> * -> *) e (m :: * -> *) i.
    (MArray a e m, Ix i) =>
    a i e -> i -> e -> m ()
    writeArray STArray s i e
    arr i
    i e
    e)

    {-# INLINE unsafeWriteSTArray #-}
    unsafeWriteSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
      Applicative m) =>
                          STArray s i e -> Int -> e -> STT s m ()
    unsafeWriteSTArray :: forall (m :: * -> *) s i e.
    Applicative m =>
    STArray s i e -> Int -> e -> STT s m ()
    unsafeWriteSTArray STArray s i e
    arr Int
    i e
    e = ST s () -> STT s m ()
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> Int -> e -> ST s ()
    forall s i e. STArray s i e -> Int -> e -> ST s ()
    STArray.unsafeWriteSTArray STArray s i e
    arr Int
    i e
    e)

    {-# INLINE freezeSTArray #-}
    -- | Copy a mutable array and turn it into an immutable array
    freezeSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
      Applicative m) =>
                     STArray s i e -> STT s m (Array i e)
    freezeSTArray :: forall (m :: * -> *) s i e.
    Applicative m =>
    STArray s i e -> STT s m (Array i e)
    freezeSTArray STArray s i e
    arr = ST s (Array i e) -> STT s m (Array i e)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> ST s (Array i e)
    forall s i e. STArray s i e -> ST s (Array i e)
    STArray.freezeSTArray STArray s i e
    arr)

    {-# INLINE unsafeFreezeSTArray #-}
    unsafeFreezeSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
      Applicative m) =>
                           STArray s i e -> STT s m (Array i e)
    unsafeFreezeSTArray :: forall (m :: * -> *) s i e.
    Applicative m =>
    STArray s i e -> STT s m (Array i e)
    unsafeFreezeSTArray STArray s i e
    arr = ST s (Array i e) -> STT s m (Array i e)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (STArray s i e -> ST s (Array i e)
    forall s i e. STArray s i e -> ST s (Array i e)
    STArray.unsafeFreezeSTArray STArray s i e
    arr)

    {-# INLINE thawSTArray #-}
    -- | Copy an immutable array and turn it into a mutable array
    thawSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
      Applicative m) =>
                   Array i e -> STT s m (STArray s i e)
    thawSTArray :: forall (m :: * -> *) i e s.
    Applicative m =>
    Array i e -> STT s m (STArray s i e)
    thawSTArray Array i e
    arr = ST s (STArray s i e) -> STT s m (STArray s i e)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (Array i e -> ST s (STArray s i e)
    forall i e s. Array i e -> ST s (STArray s i e)
    STArray.thawSTArray Array i e
    arr)

    {-# INLINE unsafeThawSTArray #-}
    unsafeThawSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
        Ix i,
    #endif
      Applicative m) =>
                         Array i e -> STT s m (STArray s i e)
    unsafeThawSTArray :: forall (m :: * -> *) i e s.
    Applicative m =>
    Array i e -> STT s m (STArray s i e)
    unsafeThawSTArray Array i e
    arr = ST s (STArray s i e) -> STT s m (STArray s i e)
    forall (m :: * -> *) s a. Applicative m => ST s a -> STT s m a
    liftST (Array i e -> ST s (STArray s i e)
    forall i e s. Array i e -> ST s (STArray s i e)
    STArray.unsafeThawSTArray Array i e
    arr)

    {-# INLINE runSTArray #-}
    -- | 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.
    runSTArray :: (
    #if __GLASGOW_HASKELL__ <= 710
      Ix i,
    #endif
    #if __GLASGOW_HASKELL__ <= 708
      Applicative m,
    #endif
      Monad m)
               => (forall s . STT s m (STArray s i e))
               -> m (Array i e)
    runSTArray :: forall (m :: * -> *) i e.
    Monad m =>
    (forall s. STT s m (STArray s i e)) -> m (Array i e)
    runSTArray forall s. STT s m (STArray s i e)
    st = (forall s. STT s m (Array i e)) -> m (Array i e)
    forall (m :: * -> *) a. Monad m => (forall s. STT s m a) -> m a
    runSTT (STT s m (STArray s i e)
    forall s. STT s m (STArray s i e)
    st STT s m (STArray s i e)
    -> (STArray s i e -> STT s m (Array i e)) -> STT s m (Array i e)
    forall a b. STT s m a -> (a -> STT s m b) -> STT s m b
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= STArray s i e -> STT s m (Array i e)
    forall (m :: * -> *) s i e.
    Applicative m =>
    STArray s i e -> STT s m (Array i e)
    unsafeFreezeSTArray)

    {-# NOINLINE unsafeIOToSTT #-}
    unsafeIOToSTT :: (Monad m, Functor m) => IO a -> STT s m a
    unsafeIOToSTT :: forall (m :: * -> *) a s. (Monad m, Functor m) => IO a -> STT s m a
    unsafeIOToSTT IO a
    m = a -> STT s m a
    forall a. a -> STT s m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> STT s m a) -> a -> STT s m a
    forall a b. (a -> b) -> a -> b
    $! IO a -> a
    forall a. IO a -> a
    unsafePerformIO IO a
    m

    {-# DEPRECATED unsafeSTToIO "Use unsafeSTTToIO instead" #-}
    unsafeSTToIO :: STT s IO a -> IO a
    unsafeSTToIO :: forall s a. STT s IO a -> IO a
    unsafeSTToIO STT s IO a
    m = (forall s. STT s IO a) -> IO a
    forall (m :: * -> *) a. Monad m => (forall s. STT s m a) -> m a
    runSTT ((forall s. STT s IO a) -> IO a) -> (forall s. STT s IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ STT s IO a -> STT s IO a
    forall a b. a -> b
    unsafeCoerce STT s IO a
    m

    unsafeSTTToIO :: STT s IO a -> IO a
    unsafeSTTToIO :: forall s a. STT s IO a -> IO a
    unsafeSTTToIO STT s IO a
    m = (forall s. STT s IO a) -> IO a
    forall (m :: * -> *) a. Monad m => (forall s. STT s m a) -> m a
    runSTT ((forall s. STT s IO a) -> IO a) -> (forall s. STT s IO a) -> IO a
    forall a b. (a -> b) -> a -> b
    $ STT s IO a -> STT s IO a
    forall a b. a -> b
    unsafeCoerce STT s IO a
    m

    -- This should work, as STRef and IORef should have identical internal representation
    unsafeSTRefToIORef  :: STRef s a -> IORef a
    unsafeSTRefToIORef :: forall s a. STRef s a -> IORef a
    unsafeSTRefToIORef STRef s a
    ref = STRef s a -> IORef a
    forall a b. a -> b
    unsafeCoerce STRef s a
    ref

    unsafeIORefToSTRef :: IORef a -> STRef s a
    unsafeIORefToSTRef :: forall a s. IORef a -> STRef s a
    unsafeIORefToSTRef IORef a
    ref = IORef a -> STRef s a
    forall a b. a -> b
    unsafeCoerce IORef a
    ref