I want to pull out a key quote from “Algebraic Effects for the Rest of Us”:
I think they could be a great fit for a language where mutation is uncommon, and where the standard library fully embraced effects. If you primarily do perform Timeout(1000), perform Fetch('http://google.com'), and perform ReadFile('file.txt'), and your language has pattern matching and static typing for effects, it might be a very nice programming environment.
Maybe that language could even compile to JavaScript!
In my opinion ReScript has a great opportunity to be that language and also solve cross cutting concerns like async/await and generators in the process. What are your thoughts?
Would love to have them, of course.
But as a realist, I only see the limited time the ReScript team has got and simply cannot imagine they are capable (in terms of time of course) to do such a R&D-heavy task.
Maybe it’s better to wait for OCaml landing the effect system and then build on top of it, and simplify it/adapt it to better fit the JS scope.
I’m not sure what point you’re trying to make here. Are you commenting on the conservative approach the core team takes in adopting FP idioms? It reads as a little entitled and derivative to me so would be good if you could expand a little.
Yes, I’m trying to point out that the team emphasizes a practical mix of imperative and functional programming, and has repeatedly mentioned in this forum that topics you might see in Haskell are not a focus of ReScript. I generally get the impression that if it would take someone coming from Typescript more than a few hours to learn, then the team would prefer not to use it as a core idiom in ReScript.
That’s fair. I do see alg effects as a more attractive proposition than many other FP features in the JS community, but that’s just anecdotal experience.
I see lots of analogies to Promises actually. They’re easy to grok for JS devs familiar with imperative programming but have a FP history and are monads under the hood.
My personal conclusion after this experience (community, libraries, specs, PLs, working on projects) is that this particular part of the JS community will probably stay niche because of many different (social) issues. I saw myself, and many other FP-JS enthusiasts, ending up in a pretty weird echo-chamber, where we were all repeating back our positive opinions about category theory, monads, functional composition, pureness etc, while in the meantime, we completely ignored the rest of the JS community and all the folks that didn’t understand our (abstract thinking) mindset.
…
Anyways, now with ReScript we have a real chance on taking the practical parts of all that FP jazz, remove the fancy words, polish the syntax in a more JS friendly manner, and reduce the number of concepts to learn so ppl can focus on the IMO “more relevant” parts of the language.
I think it’s fair to say this has been the approach of the ReScript team to FP concepts overall.
I think you can sell effects to (parts of) the JS community now, since there are React Hooks.
Maybe spare the “algebraic” and explain how async/await can be done with an effect as well.
If you have a concrete case that is helped by a concept, it can be far easier to get the concept accepted. There are situations where you don’t want the language as a research vehicle, but rather as an implementor of known proven ideas.
Algebraic effects work quite differently than how React implements hooks though. It’s still an open question how they would be implemented on the JS platform, or indeed if they even could be in a performant and efficient way. Meanwhile, JS platform ships with an async runtime that exposes Promises as the main async API, which happens to fit very well with ReScript thanks to the ease of binding to the API.
If the question is between (a) use an unknown new effect system that no one knows how it would perform on the JS platform, and (b) use the Promise API with the existing async runtime that everyone knows, I think you would have a hard time convincing people to go with (a).
I agree that async isn’t the headline use case in JS, although it would certainly be improved with alg effects.
What I would like to see is some real progress on the JS proposal, hopefully one day in the far future it will reach stage 2 and ReScript can have a real crack at implementing targeting it.
Part of the plan for multicore OCaml is to include non-monadic green threading into the runtime. In order to allow for this, algebraic effects are being added to the language. These are similar to exceptions but with a bookmark to the current position of the execution (aka continuation) added to each “exception” (aka effect) thrown, so one has the option to continue execution after handling the effect.
Initially, this was going to exist outside of the type system. However, this introduces many issues, and we’d much rather have it be typed and handled by the type system. Extending OCaml’s type system with algebraic effects would make it similar to Haskell’s, but without requiring monads for effects.
I think that document is slightly outdated. OCaml 5 beta is currently available and has effects. The full manual for them is here. But from my understanding, effects will still be considered experimental even after 5.0 is fully released, and there’s still not an obvious way to translate them to JavaScript.
For anyone interested, OCaml 5 with effects is fully released, and Js_of_ocaml (the other OCaml-to-JS compiler) has effects supported in its master branch now (which is unreleased as of this writing).
The way that JSOO supports effects is interesting. You can see their discussion on the PR here. The basic story is that they transform the JS output to use continuation-passing-style. As a tradeoff, the JS is much larger and slower, and the interop between OCaml and JS is more complicated. (And it’s probably less readable.)
So while it’s cool that we have a working example of effects in JS, they still don’t seem viable for a project like ReScript yet, IMO. However, I’m excited to see how they develop in the near future!
I think dependency injection is actually a good way to think about it!
Importantly though where you would classically create a global “DI container”, with effects you can create many containers over different parts of the call tree. In this way it’s more akin to React’s context, which can also be thought of as a DI mechanism.
Effect also have properties from other inversion of control techniques such as callbacks in that an effect can resume a suspended execution.