I first encountered Algebraic Effects in Unison where they're called "abilities" [0] via the strangeloop talk from 2 years ago [1]. Just from the little I've seen of it I feel like AE is a fundamental abstraction tool that's been missing in programming language design. "Fundamental" as in the same level as <i>function arguments</i>. So many problems that were solved with myriad complex programming language constructs are just absorbed as a trivial user-implementation with an effect system: exceptions, sync vs async, dependency injection, cancellation tokens, dynamic contexts... all of these problems where the essential complexity is a need to have an effect that cuts through the function call stack.<p>I'm not saying that all our problems are solved and the programming world will now be rainbows and butterflies, I'm just saying that this feature is the correct framing and abstraction for issues we've run into many times in the past, and it has the potential to greatly simplify and unify the hacky, bespoke, situational solutions we've found.<p>[0]: <a href="https://www.unisonweb.org/docs/abilities" rel="nofollow">https://www.unisonweb.org/docs/abilities</a><p>[1]: <a href="https://youtu.be/gCWtkvDQ2ZI" rel="nofollow">https://youtu.be/gCWtkvDQ2ZI</a>
See also the actual roadmap[1] to the OCaml 5.0 - the first version of OCaml with Multicore upstreamed.<p>[1] <a href="https://discuss.ocaml.org/t/the-road-to-ocaml-5-0/8584" rel="nofollow">https://discuss.ocaml.org/t/the-road-to-ocaml-5-0/8584</a>
Thanks for the article. OCaml has long been on my short list of languages to learn, and continuations are an hobby of mine. I'll have to dig into this deeper.<p>If someone has experience with algebraic effects, I have a question to ask. Why are they needed at all as a type system extension and why can't they just be represented with function types? (excuse my Haskell pseudocode, I'm just a filthy C++ programmer abusing the notation I don't really know the language, also don't assume lazy semantics):<p><pre><code> newtype Effect a = Effect (a -> Effect a)
newtype EffectHandler a = EffectHandler (() -> (a, EffectHandler a))
</code></pre>
A function with an effect would have an explicit Effect parameter, while an effect handler would take an EffectHandler as a parameter (and return it as well). You could also add phantom types if you really need to distinguish different effects beyond 'a.<p>The only magic would be in the function that creates the continuation:<p><pre><code> typed_callcc1 :: (Effect a -> Effect a) -> EffectHandler a
</code></pre>
Of course you could generalize Effect and EffectHandler into a bidirectional typed continuation:<p><pre><code> newtype Cont a b = Cont (a -> (b, Cont a b))
</code></pre>
I don't pretend to fully understand algebraic effects but from what I see they are pretty much equivalent, except that there is no explicit effect parameter, just the type (so the continuation is not exactly first class and it is logically passed implicitly). For similar reasons, I think you can't hide them in a closure. What is the gain? What am I missing?
Something I rarely see addressed: why was multicore ocaml blocked on having full-fledged effects? Couldn't multicore have landed years ago, and then gradually insert effects in the language?
Wow Algebraic Effects are a totally new thing i never seen mentionned so far
I always thought that async /await was the best known way to handle resumable computation<p>Totally blew my mind
Effectful concurrency feels so different from the async/await model I'm used to, but I'm really looking forward to playing around with it when OCaml 5 drops. Does anybody here have a more "ELI5" tier guide to it?
I've actually been playing with a similar idea in JavaScript, having pure functions generate "Plans" for async actions which are then executed later by other code. They can be thought of as Promises that haven't happened yet.<p>A neat side-effect (no pun intended) of doing things this way is that, unlike Promises, Plans can be stored as constants (or cached) and re-used multiple times.<p>I'm sure it's nowhere near as advanced or flexible as the OP, but it seems to be in the same general spirit
> allowing the programmer to separate the expression of an effectful computation from its implementation<p>How does this compare with IO monads? Seems like they accomplish roughly the same goal
Is this what Dan talked about in react hooks origins? <a href="https://overreacted.io/algebraic-effects-for-the-rest-of-us/" rel="nofollow">https://overreacted.io/algebraic-effects-for-the-rest-of-us/</a>
Isn't Java capable of the same thing now that it has algebraic data types with records + sealed classes + pattern matching? Given that Java already has a fine concurrency story, isn't OCaml a hard sell to someone that's not into compiler development to depend on its rich ecosystem?