Hi, On Wed, May 14, 2008 at 03:59:58PM +0300, Lauri Alanko wrote: > On Wed, May 14, 2008 at 10:11:17AM +0100, Edsko de Vries wrote: > > Suppose we have some data structure that uses HOAS; typically, a DSL > > with explicit sharing. For example: > > > > > data Expr = One | Add Expr Expr | Let Expr (Expr -> Expr) > > > > When I use such a data structure, I find myself writing expressions such > > as > > > > > Let foo $ \a -> > > > Let bar $ \b -> > > > Add a b > > > > It seems to me that there should be a monad here somewhere, so that I > > can write this approximately like > > > > do a <- foo > > b <- bar > > return (Add a b) > > Neat idea, but the monad can't work exactly as you propose, because > it'd break the monad laws: do { a <- foo; return a } should be equal > to foo, but in your example it'd result in Let foo id. > > However, with an explicit binding marker the continuation monad does > what you want: > > import Control.Monad.Cont > > data Expr = One | Add Expr Expr | Let Expr (Expr -> Expr) > > type ExprM = Cont Expr > > bind :: Expr -> ExprM Expr > bind e = Cont (Let e) > > runExprM :: ExprM Expr -> Expr > runExprM e = runCont e id > > Now you'd write your example as > > do a <- bind foo > b <- bind bar > return (Add a b)
Nice. That's certainly a step towards what I was looking for, although it requires slightly more "tags" than I was hoping for :) But I've incorporated it into my code and it's much better already :) You mention that a "direct" implementation of what I suggested would break the monad laws, as (foo) and (Let foo id) are not equal. But one might argue that they are in fact, in a sense, equivalent. Do you reckon that if it is acceptable that foo and do { a <- foo; return a } don't return equal terms (but equivalent terms), we can do still better? Thanks again, Edsko _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe