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

Display warning for while loops inside lazy computation expressions for non-lazy types #364

Merged
merged 2 commits into from
Oct 7, 2020

Conversation

gusty
Copy link
Member

@gusty gusty commented Oct 6, 2020

With this PR we'll attempt to do as much as possible to help non-expert CE users to use generic CEs the right way.

To recap:

  • when using a generic CE we have to take into account whether the type involved is lazy or not. The default CE: monad is lazy.
  • if we use a lazy CE with a strict type, bad things can happen, from runtime errors to infinite loops, but as long as we don't use any advanced construct (try block, using or while) everything should work fine in any case.

So, regarding the advanced constructs:

  • for loops have a run-time "auto-sense" feature that checks if the type is really lazy, if is not they call the strict version of the construct.
  • try blocks have a compile-time check, since a lazy monad needs to define them, if they are not present a compiler error tells about the problem and how to fix it.

Now while-loops are the trickiest ones, because as opposed to for-loops the body is directly an expression, not a function, so when used within a strict type but in a lazy CE which has the wrong delay signature, the body of the while will be evaluated eagerly when passed as a parameter to the While method, so no chance to the auto-sense stuff, not even to throw a nice run-time error.

Also, as opposed to try-blocks, the while method is not compulsory, actually is not customizable so far.

So, no chance to do run-time or compile-time checks here.

The proposed solution

In this PR, we will introduce a compile-time check inside the While function that checks whether the type has a TryWith static method, that would be our way to "guess" if it's a lazy monad or not. If it fails it will display a compile-time warning.

Here's the trickiest part: I think this should be good enough as all lazy monads implemented here have a corresponding TryWith implementation, so if you get the warning using one of those types, it is really the case of misusing the CE.

But, it could be the rare case, that a user defined its own lazy monad without a TryWith because he's not planning to use try blocks, note that TryWith is normally unrelated to while loops.

In this case the warning will display as well, but in this case we're talking about an advanced user, so he should be able to implement a basic TryWith just to get rid of the warning, or simply use a #nowarn "10710" directive.

Conclusion: with this PR we're leaning on the safe side of the story and it will complete the picture of no surprising non CE expert users of the library, on the other hand there is a small chance that it will generate a warning on a very specific situation an advanced user can eventually run into and force him to either ignore it or implement a TryWith.

@gusty gusty mentioned this pull request Oct 6, 2020
@gusty gusty merged commit a8d3781 into master Oct 7, 2020
@gusty gusty deleted the gusty-while branch February 13, 2021 18:49
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

Successfully merging this pull request may close these issues.

1 participant