    {-# LANGUAGE CPP #-}
    {-# LANGUAGE NoImplicitPrelude #-}
    {-# LANGUAGE FlexibleContexts #-}

    #if __GLASGOW_HASKELL__ >= 704
    {-# LANGUAGE Safe #-}
    #endif

    {- |
    Module      :  Data.IORef
    Copyright   :  Liyang HU, Bas van Dijk
    License     :  BSD-style

    Maintainer  :  Bas van Dijk <v.dijk.bas@gmail.com>
    Stability   :  experimental

    This is a wrapped version of "Data.IORef" with types
    generalised from 'IO' to all monads in 'MonadBase'.
    -}

    module Data.IORef.Lifted
        ( IORef
        , newIORef
        , readIORef
        , writeIORef
        , modifyIORef
    #if MIN_VERSION_base(4,6,0)
        , modifyIORef'
    #endif
        , atomicModifyIORef
    #if MIN_VERSION_base(4,6,0)
        , atomicModifyIORef'
        , atomicWriteIORef
    #endif
        , mkWeakIORef
        ) where

    --------------------------------------------------------------------------------
    -- Imports
    --------------------------------------------------------------------------------

    -- from base:
    import Data.IORef ( IORef )
    import qualified Data.IORef as R
    import System.IO ( IO )
    import System.Mem.Weak ( Weak )
    import Prelude ( (.) )

    -- from transformers-base:
    import Control.Monad.Base ( MonadBase, liftBase )

    -- from monad-control:
    import Control.Monad.Trans.Control ( MonadBaseControl, liftBaseDiscard )

    #include "inlinable.h"

    --------------------------------------------------------------------------------
    -- * IORefs
    --------------------------------------------------------------------------------

    -- | Generalized version of 'R.newIORef'.
    newIORef :: MonadBase IO m => a -> m (IORef a)
    newIORef :: forall (m :: * -> *) a. MonadBase IO m => a -> m (IORef a)
    newIORef = IO (IORef a) -> m (IORef a)
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO (IORef a) -> m (IORef a))
    -> (a -> IO (IORef a)) -> a -> m (IORef a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> IO (IORef a)
    forall a. a -> IO (IORef a)
    R.newIORef
    {-# INLINABLE newIORef #-}

    -- | Generalized version of 'R.readIORef'.
    readIORef :: MonadBase IO m => IORef a -> m a
    readIORef :: forall (m :: * -> *) a. MonadBase IO m => IORef a -> m a
    readIORef = IO a -> m a
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO a -> m a) -> (IORef a -> IO a) -> IORef a -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> IO a
    forall a. IORef a -> IO a
    R.readIORef
    {-# INLINABLE readIORef #-}

    -- | Generalized version of 'R.writeIORef'.
    writeIORef :: MonadBase IO m => IORef a -> a -> m ()
    writeIORef :: forall (m :: * -> *) a. MonadBase IO m => IORef a -> a -> m ()
    writeIORef IORef a
    r = IO () -> m ()
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO () -> m ()) -> (a -> IO ()) -> a -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> a -> IO ()
    forall a. IORef a -> a -> IO ()
    R.writeIORef IORef a
    r
    {-# INLINABLE writeIORef #-}

    -- | Generalized version of 'R.modifyIORef'.
    modifyIORef :: MonadBase IO m => IORef a -> (a -> a) -> m ()
    modifyIORef :: forall (m :: * -> *) a.
    MonadBase IO m =>
    IORef a -> (a -> a) -> m ()
    modifyIORef IORef a
    r = IO () -> m ()
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO () -> m ()) -> ((a -> a) -> IO ()) -> (a -> a) -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> (a -> a) -> IO ()
    forall a. IORef a -> (a -> a) -> IO ()
    R.modifyIORef IORef a
    r
    {-# INLINABLE modifyIORef #-}

    -- | Generalized version of 'R.atomicModifyIORef'.
    atomicModifyIORef :: MonadBase IO m => IORef a -> (a -> (a, b)) -> m b
    atomicModifyIORef :: forall (m :: * -> *) a b.
    MonadBase IO m =>
    IORef a -> (a -> (a, b)) -> m b
    atomicModifyIORef IORef a
    r = IO b -> m b
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO b -> m b) -> ((a -> (a, b)) -> IO b) -> (a -> (a, b)) -> m b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> (a -> (a, b)) -> IO b
    forall a b. IORef a -> (a -> (a, b)) -> IO b
    R.atomicModifyIORef IORef a
    r
    {-# INLINABLE atomicModifyIORef #-}

    #if MIN_VERSION_base(4,6,0)
    -- | Generalized version of 'R.modifyIORef''.
    modifyIORef' :: MonadBase IO m => IORef a -> (a -> a) -> m ()
    modifyIORef' :: forall (m :: * -> *) a.
    MonadBase IO m =>
    IORef a -> (a -> a) -> m ()
    modifyIORef' IORef a
    r = IO () -> m ()
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO () -> m ()) -> ((a -> a) -> IO ()) -> (a -> a) -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> (a -> a) -> IO ()
    forall a. IORef a -> (a -> a) -> IO ()
    R.modifyIORef' IORef a
    r
    {-# INLINABLE modifyIORef' #-}

    -- | Generalized version of 'R.atomicModifyIORef''.
    atomicModifyIORef' :: MonadBase IO m => IORef a -> (a -> (a, b)) -> m b
    atomicModifyIORef' :: forall (m :: * -> *) a b.
    MonadBase IO m =>
    IORef a -> (a -> (a, b)) -> m b
    atomicModifyIORef' IORef a
    r = IO b -> m b
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO b -> m b) -> ((a -> (a, b)) -> IO b) -> (a -> (a, b)) -> m b
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> (a -> (a, b)) -> IO b
    forall a b. IORef a -> (a -> (a, b)) -> IO b
    R.atomicModifyIORef' IORef a
    r
    {-# INLINABLE atomicModifyIORef' #-}

    -- | Generalized version of 'R.atomicWriteIORef'.
    atomicWriteIORef :: MonadBase IO m => IORef a -> a -> m ()
    atomicWriteIORef :: forall (m :: * -> *) a. MonadBase IO m => IORef a -> a -> m ()
    atomicWriteIORef IORef a
    r = IO () -> m ()
    forall α. IO α -> m α
    forall (b :: * -> *) (m :: * -> *) α. MonadBase b m => b α -> m α
    liftBase (IO () -> m ()) -> (a -> IO ()) -> a -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> a -> IO ()
    forall a. IORef a -> a -> IO ()
    R.atomicWriteIORef IORef a
    r
    #endif

    -- | Generalized version of 'R.mkWeakIORef'.
    --
    -- Note any monadic side effects in @m@ of the \"finalizer\" computation
    -- are discarded.
    mkWeakIORef :: MonadBaseControl IO m => IORef a -> m () -> m (Weak (IORef a))
    mkWeakIORef :: forall (m :: * -> *) a.
    MonadBaseControl IO m =>
    IORef a -> m () -> m (Weak (IORef a))
    mkWeakIORef = (IO () -> IO (Weak (IORef a))) -> m () -> m (Weak (IORef a))
    forall (b :: * -> *) (m :: * -> *) a.
    MonadBaseControl b m =>
    (b () -> b a) -> m () -> m a
    liftBaseDiscard ((IO () -> IO (Weak (IORef a))) -> m () -> m (Weak (IORef a)))
    -> (IORef a -> IO () -> IO (Weak (IORef a)))
    -> IORef a
    -> m ()
    -> m (Weak (IORef a))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IORef a -> IO () -> IO (Weak (IORef a))
    forall a. IORef a -> IO () -> IO (Weak (IORef a))
    R.mkWeakIORef
    {-# INLINABLE mkWeakIORef #-}