Stream: ideas

Topic: Purity Inference


view this post on Zulip Richard Feldman (Aug 28 2024 at 13:44):

I wrote up a proposal for something I think could have a huge positive impact on Roc - https://docs.google.com/document/d/1siZalWbCI8dkW5wWRg_0KOXqiPMofkbwy0KdfQzp1H4/edit?usp=sharing

any feedback welcome!

edit: there is now a thread for a v2 of the proposal based on feedback in this thread! #ideas > Purity Inference proposal v2

view this post on Zulip Agus Zubiaga (Aug 28 2024 at 15:30):

Is "Dead code elimination is maximally effective" intentionally removed from the second list of benefits?

view this post on Zulip Agus Zubiaga (Aug 28 2024 at 15:32):

I feel like this proposal doesn't change that because things like import side effects would still be impossible (only functions can be effectful)

view this post on Zulip Richard Feldman (Aug 28 2024 at 15:49):

oops, fixed!

view this post on Zulip drew (Aug 28 2024 at 17:56):

This is a fascinating idea. One note -- as an outsider who occasionally checks in on the ecosystem, I feel like the language is accumulating a lot of sugar and symbols. If you're in the community, adding them gradually probably feels fine, but right now (assuming this proposal would be added), i'm thinking about seeing !, _, *, ?, ->, ,, and =>. it feels somewhat overwhelming for a language bills itself as friendly. perhaps some of this is related to the desire to not have overly-general solutions (e.g. backpassing) and perhaps my perspective is totally off base. but this combined with the number of module types starts to feel either overwhelming or that some more general solution would actually end up being simpler. i hope this isn't coming off as negative, as i think the proposal is very cool, but wanted to just call out this perspective.

view this post on Zulip Richard Feldman (Aug 28 2024 at 17:57):

that's a great point!

view this post on Zulip drew (Aug 28 2024 at 17:57):

i do think the simplification / merging of Task with Result feels intuitive

view this post on Zulip drew (Aug 28 2024 at 17:58):

and very interesting

view this post on Zulip drew (Aug 28 2024 at 17:58):

unison uses ' in signatures to represent effectful code, it is literally syntactic sugar for {} -> ...

view this post on Zulip drew (Aug 28 2024 at 17:58):

i'm not sure i love it, but interesting prior art none the less

view this post on Zulip Richard Feldman (Aug 28 2024 at 17:59):

one related data point is that Ruby code has all of those symbols (except for * in types, which we're talking about removing anyway) and I haven't heard people finding Ruby hard for beginners to learn or read

view this post on Zulip Richard Feldman (Aug 28 2024 at 17:59):

drew said:

unison uses ' in signatures to represent effectful code, it is literally syntactic sugar for {} -> ...

yeah, I looked at how they do it and ! feels like a more natural symbol to me :big_smile:

view this post on Zulip drew (Aug 28 2024 at 18:00):

agreed. it does feel a bit odd that there's an asymmetry between the value and type levels (e.g. ? vs !)

view this post on Zulip Alexander Pyattaev (Aug 28 2024 at 18:27):

Overall I suggest you do either or. Both approaches have merits:

As pointed out above, ! is probably not the best symbol for this due to its semantic meaning in sentences, and also since it is commonly used as a "not" operator in many languages (sadly, not something roc does, but one can dream). Maybe something like $ or @ could be considered instead? And yes, in rust ! is also kind of inappropriate at macro call sites as it can be mistaken for a "not" operator which uses the same symbol. It would also separate it more from the ? operator.

view this post on Zulip Richard Feldman (Aug 28 2024 at 18:30):

interesting! I hadn't considered the Task and Future angle, although I think overall this would make the language more approachable to Rust programmers because read? is exactly how you'd read from a file in Rust and then unwrap the Result in a way that propagates the error :big_smile:

view this post on Zulip Richard Feldman (Aug 28 2024 at 18:30):

also worth noting is that in this proposal, the equivalent of Rust's Future becomes "don't worry about it, your I/O is all async automatically"

view this post on Zulip Richard Feldman (Aug 28 2024 at 18:31):

which I think has an even gentler learning curve than Task <-> Future :grinning_face_with_smiling_eyes:

view this post on Zulip Richard Feldman (Aug 28 2024 at 18:35):

Alexander Pyattaev said:

As pointed out above, ! is probably not the best symbol for this due to its semantic meaning in sentences, and also since it is commonly used as a "not" operator in many languages (sadly, not something roc does, but one can dream). Maybe something like $ or @ could be considered instead? And yes, in rust ! is also kind of inappropriate at macro call sites as it can be mistaken for a "not" operator which uses the same symbol. It would also separate it more from the ? operator.

some notes:

view this post on Zulip Notification Bot (Aug 28 2024 at 19:50):

105 messages were moved from this topic to #ideas > function effectfulness syntax by Richard Feldman.

view this post on Zulip Richard Feldman (Aug 28 2024 at 19:51):

:point_up: was a very long tangent about one topic within this proposal, so I'm moving it to its own thread in order to keep this one shorter in case people want to talk about other topics here without having to scroll through that long discussion of one topic :big_smile:

view this post on Zulip Norbert Hajagos (Aug 29 2024 at 11:01):

What the proposal wants to achieve is very good!
I feel like it is not the case, but maybe: with the glory of type inference, if an unannotated and effectless fn has already returned a Result, adding some effects to it does not force changes at the call-site (provided thos are unannotated as well)? Cause this could be a strong card againts "but function coloring..."

IIuc, user defined effect-polymorphic functions aren't allowed. This woul mean that for MyLinkedList implementation, I would have to implement a walk and a walkTask. Except, I wouldn't call it that, since task will preferably be out of the dictionary for users. MyLinkedList.walkWithEffect? While at naming: Task.forever and Task.loop would become Result.forever, Result.loop? The names seem odd, but nothing ppl couldn't live with.

The thunk-ed record builders were quiet daunting at first compared to the current but I'm not even familiar with the current version. Mainly because of the many symbols. The current version looked simpler. But after looking at it again, I realised how Task.parallel would work, while I couldn't imagine that for the version that didn't use thunks. I would have also made the said mistake of adding !-s at the end of tasks in record-builded, Task.parallels.

I belive the snippet has an extra 'List' in the function argument under the text: "So fx would be a type variable for the effectfulness (or lack thereof) of the function. Here's how this could look in List.map"

view this post on Zulip Brendan Hansknecht (Aug 29 2024 at 15:42):

Norbert Hajagos said:

IIuc, user defined effect-polymorphic functions aren't allowed. This woul mean that for MyLinkedList implementation, I would have to implement a walk and a walkTask.

That is not the case. Users defined are allowed with this proposal.

view this post on Zulip Alexander Pyattaev (Aug 31 2024 at 18:27):

I would have never guessed that ! works on bool arguments in roc =) To be honest, the Python's approach of having to write "not x" instead of "!x" feels, generally, like a better way (yes, it is less concise, but far far less error-prone).


Last updated: Jun 16 2026 at 16:19 UTC