-
Notifications
You must be signed in to change notification settings - Fork 90
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
Add lazily evaluated versions of the conditional functions for applicatives and monads #313
base: master
Are you sure you want to change the base?
Add lazily evaluated versions of the conditional functions for applicatives and monads #313
Conversation
Unless the One potential argument for adding these would be if it's expensive to construct the |
@garyb you're right the side effects are not evaluated and I had a bad foreign import. I've changed the PR content to focus on the issue of effects that are expensive to compute. An example I've run into where the effects are expensive to construct is when using a JS logging framework: foreign import log :: String -> Effect Unit
main :: Effect Unit
main = do
ifM (...) (...) (log "...") Another small advantage of the function is that it can be more ergonomic to write |
@garyb could you please take another look at this? |
src/Control/Bind.purs
Outdated
-- | Similar to `ifM` but for use in cases where one of the monadic actions may | ||
-- | be expensive to compute. As PureScript is not lazy, the standard `ifM` has |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps "construct" rather than "compute" in this first sentence? And really I think that would suffice for the explanation, elaborating further on strict eval semantics only really applies to people who are newly coming to PS from Haskell. 😉
Having the code example is still good though 👍
Thanks @garyb I've cut down the |
I just realised all the other comments refer to performing an action lazily, could you update those too? (Sorry) Also there's an unused dependency that is causing the build failure just now. 😉 |
Thanks @garyb no problem :) I've reworded them from |
Hey @garyb could this please be merged? |
Sorry sorry, I've been crazy busy lately. Perhaps "Construct and evaluate" since it sounds like now it's just constructing them but not doing anything with them? |
Thanks @garyb no worries :) I've reworded it like this: -- | Perform a monadic action when a condition is true, where the conditional
-- | value is also in a monadic context.
whenM :: forall m. Monad m => m Boolean -> m Unit -> m Unit
whenM mb m = ifM mb m $ pure unit
-- | Perform a monadic action when a condition is true, without constructing it
-- | otherwise, where the conditional value is also in a monadic context.
whenM' :: forall m a. Monad m => (a -> m Boolean) -> (a -> m Unit) -> a -> m Unit
whenM' mb m = ifM' mb m \_ -> pure unit I think it makes it a lot clearer that they both will only evaluate the monadic action when the condition is true, but only |
Hey @garyb so sorry to tag you again in this since you are busy with other things but I'd really like to complete this PR, do you have a moment to approve it? |
ifM
,whenM
andunlessM
are really helpful for handling monads expressively. However, they require both of the possible outputs to be constructed. This can be problematic when the Monad isEffect
, as PureScript is strictly evaluated, since both the side effects will still need to be constructed, even if they are not launched. This is because they may be expensive to compute especially if they use the imported JS functions.Here is an example where a lazily evaluated version
ifM'
would be helpful:This PR creates lazy versions of each of the conditional functions for Applicatives and Monads:
ifM'
unless'
unlessM'
when'
whenM'
This is following the same approach as
maybe'
:Checklist: