[Haskell-cafe] Question on monad transformers stack

Jonathan Geddes geddes.jonathan at gmail.com
Tue Sep 28 09:03:16 EDT 2010


Arnaud,

You might also consider writing monad-agnostic code: code that doesn't
know which monad it is executing in.

For example:

>class (Monad g) => MonadGit g where
>   gitOp1 :: ....
>   gitOp2 :: ....
>   ....
>
>instance MonadGit Git where
>   gitOp1 = ...
>   gitOp2 = ...
>   ...
>
>intance MonadGit DebugGit where
>  gitOp1 = ...
>  gitOp2 = ...
>
>otherGitOp :: (MonadGit g) => a -> b -> g a
>otherGitOp = gitOp1 . gitOp2 . otherF . etc

In other words, you create a typeclass that (at least) two different
monads will implement. One which runs the code normally, while the
other performs the debug actions that you described. Then your "debug
flag" becomes a choice of which monad to begin execution in. Note that
this can be a bit cumbersome (but I don't think impossible) if the
debug flag has to be changed at runtime.

Hope this helps,

--Jonathan


On Tue, Sep 28, 2010 at 12:56 AM, Arnaud Bailly <arnaud.oqube at gmail.com> wrote:
> 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
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>


More information about the Haskell-Cafe mailing list