Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First expression in mdo is eagerly evaluated #5

Open
rymndhng opened this issue May 22, 2016 · 3 comments
Open

First expression in mdo is eagerly evaluated #5

rymndhng opened this issue May 22, 2016 · 3 comments

Comments

@rymndhng
Copy link

I'm seeing that the first expression inside an mdo is always evaluated, which may execute side-effects before the monad is run.

For example:

(mdo 
  failure <- (throw (RuntimeException. "AHA!"))
  _ <- (right :something)      
  :success)

This throws the runtime exception before I try to execute it with monads.core/run-monad

@bwo
Copy link
Owner

bwo commented May 22, 2016

Yeah, I've actually run into this but haven't fixed it (obviously). A kind of stupid workaround for now is to just insert a do-nothing return expression at the beginning. Thanks for the report though, will work on a fix.

@bwo
Copy link
Owner

bwo commented May 22, 2016

I'll just drop some thoughts in here ...

Actually, on further thought, there is a real question about how to treat this. The above example translates thus:

(>>= (throw (RuntimeException. "AHA!"))
     (fn [failure] (>>= (right :something)
                        (fn [_] :success))))

And if you think of mdo as just sugar for a series of nested binds, then this is quite correct (and the reason for the problem becomes apparent, since >>= is a regular function). Basically, we always have eager evaluation, it's just that the evaluation of the later expressions doesn't take place until their post-macroexpansion enclosing functions are called. (Poor man's laziness, whereas Haskell has real laziness from the get-go so even the initial expression isn't evaluated until demanded.)

Of course it's possible to have mdo insert some extra fanciness (or just to insert the not-fancy workaround mentioned above, at the cost of traversing an extra bind at the beginning), but that make the relationship between mdo and >>= & friends less obvious. (>>= and >> etc. could also just be macros that delay their first argument, but that seems like it would involve a lot of overhead.)

It's still a PITA of course.

@rymndhng
Copy link
Author

Agree with your concerns. Thinking about it as syntactic sugar makes sense to "not" be the libraries problem.

My background isn't in haskell, but my mental model for mdo is that whatever is inside the mdo is expected to be lazy so that I can pass the computation around and potentially evaluate it in different contexts, i.e try/catch and transaction.

Again, I'm not sure if there's a good solution for this -- though at minimal maybe this could be added to the README.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants