Control.Monad.IO.Unlift

unliftio-core-0.2.1.0: The MonadUnliftIO typeclass for unlifting monads to IO

Safe Haskell | Safe-Inferred
Language | Haskell2010

Control.Monad.IO.Unlift

Description

Please see the README.md file for information on using this package at https://www.stackage.org/package/unliftio-core.

Synopsis

- class MonadIO m => MonadUnliftIO (m :: Type -> Type) where
  - withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b
- newtype UnliftIO (m :: Type -> Type) = UnliftIO {
  - unliftIO :: forall a. m a -> IO a
  }
- askUnliftIO :: MonadUnliftIO m => m (UnliftIO m)
- askRunInIO :: MonadUnliftIO m => m (m a -> IO a)
- withUnliftIO :: MonadUnliftIO m => (UnliftIO m -> IO a) -> m a
- toIO :: MonadUnliftIO m => m a -> m (IO a)
- wrappedWithRunInIO :: MonadUnliftIO n => (n b -> m b) -> (forall a. m a -> n a) -> ((forall a. m a -> IO a) -> IO b) -> m b
- liftIOOp :: MonadUnliftIO m => (IO a -> IO b) -> m a -> m b
- class Monad m => MonadIO (m :: Type -> Type) where
  - liftIO :: IO a -> m a

# Documentation

class MonadIO m => MonadUnliftIO (m :: Type -> Type) where #

Monads which allow their actions to be run in `IO`.

While `MonadIO` allows an `IO` action to be lifted into another monad, this class captures the opposite concept: allowing you to capture the monadic context. Note that, in order to meet the laws given below, the intuition is that a monad must have no monadic state, but may have monadic context. This essentially limits `MonadUnliftIO` to `ReaderT` and `IdentityT` transformers on top of `IO`.

Laws. For any function `run` provided by `withRunInIO`, it must meet the monad transformer laws as reformulated for `MonadUnliftIO`:

-     run . return = return

-     run (m >>= f) = run m >>= run . f

Instances of `MonadUnliftIO` must also satisfy the following laws:

Identity law
  `withRunInIO (\run -> run m) = m`
Inverse law
  `withRunInIO (\_ -> m) = liftIO m`

As an example of an invalid instance, a naive implementation of `MonadUnliftIO (StateT s m)` might be

    withRunInIO inner =
      StateT $ \s ->
        withRunInIO $ \run ->
          inner (run . flip evalStateT s)

This breaks the identity law because the inner `run m` would throw away any state changes in `m`.

Since: 0.1.0.0

Methods

withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b #

Convenience function for capturing the monadic context and running an `IO` action with a runner function. The runner function is used to run a monadic action `m` in `IO`.

Since: 0.1.0.0

#### Instances

Instances details

MonadUnliftIO IO # |
Instance details Defined in Control.Monad.IO.Unlift Methods withRunInIO :: ((forall a. IO a -> IO a) -> IO b) -> IO b #
MonadUnliftIO m => MonadUnliftIO (IdentityT m) # |
Instance details Defined in Control.Monad.IO.Unlift Methods withRunInIO :: ((forall a. IdentityT m a -> IO a) -> IO b) -> IdentityT m b #
MonadUnliftIO m => MonadUnliftIO (ReaderT r m) # |
Instance details Defined in Control.Monad.IO.Unlift Methods withRunInIO :: ((forall a. ReaderT r m a -> IO a) -> IO b) -> ReaderT r m b #

newtype UnliftIO (m :: Type -> Type) #

The ability to run any monadic action `m a` as `IO a`.

This is more precisely a natural transformation. We need to new datatype (instead of simply using a `forall`) due to lack of support in GHC for impredicative types.

Since: 0.1.0.0

Constructors

UnliftIO |
Fields unliftIO :: forall a. m a -> IO a

askUnliftIO :: MonadUnliftIO m => m (UnliftIO m) #

Capture the current monadic context, providing the ability to run monadic actions in `IO`.

See `UnliftIO` for an explanation of why we need a helper datatype here.

Prior to version 0.2.0.0 of this library, this was a method in the `MonadUnliftIO` type class. It was moved out due to https://github.com/fpco/unliftio/issues/55.

Since: 0.1.0.0

askRunInIO :: MonadUnliftIO m => m (m a -> IO a) #

Same as `askUnliftIO`, but returns a monomorphic function instead of a polymorphic newtype wrapper. If you only need to apply the transformation on one concrete type, this function can be more convenient.

Since: 0.1.0.0

withUnliftIO :: MonadUnliftIO m => (UnliftIO m -> IO a) -> m a #

Convenience function for capturing the monadic context and running an `IO` action. The `UnliftIO` newtype wrapper is rarely needed, so prefer `withRunInIO` to this function.

Since: 0.1.0.0

toIO :: MonadUnliftIO m => m a -> m (IO a) #

Convert an action in `m` to an action in `IO`.

Since: 0.1.0.0

wrappedWithRunInIO #

Arguments

:: MonadUnliftIO n |
=> (n b -> m b) | The wrapper, for instance `IdentityT`.
-> (forall a. m a -> n a) | The inverse, for instance `runIdentityT`.
-> ((forall a. m a -> IO a) -> IO b) | The actual function to invoke `withRunInIO` with.
-> m b |

A helper function for implementing `MonadUnliftIO` instances. Useful for the common case where you want to simply delegate to the underlying transformer.

Note: You can derive `MonadUnliftIO` for newtypes without this helper function in `unliftio-core` 0.2.0.0 and later.

#### Example

Expand

    newtype AppT m a = AppT { unAppT :: ReaderT Int (ResourceT m) a }
      deriving (Functor, Applicative, Monad, MonadIO)

    -- Same as `deriving newtype (MonadUnliftIO)`
    instance MonadUnliftIO m => MonadUnliftIO (AppT m) where
      withRunInIO = wrappedWithRunInIO AppT unAppT

Since: 0.1.2.0

liftIOOp :: MonadUnliftIO m => (IO a -> IO b) -> m a -> m b #

A helper function for lifting `IO a -> IO b` functions into any `MonadUnliftIO`.

### Example

Expand

    liftedTry :: (Exception e, MonadUnliftIO m) => m a -> m (Either e a)
    liftedTry m = liftIOOp Control.Exception.try m

Since: 0.2.1.0

class Monad m => MonadIO (m :: Type -> Type) where #

Monads in which `IO` computations may be embedded. Any monad built by applying a sequence of monad transformers to the `IO` monad will be an instance of this class.

Instances should satisfy the following laws, which state that `liftIO` is a transformer of monads:

-     liftIO . return = return

-     liftIO (m >>= f) = liftIO m >>= (liftIO . f)

Methods

liftIO :: IO a -> m a #

Lift a computation from the `IO` monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. `IO` is the base monad for the stack).

### Example

Expand

    import Control.Monad.Trans.State -- from the "transformers" library

    printState :: Show s => StateT s IO ()
    printState = do
      state <- get
      liftIO $ print state

Had we omitted ``liftIO``, we would have ended up with this error:

    • Couldn't match type ‘IO’ with ‘StateT s IO’
     Expected type: StateT s IO ()
       Actual type: IO ()

The important part here is the mismatch between `StateT s IO ()` and ``IO` ()`.

Luckily, we know of a function that takes an ``IO` a` and returns an `(m a)`: ``liftIO``, enabling us to run the program and see the expected results:

    > evalStateT printState "hello"
    "hello"

    > evalStateT printState 3
    3

#### Instances

Instances details

MonadIO IO | Since: base-4.9.0.0
Instance details Defined in Control.Monad.IO.Class Methods liftIO :: IO a -> IO a #
MonadIO m => MonadIO (MaybeT m) |
Instance details Defined in Control.Monad.Trans.Maybe Methods liftIO :: IO a -> MaybeT m a #
(Monoid w, Functor m, MonadIO m) => MonadIO (AccumT w m) |
Instance details Defined in Control.Monad.Trans.Accum Methods liftIO :: IO a -> AccumT w m a #
MonadIO m => MonadIO (ExceptT e m) |
Instance details Defined in Control.Monad.Trans.Except Methods liftIO :: IO a -> ExceptT e m a #
MonadIO m => MonadIO (IdentityT m) |
Instance details Defined in Control.Monad.Trans.Identity Methods liftIO :: IO a -> IdentityT m a #
MonadIO m => MonadIO (ReaderT r m) |
Instance details Defined in Control.Monad.Trans.Reader Methods liftIO :: IO a -> ReaderT r m a #
MonadIO m => MonadIO (SelectT r m) |
Instance details Defined in Control.Monad.Trans.Select Methods liftIO :: IO a -> SelectT r m a #
MonadIO m => MonadIO (StateT s m) |
Instance details Defined in Control.Monad.Trans.State.Lazy Methods liftIO :: IO a -> StateT s m a #
MonadIO m => MonadIO (StateT s m) |
Instance details Defined in Control.Monad.Trans.State.Strict Methods liftIO :: IO a -> StateT s m a #
MonadIO m => MonadIO (WriterT w m) |
Instance details Defined in Control.Monad.Trans.Writer.CPS Methods liftIO :: IO a -> WriterT w m a #
(Monoid w, MonadIO m) => MonadIO (WriterT w m) |
Instance details Defined in Control.Monad.Trans.Writer.Lazy Methods liftIO :: IO a -> WriterT w m a #
(Monoid w, MonadIO m) => MonadIO (WriterT w m) |
Instance details Defined in Control.Monad.Trans.Writer.Strict Methods liftIO :: IO a -> WriterT w m a #
MonadIO m => MonadIO (ContT r m) |
Instance details Defined in Control.Monad.Trans.Cont Methods liftIO :: IO a -> ContT r m a #
MonadIO m => MonadIO (RWST r w s m) |
Instance details Defined in Control.Monad.Trans.RWS.CPS Methods liftIO :: IO a -> RWST r w s m a #
(Monoid w, MonadIO m) => MonadIO (RWST r w s m) |
Instance details Defined in Control.Monad.Trans.RWS.Lazy Methods liftIO :: IO a -> RWST r w s m a #
(Monoid w, MonadIO m) => MonadIO (RWST r w s m) |
Instance details Defined in Control.Monad.Trans.RWS.Strict Methods liftIO :: IO a -> RWST r w s m a #