[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