[Haskell-cafe] Question on monad transformers stack

Arnaud Bailly arnaud.oqube at gmail.com
Tue Sep 28 02:56:48 EDT 2010


Hello Cafe,

I have the following type which represents some action using Git

> newtype (Monad m) => Git m a = Git { runGit :: ErrorT String (StateT Environment m) a }
>              deriving (Monad, MonadState Environment, MonadError String)

and the following typeclass whose purpose is to abstract away the
details of executing commands in the OS, with an obvious IO instance,
and to ease testing of commands effects:

> -- | A monad for simple execution of a process within the
> class (MonadError e m) => MonadExec e m  where
>   debug :: String -> m ()
>   exec  :: String -> [String] -> m String
>   -- ^Do not really execute commande but output the command string and arguments passed
>   exec' :: String -> [String] -> m String
>   exec' proc args = return $ program proc args

The type environment is :

> data Environment = Env { debugMode     :: Bool,
>                          baseDirectory :: FilePath,
>                          maven         :: FilePath,
>                          git           :: FilePath,
>                          p4            :: FilePath,
>                          javaHome      :: FilePath}
>                  deriving (Eq, Show, Read)

This follows the monad stack pattern presented in RWH and in Don
Stewart's presentation on scripting with haskell. Actually, what I am
trying to achieve is to be able to write my own scripts in Haskell.

What I would like to do is to be able to wrap each Git action occuring
in a MonadExec instance into a call to debug according to the status
of the debugMode flag in environment, in order to prevent the need of
explicit calls to debug. Something like the -v flag in bash...

I can imagine being able to do this using 2 different ways:
 - add a constraint on Git monad and write explicitly return and >>=
   to use debug
 - push the environment or part of it inside the MonadExec, for
   example as a Reader.

What is the "best" (i.e. most economical) way of doing this?

Thanks for your advices.

Arnaud Bailly


More information about the Haskell-Cafe mailing list