{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DerivingVia #-}
--
-- (c) The University of Glasgow 2002-2006
--

-- | The IO Monad with an environment
--
-- The environment is passed around as a Reader monad but
-- as its in the IO monad, mutable references can be used
-- for updating state.
--
module GHC.Data.IOEnv (
        IOEnv, -- Instance of Monad

        -- Monad utilities
        module GHC.Utils.Monad,

        -- Errors
        failM, failWithM,
        IOEnvFailure(..),

        -- Getting at the environment
        getEnv, setEnv, updEnv,

        runIOEnv, unsafeInterleaveM, uninterruptibleMaskM_,
        tryM, tryAllM, tryMostM, fixM,

        -- I/O operations
        IORef, newMutVar, readMutVar, writeMutVar, updMutVar,
        atomicUpdMutVar, atomicUpdMutVar'
  ) where

import GHC.Prelude

import GHC.Driver.Session
import GHC.Utils.Exception
import GHC.Unit.Module
import GHC.Utils.Panic

import Data.IORef       ( IORef, newIORef, readIORef, writeIORef, modifyIORef,
                          atomicModifyIORef, atomicModifyIORef' )
import System.IO.Unsafe ( unsafeInterleaveIO )
import System.IO        ( fixIO )
import Control.Monad
import Control.Monad.Trans.Reader
import Control.Monad.Catch (MonadCatch, MonadMask, MonadThrow)
import GHC.Utils.Monad
import Control.Applicative (Alternative(..))

----------------------------------------------------------------------
-- Defining the monad type
----------------------------------------------------------------------


newtype IOEnv env a = IOEnv (env -> IO a)
  deriving (a -> IOEnv env b -> IOEnv env a
(a -> b) -> IOEnv env a -> IOEnv env b
(forall a b. (a -> b) -> IOEnv env a -> IOEnv env b)
-> (forall a b. a -> IOEnv env b -> IOEnv env a)
-> Functor (IOEnv env)
forall a b. a -> IOEnv env b -> IOEnv env a
forall a b. (a -> b) -> IOEnv env a -> IOEnv env b
forall env a b. a -> IOEnv env b -> IOEnv env a
forall env a b. (a -> b) -> IOEnv env a -> IOEnv env b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> IOEnv env b -> IOEnv env a
$c<$ :: forall env a b. a -> IOEnv env b -> IOEnv env a
fmap :: (a -> b) -> IOEnv env a -> IOEnv env b
$cfmap :: forall env a b. (a -> b) -> IOEnv env a -> IOEnv env b
External instance of the constraint type Functor IO
Functor)
  deriving (Monad (IOEnv env)
e -> IOEnv env a
Monad (IOEnv env)
-> (forall e a. Exception e => e -> IOEnv env a)
-> MonadThrow (IOEnv env)
forall {env}. Monad (IOEnv env)
forall e a. Exception e => e -> IOEnv env a
forall env e a. Exception e => e -> IOEnv env a
forall (m :: * -> *).
Monad m -> (forall e a. Exception e => e -> m a) -> MonadThrow m
throwM :: e -> IOEnv env a
$cthrowM :: forall env e a. Exception e => e -> IOEnv env a
External instance of the constraint type MonadThrow IO
External instance of the constraint type MonadThrow IO
External instance of the constraint type forall (m :: * -> *) r. MonadThrow m => MonadThrow (ReaderT r m)
Evidence bound by a type signature of the constraint type Exception e
Evidence bound by a HsWrapper of the constraint type Exception e
Evidence bound by a HsWrapper of the constraint type Exception e
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
MonadThrow, MonadThrow (IOEnv env)
MonadThrow (IOEnv env)
-> (forall e a.
    Exception e =>
    IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a)
-> MonadCatch (IOEnv env)
IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a
forall env. MonadThrow (IOEnv env)
forall e a.
Exception e =>
IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a
forall env e a.
Exception e =>
IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a
forall (m :: * -> *).
MonadThrow m
-> (forall e a. Exception e => m a -> (e -> m a) -> m a)
-> MonadCatch m
catch :: IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a
$ccatch :: forall env e a.
Exception e =>
IOEnv env a -> (e -> IOEnv env a) -> IOEnv env a
External instance of the constraint type MonadCatch IO
External instance of the constraint type MonadCatch IO
External instance of the constraint type forall (m :: * -> *) r. MonadCatch m => MonadCatch (ReaderT r m)
Evidence bound by a type signature of the constraint type Exception e
Evidence bound by a HsWrapper of the constraint type Exception e
Evidence bound by a HsWrapper of the constraint type Exception e
Instance of class: MonadThrow of the constraint type forall env. MonadThrow (IOEnv env)
Instance of class: MonadThrow of the constraint type forall env. MonadThrow (IOEnv env)
MonadCatch, MonadCatch (IOEnv env)
MonadCatch (IOEnv env)
-> (forall b.
    ((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
    -> IOEnv env b)
-> (forall b.
    ((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
    -> IOEnv env b)
-> (forall a b c.
    IOEnv env a
    -> (a -> ExitCase b -> IOEnv env c)
    -> (a -> IOEnv env b)
    -> IOEnv env (b, c))
-> MonadMask (IOEnv env)
IOEnv env a
-> (a -> ExitCase b -> IOEnv env c)
-> (a -> IOEnv env b)
-> IOEnv env (b, c)
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
forall env. MonadCatch (IOEnv env)
forall b.
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
forall env b.
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
forall a b c.
IOEnv env a
-> (a -> ExitCase b -> IOEnv env c)
-> (a -> IOEnv env b)
-> IOEnv env (b, c)
forall env a b c.
IOEnv env a
-> (a -> ExitCase b -> IOEnv env c)
-> (a -> IOEnv env b)
-> IOEnv env (b, c)
forall (m :: * -> *).
MonadCatch m
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall b. ((forall a. m a -> m a) -> m b) -> m b)
-> (forall a b c.
    m a -> (a -> ExitCase b -> m c) -> (a -> m b) -> m (b, c))
-> MonadMask m
generalBracket :: IOEnv env a
-> (a -> ExitCase b -> IOEnv env c)
-> (a -> IOEnv env b)
-> IOEnv env (b, c)
$cgeneralBracket :: forall env a b c.
IOEnv env a
-> (a -> ExitCase b -> IOEnv env c)
-> (a -> IOEnv env b)
-> IOEnv env (b, c)
uninterruptibleMask :: ((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
$cuninterruptibleMask :: forall env b.
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
mask :: ((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
$cmask :: forall env b.
((forall a. IOEnv env a -> IOEnv env a) -> IOEnv env b)
-> IOEnv env b
External instance of the constraint type MonadMask IO
External instance of the constraint type MonadMask IO
External instance of the constraint type MonadMask IO
External instance of the constraint type MonadMask IO
External instance of the constraint type forall (m :: * -> *) r. MonadMask m => MonadMask (ReaderT r m)
Instance of class: MonadCatch of the constraint type forall env. MonadCatch (IOEnv env)
Instance of class: MonadCatch of the constraint type forall env. MonadCatch (IOEnv env)
MonadMask, Monad (IOEnv env)
Monad (IOEnv env)
-> (forall a. IO a -> IOEnv env a) -> MonadIO (IOEnv env)
IO a -> IOEnv env a
forall {env}. Monad (IOEnv env)
forall a. IO a -> IOEnv env a
forall env a. IO a -> IOEnv env a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: IO a -> IOEnv env a
$cliftIO :: forall env a. IO a -> IOEnv env a
External instance of the constraint type MonadIO IO
External instance of the constraint type MonadIO IO
External instance of the constraint type forall (m :: * -> *) r. MonadIO m => MonadIO (ReaderT r m)
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
MonadIO) via (ReaderT env IO)

unIOEnv :: IOEnv env a -> (env -> IO a)
unIOEnv :: IOEnv env a -> env -> IO a
unIOEnv (IOEnv env -> IO a
m) = env -> IO a
m

instance Monad (IOEnv m) where
    >>= :: IOEnv m a -> (a -> IOEnv m b) -> IOEnv m b
(>>=)  = IOEnv m a -> (a -> IOEnv m b) -> IOEnv m b
forall m a b. IOEnv m a -> (a -> IOEnv m b) -> IOEnv m b
thenM
    >> :: IOEnv m a -> IOEnv m b -> IOEnv m b
(>>)   = IOEnv m a -> IOEnv m b -> IOEnv m b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
Instance of class: Applicative of the constraint type forall {m}. Applicative (IOEnv m)
(*>)

instance MonadFail (IOEnv m) where
    fail :: String -> IOEnv m a
fail String
_ = IOEnv m a
forall env a. IOEnv env a
failM -- Ignore the string

instance Applicative (IOEnv m) where
    pure :: a -> IOEnv m a
pure = a -> IOEnv m a
forall a env. a -> IOEnv env a
returnM
    IOEnv m -> IO (a -> b)
f <*> :: IOEnv m (a -> b) -> IOEnv m a -> IOEnv m b
<*> IOEnv m -> IO a
x = (m -> IO b) -> IOEnv m b
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ m
env -> m -> IO (a -> b)
f m
env IO (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
External instance of the constraint type Applicative IO
<*> m -> IO a
x m
env )
    *> :: IOEnv m a -> IOEnv m b -> IOEnv m b
(*>) = IOEnv m a -> IOEnv m b -> IOEnv m b
forall m a b. IOEnv m a -> IOEnv m b -> IOEnv m b
thenM_

returnM :: a -> IOEnv env a
returnM :: a -> IOEnv env a
returnM a
a = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
_ -> a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
External instance of the constraint type Monad IO
return a
a)

thenM :: IOEnv env a -> (a -> IOEnv env b) -> IOEnv env b
thenM :: IOEnv env a -> (a -> IOEnv env b) -> IOEnv env b
thenM (IOEnv env -> IO a
m) a -> IOEnv env b
f = (env -> IO b) -> IOEnv env b
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> do { a
r <- env -> IO a
m env
env ;
                                         IOEnv env b -> env -> IO b
forall env a. IOEnv env a -> env -> IO a
unIOEnv (a -> IOEnv env b
f a
r) env
env })

thenM_ :: IOEnv env a -> IOEnv env b -> IOEnv env b
thenM_ :: IOEnv env a -> IOEnv env b -> IOEnv env b
thenM_ (IOEnv env -> IO a
m) IOEnv env b
f = (env -> IO b) -> IOEnv env b
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> do { a
_ <- env -> IO a
m env
env ; IOEnv env b -> env -> IO b
forall env a. IOEnv env a -> env -> IO a
unIOEnv IOEnv env b
f env
env })

failM :: IOEnv env a
failM :: IOEnv env a
failM = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
_ -> IOEnvFailure -> IO a
forall e a. Exception e => e -> IO a
Instance of class: Exception of the constraint type Exception IOEnvFailure
throwIO IOEnvFailure
IOEnvFailure)

failWithM :: String -> IOEnv env a
failWithM :: String -> IOEnv env a
failWithM String
s = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
_ -> IOError -> IO a
forall a. IOError -> IO a
ioError (String -> IOError
userError String
s))

data IOEnvFailure = IOEnvFailure

instance Show IOEnvFailure where
    show :: IOEnvFailure -> String
show IOEnvFailure
IOEnvFailure = String
"IOEnv failure"

instance Exception IOEnvFailure

instance ContainsDynFlags env => HasDynFlags (IOEnv env) where
    getDynFlags :: IOEnv env DynFlags
getDynFlags = do env
env <- IOEnv env env
forall env. IOEnv env env
getEnv
                     DynFlags -> IOEnv env DynFlags
forall (m :: * -> *) a. Monad m => a -> m a
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
return (DynFlags -> IOEnv env DynFlags) -> DynFlags -> IOEnv env DynFlags
forall a b. (a -> b) -> a -> b
$! env -> DynFlags
forall t. ContainsDynFlags t => t -> DynFlags
Evidence bound by a type signature of the constraint type ContainsDynFlags env
extractDynFlags env
env

instance ContainsModule env => HasModule (IOEnv env) where
    getModule :: IOEnv env Module
getModule = do env
env <- IOEnv env env
forall env. IOEnv env env
getEnv
                   Module -> IOEnv env Module
forall (m :: * -> *) a. Monad m => a -> m a
Instance of class: Monad of the constraint type forall {env}. Monad (IOEnv env)
return (Module -> IOEnv env Module) -> Module -> IOEnv env Module
forall a b. (a -> b) -> a -> b
$ env -> Module
forall t. ContainsModule t => t -> Module
Evidence bound by a type signature of the constraint type ContainsModule env
extractModule env
env

----------------------------------------------------------------------
-- Fundamental combinators specific to the monad
----------------------------------------------------------------------


---------------------------
runIOEnv :: env -> IOEnv env a -> IO a
runIOEnv :: env -> IOEnv env a -> IO a
runIOEnv env
env (IOEnv env -> IO a
m) = env -> IO a
m env
env


---------------------------
{-# NOINLINE fixM #-}
  -- Aargh!  Not inlining fixM alleviates a space leak problem.
  -- Normally fixM is used with a lazy tuple match: if the optimiser is
  -- shown the definition of fixM, it occasionally transforms the code
  -- in such a way that the code generator doesn't spot the selector
  -- thunks.  Sigh.

fixM :: (a -> IOEnv env a) -> IOEnv env a
fixM :: (a -> IOEnv env a) -> IOEnv env a
fixM a -> IOEnv env a
f = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> (a -> IO a) -> IO a
forall a. (a -> IO a) -> IO a
fixIO (\ a
r -> IOEnv env a -> env -> IO a
forall env a. IOEnv env a -> env -> IO a
unIOEnv (a -> IOEnv env a
f a
r) env
env))


---------------------------
tryM :: IOEnv env r -> IOEnv env (Either IOEnvFailure r)
-- Reflect UserError exceptions (only) into IOEnv monad
-- Other exceptions are not caught; they are simply propagated as exns
--
-- The idea is that errors in the program being compiled will give rise
-- to UserErrors.  But, say, pattern-match failures in GHC itself should
-- not be caught here, else they'll be reported as errors in the program
-- begin compiled!
tryM :: IOEnv env r -> IOEnv env (Either IOEnvFailure r)
tryM (IOEnv env -> IO r
thing) = (env -> IO (Either IOEnvFailure r))
-> IOEnv env (Either IOEnvFailure r)
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> IO r -> IO (Either IOEnvFailure r)
forall a. IO a -> IO (Either IOEnvFailure a)
tryIOEnvFailure (env -> IO r
thing env
env))

tryIOEnvFailure :: IO a -> IO (Either IOEnvFailure a)
tryIOEnvFailure :: IO a -> IO (Either IOEnvFailure a)
tryIOEnvFailure = IO a -> IO (Either IOEnvFailure a)
forall e a. Exception e => IO a -> IO (Either e a)
Instance of class: Exception of the constraint type Exception IOEnvFailure
try

-- XXX We shouldn't be catching everything, e.g. timeouts
tryAllM :: IOEnv env r -> IOEnv env (Either SomeException r)
-- Catch *all* exceptions
-- This is used when running a Template-Haskell splice, when
-- even a pattern-match failure is a programmer error
tryAllM :: IOEnv env r -> IOEnv env (Either SomeException r)
tryAllM (IOEnv env -> IO r
thing) = (env -> IO (Either SomeException r))
-> IOEnv env (Either SomeException r)
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> IO r -> IO (Either SomeException r)
forall e a. Exception e => IO a -> IO (Either e a)
External instance of the constraint type Exception SomeException
try (env -> IO r
thing env
env))

tryMostM :: IOEnv env r -> IOEnv env (Either SomeException r)
tryMostM :: IOEnv env r -> IOEnv env (Either SomeException r)
tryMostM (IOEnv env -> IO r
thing) = (env -> IO (Either SomeException r))
-> IOEnv env (Either SomeException r)
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> IO r -> IO (Either SomeException r)
forall a. IO a -> IO (Either SomeException a)
tryMost (env -> IO r
thing env
env))

---------------------------
unsafeInterleaveM :: IOEnv env a -> IOEnv env a
unsafeInterleaveM :: IOEnv env a -> IOEnv env a
unsafeInterleaveM (IOEnv env -> IO a
m) = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> IO a -> IO a
forall a. IO a -> IO a
unsafeInterleaveIO (env -> IO a
m env
env))

uninterruptibleMaskM_ :: IOEnv env a -> IOEnv env a
uninterruptibleMaskM_ :: IOEnv env a -> IOEnv env a
uninterruptibleMaskM_ (IOEnv env -> IO a
m) = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> IO a -> IO a
forall a. IO a -> IO a
uninterruptibleMask_ (env -> IO a
m env
env))

----------------------------------------------------------------------
-- Alternative/MonadPlus
----------------------------------------------------------------------

instance Alternative (IOEnv env) where
    empty :: IOEnv env a
empty   = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (IO a -> env -> IO a
forall a b. a -> b -> a
const IO a
forall (f :: * -> *) a. Alternative f => f a
External instance of the constraint type Alternative IO
empty)
    IOEnv env a
m <|> :: IOEnv env a -> IOEnv env a -> IOEnv env a
<|> IOEnv env a
n = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\env
env -> IOEnv env a -> env -> IO a
forall env a. IOEnv env a -> env -> IO a
unIOEnv IOEnv env a
m env
env IO a -> IO a -> IO a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
External instance of the constraint type Alternative IO
<|> IOEnv env a -> env -> IO a
forall env a. IOEnv env a -> env -> IO a
unIOEnv IOEnv env a
n env
env)

instance MonadPlus (IOEnv env)

----------------------------------------------------------------------
-- Accessing input/output
----------------------------------------------------------------------

newMutVar :: a -> IOEnv env (IORef a)
newMutVar :: a -> IOEnv env (IORef a)
newMutVar a
val = IO (IORef a) -> IOEnv env (IORef a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (a -> IO (IORef a)
forall a. a -> IO (IORef a)
newIORef a
val)

writeMutVar :: IORef a -> a -> IOEnv env ()
writeMutVar :: IORef a -> a -> IOEnv env ()
writeMutVar IORef a
var a
val = IO () -> IOEnv env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (IORef a -> a -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef a
var a
val)

readMutVar :: IORef a -> IOEnv env a
readMutVar :: IORef a -> IOEnv env a
readMutVar IORef a
var = IO a -> IOEnv env a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (IORef a -> IO a
forall a. IORef a -> IO a
readIORef IORef a
var)

updMutVar :: IORef a -> (a -> a) -> IOEnv env ()
updMutVar :: IORef a -> (a -> a) -> IOEnv env ()
updMutVar IORef a
var a -> a
upd = IO () -> IOEnv env ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (IORef a -> (a -> a) -> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef a
var a -> a
upd)

-- | Atomically update the reference.  Does not force the evaluation of the
-- new variable contents.  For strict update, use 'atomicUpdMutVar''.
atomicUpdMutVar :: IORef a -> (a -> (a, b)) -> IOEnv env b
atomicUpdMutVar :: IORef a -> (a -> (a, b)) -> IOEnv env b
atomicUpdMutVar IORef a
var a -> (a, b)
upd = IO b -> IOEnv env b
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (IORef a -> (a -> (a, b)) -> IO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef a
var a -> (a, b)
upd)

-- | Strict variant of 'atomicUpdMutVar'.
atomicUpdMutVar' :: IORef a -> (a -> (a, b)) -> IOEnv env b
atomicUpdMutVar' :: IORef a -> (a -> (a, b)) -> IOEnv env b
atomicUpdMutVar' IORef a
var a -> (a, b)
upd = IO b -> IOEnv env b
forall (m :: * -> *) a. MonadIO m => IO a -> m a
Instance of class: MonadIO of the constraint type forall env. MonadIO (IOEnv env)
liftIO (IORef a -> (a -> (a, b)) -> IO b
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef a
var a -> (a, b)
upd)

----------------------------------------------------------------------
-- Accessing the environment
----------------------------------------------------------------------

getEnv :: IOEnv env env
{-# INLINE getEnv #-}
getEnv :: IOEnv env env
getEnv = (env -> IO env) -> IOEnv env env
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> env -> IO env
forall (m :: * -> *) a. Monad m => a -> m a
External instance of the constraint type Monad IO
return env
env)

-- | Perform a computation with a different environment
setEnv :: env' -> IOEnv env' a -> IOEnv env a
{-# INLINE setEnv #-}
setEnv :: env' -> IOEnv env' a -> IOEnv env a
setEnv env'
new_env (IOEnv env' -> IO a
m) = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
_ -> env' -> IO a
m env'
new_env)

-- | Perform a computation with an altered environment
updEnv :: (env -> env') -> IOEnv env' a -> IOEnv env a
{-# INLINE updEnv #-}
updEnv :: (env -> env') -> IOEnv env' a -> IOEnv env a
updEnv env -> env'
upd (IOEnv env' -> IO a
m) = (env -> IO a) -> IOEnv env a
forall env a. (env -> IO a) -> IOEnv env a
IOEnv (\ env
env -> env' -> IO a
m (env -> env'
upd env
env))