rust-lang / rust-lang/rfcs

Explore computational expressions in rust (do notation)

Open
#2,034 13 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

T-lang
Dominant language
Markdown
Stars
6.6k
Forks
1.7k
Avg merge
16h 14m
Merged PRs (30d)
1

Description

F# includes support for what they call computational expressions which seems to be an extremely useful and powerful abstraction which doesn't require a large number of extra syntax to support it. There is a gentle introduction here, an official documentation page, and a paper discussing the topic.

I'm not an expert and am actually quite new to the idea but I'm going to try to present the idea briefly below. See the links above for more thorough discussion of these topics. I think the idea is very interesting and if the rust developers haven't seen the idea, I should think it would be a useful concept in the future development of rust.

Also, I think it can be understood as an approach to make error handing in the functional style more agreeable and some people find that very appealing. I'm not going to try to explain in detail how it works because the article linked does a much better job that I would.


I view computational expressions somewhat as an inversion of implementing the iterator trait in rust. In rust, if you have a type which you implement the iterator trait for, you immediately gain access to all of the methods iterators provide and more importantly, the ability to use the for loop construct directly.

struct X;

// We implement this iterator trait
impl Iterator for X {}

let x = X;

// and in the *context of a for loop*, you gain the benefit of *clean iteration*
for i in x {}

In a computational expression, the situation is reversed: you implement the functionality, let's assume for the moment it was an iterator, and in the context of the type, you gain the benefit of a for loop construct.

Now, I'm not sure the previous analogy is fully accurate in F# for a for loop but for let, it is more precise. Consider the following testable example where a construct maybe_worker is defined which modifies how binding occurs to allow options have simple mathematical equations applied to them. This works correctly regardless of whether any of the options are None or otherwise.

maybe_worker {
    let! x = Some 3
    let! y = Some 4
    let! z = Some 5

    return x * y + z
}

This type of construct is quite general and as such, allows you a lot of flexibility to apply these bindings to do various types of extra work (such as logging) however you define it. Another interesting aspect is they don't create extra operators, as can be seen here. They have reused many of the normal keywords of the language in these constructs as a kind of extension seeming to add a lot of flexibility.

Also interestingly, since these types holding these operation variants are essentially adding side effects
to and slightly modifying operations, they have had great success using them with types such as async and seq among others.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the linked F# computational-expressions documentation, introduction, and paper, then compare the proposal with Rust's linked Iterator trait and for-loop behavior. The issue does not name Rust files or tests; done would require a concrete, agreed language-design proposal rather than an implementation edit.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.