
"Manuel M. T. Chakravarty" wrote:
* I am not a big fan of introducing an extra monad (`GUI' in this case). It can easily become a pain in programs that do a lot of "normal" IO as you have to lift all IO functions to GUI.
So you want various IO operations, that act not only in the IO monad, but in other monads also? Perhaps something like putStrLn :: (MonadIO io) => String -> io () Then writing you IO operations inside your GUI becomes trivial. Lets push this a bit with an implementation. -- a way of tunneling into the IO Monad class (Monad m) => MonadIO m where runIO :: IO v -> m v -- and the "default" IO monad. instance MonadIO IO where runIO m = m -- a sample GUI newtype GUI a = GUI { unGUI :: IO a } -- wibble instance Monad GUI where return a = GUI (return a) (GUI m) >>= k = GUI (m >>= \ r -> unGUI (k r)) -- how the GUI tunnels instance MonadIO GUI where runIO m = GUI m -- and an implementation of putStrLn putStrLn :: (MonadIO io) => String -> io () putStrLn str = runIO (Prelude.putStrLn str) -- You need to import the Prelude hiding putStrLn, -- the import putStrLn qualified, but it should be -- possible to develop a module that contains -- your favorite IO monadic things, behind which -- this magic is hidden. (I'm not arguing for/against the Clean GUI, but one of your points of reasoning). -- Andy Gill Galois Connections