Building pattern and trying monads

Hello cafe, I'm working on a project where the main goal of the program is building some complex output (e.g. a Haskell function, module, etc.). In this process there is almost always some partially finished product on which to work. Currently I'm modelling this with a wrapper around StateT containing the partial product but I'm having some doubts about this approach. On one of the projects there is some rule-based transformation which needs to be done. The problem is with the matching and applying the rules. The matches need to retrieve information from the monads in the stack, and the application of a rule changes values in the stack. However when a match fails the stack should be left *untouched* and another rule should be tried. The solution I've in mind depends on the stack being pure. When the monad stack is pure a rule can be applied, returning a maybe value (or having a MaybeT wrapper) and when returning Nothing (failed rule) reverting the stack to it's point before applying the rule. As I'm not quite sure about the design (nor good at software design) I've some questions about this approach. 1. Is there a better approach then using a state monad for building the 'products'? 2. My solution with saving/reverting monad-stacks seems quite a hassle/hack, so is it a good approach or is there something better? Thanks in advance, Lars

It's common to use a writer monad possibly stacked with other monads (e.g. a state monad for fresh variable names) for code generation that approximates "macro expansion" - i.e. one call in Haskell maps to one-or-more lines of code in the output language, no global transformations are permitted. If you want transformations, then it is likely you will need to model the syntax of the output language or an intermediate language to have something concrete to transform.

* L Corbijn
The solution I've in mind depends on the stack being pure. When the monad stack is pure a rule can be applied, returning a maybe value (or having a MaybeT wrapper) and when returning Nothing (failed rule) reverting the stack to it's point before applying the rule.
As I'm not quite sure about the design (nor good at software design) I've some questions about this approach. 1. Is there a better approach then using a state monad for building the 'products'?
If you need to interleave building your "products" and analyzing them, State seems a reasonable choice here.
2. My solution with saving/reverting monad-stacks seems quite a hassle/hack, so is it a good approach or is there something better?
You can use a backtracking monad here ([] or Logic). The key thing is to put the backtracking monad in the bottom of your stack (everything above it will be restored on mzero). On the other hand, if you want some "global" effects that should not be restored, you can put corresponding monads below LogicT in the stack. Example: > observe $ flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) ((),13) Note that "put 0" had no effect here, because it was followed by mzero. -- Roman I. Cheplyaka :: http://ro-che.info/

observe $ flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) ((),13)
If the only thing you need is backtracking, using LogicT might be a little
overkill, using Maybe in the bottom of you monad stack suits just fine:
case flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) of
Just x -> ....
Nothing -> ....
2012/5/27 Roman Cheplyaka
* L Corbijn
[2012-05-27 14:21:39+0200] The solution I've in mind depends on the stack being pure. When the monad stack is pure a rule can be applied, returning a maybe value (or having a MaybeT wrapper) and when returning Nothing (failed rule) reverting the stack to it's point before applying the rule.
As I'm not quite sure about the design (nor good at software design) I've some questions about this approach. 1. Is there a better approach then using a state monad for building the 'products'?
If you need to interleave building your "products" and analyzing them, State seems a reasonable choice here.
2. My solution with saving/reverting monad-stacks seems quite a hassle/hack, so is it a good approach or is there something better?
You can use a backtracking monad here ([] or Logic).
The key thing is to put the backtracking monad in the bottom of your stack (everything above it will be restored on mzero). On the other hand, if you want some "global" effects that should not be restored, you can put corresponding monads below LogicT in the stack.
Example:
observe $ flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) ((),13)
Note that "put 0" had no effect here, because it was followed by mzero.
-- Roman I. Cheplyaka :: http://ro-che.info/
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

* Yves Parès
observe $ flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) ((),13)
If the only thing you need is backtracking, using LogicT might be a little overkill, using Maybe in the bottom of you monad stack suits just fine:
case flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) of Just x -> .... Nothing -> ....
Indeed, I didn't realise that Maybe may be (no pun intended) sufficient here! -- Roman I. Cheplyaka :: http://ro-che.info/

Actually, I think the backtracking property here stems more from the
MonadPlus StateT instance than from the properties of Maybe.
(mplus a b runs a and b by passing explicitely the same state to them).
2012/5/28 Roman Cheplyaka
observe $ flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) ((),13)
If the only thing you need is backtracking, using LogicT might be a
* Yves Parès
[2012-05-28 11:28:22+0200] little overkill, using Maybe in the bottom of you monad stack suits just fine:
case flip runStateT 10 $ (put 0 >> mzero) <|> modify (+3) of Just x -> .... Nothing -> ....
Indeed, I didn't realise that Maybe may be (no pun intended) sufficient here!
-- Roman I. Cheplyaka :: http://ro-che.info/
participants (4)
-
L Corbijn
-
Roman Cheplyaka
-
Stephen Tetley
-
Yves Parès