content: {-# LANGUAGE Trustworthy #-}
  
  -----------------------------------------------------------------------------
  -- |
  -- Module      :  GHC.Internal.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 GHC.Internal.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 base-4.9.0.0
  instance MonadIO IO where
      liftIO = id
  
  