
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