content: {-# LANGUAGE FlexibleContexts, FlexibleInstances, GeneralizedNewtypeDeriving, OverlappingInstances, UndecidableInstances #-}
  module Main where
  
  class (Monad m) => MonadIO m where
      -- | Lift a computation from the 'IO' monad.
      liftIO :: IO a -> m a
  
  instance MonadIO IO where
      liftIO = id
  
  class XMLGenerator m where
      genElement :: (Maybe String, String) -> m ()
  
  newtype IdentityT m a = IdentityT { runIdentityT :: m a }
      deriving (Functor, Applicative, Monad, MonadIO)
  
  instance (MonadIO m) => (XMLGenerator (IdentityT m)) where
      genElement _ = liftIO $ putStrLn "in genElement"
  
  main :: IO ()
  main =
      do runIdentityT web
         putStrLn "done."
  
  class (Widgets x) => MonadRender x
  class (XMLGenerator m)  => Widgets m
  -- instance Widgets (IdentityT IO) -- if you uncomment this, it will work
  instance (XMLGenerator m, MonadRender m) => Widgets m
  instance MonadRender (IdentityT IO)
  
  web :: ( MonadIO m
         , Widgets m
         , XMLGenerator m
         ) => m ()
  web =
      do liftIO $ putStrLn "before"
         genElement (Nothing, "p")
         return ()
  