> Suppose I have the following class of monad transformers: 
> 
> class (Monad m, Monad (t m)) => MonadT t m where
>  lift :: m a -> t m a
> 
> and several instances of the class:
> 
> instance MonadT MT1 where ...
> instance MonadT MT2 where ...
> . . .
> instance MonadT MTn where ...
> 
> I obtain a new monad composing monad transformers through the IO monad:
> 
> type MyMonad = MT1 (MT2 (... (MTn IO)))
> 
> And now, if I want to lift "putStrLn" I must write:
> 
> myPutStrLn = lift . lift . ... lift . putStrLn
> 
> This works but looks ugly. 
> 
> The question is:
> Is there a way that the system could detect how many 
> lifts are necessary to select the right function?

Yes, there is a way. It's a bit painful but it works. The idea is to
overload the IO primitives as well. This is in accordance with the
approach that a computational feature (here IO) is encapsulated in a
superclass of Monad.

> class (Monad io) => IOMonad io where
>     putChar                   :: Char -> io ()
>     putStr                    :: String -> io ()
>     getChar                   :: io Char
>     getLine                   :: io String
>     getContents               :: io String
>     writeFile                 :: FilePath -> String -> io ()
>     appendFile                :: FilePath -> String -> io ()
>     readFile                  :: FilePath -> io String
>     fail                      :: IOError -> io a
>     catch                     :: io a -> (IOError -> io a) -> io a

Now, you have to lift the operations through the various monad
transformers (typically using lift) and to make IO an instance of
IOMonad.

> instance IOMonad IO where
>     putChar                   =  Prelude.putChar
>     putStr                    =  Prelude.putStr
>     getChar                   =  Prelude.getChar
>     getLine                   =  Prelude.getLine
>     getContents               =  Prelude.getContents
>     writeFile                 =  Prelude.writeFile
>     appendFile                =  Prelude.appendFile
>     readFile                  =  Prelude.readFile
>     fail                      =  Prelude.fail
>     catch                     =  Prelude.catch

HTH Ralf


Reply via email to