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

Add RFC For Algebraic Effects #73

Closed
wants to merge 3 commits into from

Conversation

Projects
None yet
@thehydroimpulse
Copy link

thehydroimpulse commented May 8, 2014

No description provided.

@nrc

This comment has been minimized.

Copy link
Member

nrc commented May 8, 2014

I'm a big fan of effects systems and would love to see something in Rust some day, but I believe that there would need to be considerable research work done to adapt any of the existing systems to Rust. This is not going to happen for 1.0, and probably not 2.0 or 3.0 either. So this is probably not the best place to discuss it. I propose we close this RFC. If anyone is interested in pursuing this, it is probably better done as a research project. I'm sure people would happy to collaborate on that.


Safety is the cornerstone of the language (within the realms that a systems language allows — i.e., practicality). Pure functions, in languages like Haskell, don't allow any side effects, but real applications do. Things like state, communication over the network, file I/O, etc... Above all that, real systems may fail.

Haskell, for example, solves such problems with the use of monads and monad transformers. However, there are problems with using such a tool (See the paper for details).

This comment has been minimized.

@huonw

huonw May 8, 2014

Member

Do you have a two sentence summary of these problems?

This comment has been minimized.

@thehydroimpulse

thehydroimpulse May 9, 2014

Author

I'll add it to the RFC.


# Summary

(Some of the ideas and concepts are inspired by the [effects proposal in the Rust wiki](https://github.com/mozilla/rust/wiki/Proposal-for-effects) written by [@cartazio](https://github.com/cartazio))

This comment has been minimized.

@huonw

huonw May 8, 2014

Member

(Are you specifically referring to the paragraph at the end? Because actual proposal was written by @bblum: history.)

This comment has been minimized.

@thehydroimpulse

thehydroimpulse May 8, 2014

Author

@huonw Ahh, should of checked the history. I'll change it to specify the correct author.

@bill-myers

This comment has been minimized.

Copy link

bill-myers commented May 9, 2014

@nick29581 Why does an effect system need any research at all? (beyond just trying to see if it's too much of a burden or not)

It is relatively easy to design and implement, and the real hard problem is making the decision that the positives outweigh the need to specify whether functions have side effects or not, and the potential inflexibility in being unable to implement side-effect-free traits using side effects.

And that decision MUST be made before 1.0, because it requires changing ALL code to denote whether it has side effects or not, and is of course not backwards compatible at all (the changes can be mostly automated using inference though, but extern functions, unsafe blocks, traits and public APIs will need manual attention).

There is also a much simpler (but less powerful) way to have an effect system that this RFC: just have a single effect for I/O and usage of mutable static and task-local variables, and denote it by writing "fn" for side-effect free functions, and "sub" for subroutines with side effects, and then split "unsafe" into "unsafe" (inferred side effects), "pure_unsafe" (forces no side effects) and "io_unsafe" (forces side effects).

Regarding this RFC, it's fine except for the fact that "Unsafe" makes no sense to have as an effect: what actually matters is which side effects the unsafe blocks actually cause, which they should be forced to declare, and whether the module has the privilege to have any unsafe blocks at all (which should be handled by the loading mechanism).

Also, "Fail" as an effect is far more problematic that the RFC indicates since just calling functions can intrinsically fail due to stack overflow, so you'd need to ban recursion, indirect calls without a stack usage limit, and have static stack analysis to ensure that there's enough stack, and also ban memory allocation, since that can also always fail too.

Added a summary of the problems using monads and monad transformers t…
…o express effects that the paper describes. Added note of the correct author of the original proposal.
@thehydroimpulse

This comment has been minimized.

Copy link
Author

thehydroimpulse commented May 9, 2014

@bill-myers

And that decision MUST be made before 1.0, because it requires changing ALL code to denote whether it has side effects or not, and is of course not backwards compatible at all (the changes can be mostly automated using inference though, but extern functions, unsafe blocks, traits and public APIs will need manual attention).

While I agree that having this decision be made sooner rather than later is best, the ultimate purpose was to allow backwards-compatibility. Overall, an algebraic effects system isn't exactly mainstream and new comers won't want to touch it at the beginning. Thus, there would be 0 enforcements (wont(Effect1, ...EffectN)) by default (Actually, you would simply enforce the top-level effect Anything, which would exclude things like Unsafe to match the current semantics). However, effects could still be inferred automatically. One who learns about effects or wants to take advantage of them can start to introduce enforcements when they please to (I think it would be unrealistic to enforce enforcements to all Rust programs. That'd make it a no go for sure).

Regarding this RFC, it's fine except for the fact that "Unsafe" makes no sense to have as an effect: what actually matters is which side effects the unsafe blocks actually cause, which they should be forced to declare, and whether the module has the privilege to have any unsafe blocks at all (which should be handled by the loading mechanism).

I think Unsafe would be a top-level effect where other effects can take place (and those are probably what you want to pay attention to). That's if you don't want to force the user to annotate effects, which was the original goal of the RFC so it's optional.

You could make an exception for unsafe blocks, where you must annotate (because the compiler won't be able to infer many cases).

Also, "Fail" as an effect is far more problematic that the RFC indicates since just calling functions can intrinsically fail due to stack overflow, so you'd need to ban recursion, indirect calls without a stack usage limit, and have static stack analysis to ensure that there's enough stack, and also ban memory allocation, since that can also always fail too.

That's one of the major issues with an effects system (and I should probably emphasis it in the RFC). Any useful code (this includes functions calls and such) in that context is ultimately able to fail. So perhaps it's not a realistic effect that one could use, or there would have to be limits in-place that has a trustme(wont(Fail)).

For example, assert would have to have a Fail effect (if one were to exist), but if you have an assert call in the destructure (or any memory functions) then the destructure could fail. One of the goals is to be able to have a wont(Fail) so that there's no memory leaks if the task fails.

@cmr

This comment has been minimized.

Copy link
Member

cmr commented May 10, 2014

First reaction: I liked the proposal when bblum made it, and I like it now. I look forward to a Rust with a system that is at least as powerful as this in it.

@cmr

This comment has been minimized.

Copy link
Member

cmr commented May 10, 2014

Thanks @thehydroimpulse for writing it up!

@aochagavia

This comment has been minimized.

Copy link
Contributor

aochagavia commented May 10, 2014

Won't this cause a lot of boilerplate like Java's throws keyword? Here is an interesting discussion about possible consequences of this approach (in other programming languages): http://ericlippert.com/2014/03/03/living-with-unchecked-exceptions/. See also http://www.artima.com/intv/handcuffs.html.

@thehydroimpulse

This comment has been minimized.

Copy link
Author

thehydroimpulse commented May 10, 2014

@aochagavia No, I don't think it would. That was a concern of mine, and I don't like how D does it (Not really an effect system, just a bunch of keywords like pure) where it becomes way too verbose.

The effect annotation won't be needed most of the time effect(Effect1, ...EffectN). The compiler would be able to infer it. The enforcements is the main place where verbosity might be possible, but by using top-level effects, one can mitigate it.

@aochagavia

This comment has been minimized.

Copy link
Contributor

aochagavia commented May 10, 2014

@thehydroimpulse That sounds really nice!

@gsingh93

This comment has been minimized.

Copy link

gsingh93 commented May 10, 2014

@thehydroimpulse I'm not sure I like the sound of "the effect annotation won't be needed most of the time". I hate how in C++ a lot of optimizations happen most of the time, but I never know in what situations they occur or don't occur, so the only way to make sure is to write the code differently to make sure it's a situation where the optimization will definitely happen or confirm by looking at the assembly. However, if the specific cases where the developer will have to manually specify the effects is clear, than I'm fine with that.

@Valloric

This comment has been minimized.

Copy link

Valloric commented May 10, 2014

This RFC looks really nice, but like others, I'm concerned it might suffer the same fate as Java's checked exceptions. Those also looked like a great idea on paper but with experience turned out to be a bad idea.

If this were implemented, it might be a good idea to first have it behind a feature gate until we're certain it's a net positive.

@thehydroimpulse

This comment has been minimized.

Copy link
Author

thehydroimpulse commented May 10, 2014

@gsingh93 The reason I say most is because there would be cases where the compiler might not be able to infer the effects. For example, code within unsafe blocks is harder to understand from a compiler's point of view because there are a lot less restrictions in place.

There are a couple solutions to this problem:

  • If the compiler cannot infer an effect it, then a warning could be shown (similar to lifetimes).
  • Code that has unsafe blocks must annotate it's side-effects, otherwise an error would be thrown.

@Valloric it honestly depends on the amount of effects. I'll update the RFC talking about user defined effects and how I'd be against it. It also depends on how much you wish to enforce effects. Again, I wouldn't want them to be forced upon users who don't like them, have no idea what they are, or don't care about them.

effect Anything
```

The first letter of each word in effects are capitalized, the remaining letters are lowercased. `Fail`, `GC`, `Unsafe`, `IO`.

This comment has been minimized.

@lilyball

lilyball May 10, 2014

Contributor

GC and IO do not have the remaining letters lowercased.

This comment has been minimized.

@thehydroimpulse

thehydroimpulse May 10, 2014

Author

I'm treating acronyms as two separate words. Instead of GarbageCollection, it's GC.

Cleanup RFC
* Remove the `Unsafe` effect.
* List all needed keywords.
* Rename `wont` to `forbid`
* Rename `Fail` to `Failure` to be gramatically correct with the use
  of `forbid`.
* Explain the `Failure` problems as discussed in the comments.
* Mention the unresolved questions about compiler inference (when it
  can't do so)
@pnkfelix

This comment has been minimized.

Copy link
Member

pnkfelix commented May 16, 2014

I'm with @nick29581 : I'm also a big fan of effects systems, but think it is premature to try to integrate one into Rust now, and thus I think we should close this RFC.

(At the very least, we would need to figure out our language versioning story before we try even to lay the groundwork for something like this.)

@brson

This comment has been minimized.

Copy link
Contributor

brson commented May 20, 2014

Effects systems are frequently requested, and the response is always that to do so would be far beyond Rust's complexity budget. Closing.

@brson brson closed this May 20, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.