    {-# LANGUAGE Trustworthy #-}

    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Control.Monad.IO.Class
    -- Copyright   :  (c) Andy Gill 2001,
    --                (c) Oregon Graduate Institute of Science and Technology, 2001
    -- License     :  BSD-style (see the file LICENSE)
    --
    -- Maintainer  :  R.Paterson@city.ac.uk
    -- Stability   :  stable
    -- Portability :  portable
    --
    -- Class of monads based on @IO@.
    -----------------------------------------------------------------------------

    module Control.Monad.IO.Class (
        MonadIO(..)
      ) where

    import GHC.Internal.Base

    -- | 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)@

    class (Monad m) => MonadIO m where
        -- | 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__
        --
        --
        -- > 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
        -- @
        --
        liftIO :: IO a -> m a

    -- | @since 4.9.0.0
    instance MonadIO IO where
        liftIO :: forall a. IO a -> IO a
    liftIO = IO a -> IO a
    forall a. a -> a
    id