I don't quite understand, let's say I have a bunch of effects in my code, all depending on one another. Will that make a mess? If so, how does one avoid that, or is that an inherent issue in algebraic effects systems?
> I don't quite understand, let's say I have a bunch of effects in my code, all depending on one another. Will that make a mess?
It depends entirely on what those effects and dependencies actually are. If you really want to, you can use an effect system as a dynamically scoped imperative language, just like you can write all your Haskell code in `IO` or use exceptions for control-flow in C++. The value proposition is that you have to do it on purpose.
I've used Rx style libraries in static languages but I've found that it created a mess over time, even with their intended idiomatic usage, so I was just wondering if it were the same for effects, even if we use them in static languages how effects would be intended to be used there.
> even if we use them in static languages how effects would be intended to be used there.
There's not much that can be said about how effects, in general, are intended to be used. Algebraic effects subsume basically every control flow construct in common use: exceptions, transactional semantics, cooperative multitasking, search, probabilistic programming, IO... non-delimited continuations are the only exception I can think of. Unless you only ever write provably-total pure functions, you're always using effects of some sort. And even then, you might want to think of your program as effectful even when you don't have to: reading `a -> Maybe b` as "`a -> b` with the possibility of failure" is a classic example.
Thanks, I think I'll have to actually do some coding with effects (as I haven't really used them) to understand exactly how they work and their pros and cons. Any thoughts on which language to start off with, is Koka good as a beginner effects language, or is another one like OCaml 5 recommended?
I wouldn't worry about language-level support at the moment: there aren't as far as I know any mature implementations yet, and even if there were libraries are usually better for learning purposes.
Personally I would recommend Haskell. Native row types are coming "eventually" and always will be, so there's some ceremony involved, but it's the ecosystem with by far the best alternative solutions to the problems algebraic effects are supposed to deal with: idiomatic javascript can make any programming discipline look good, whereas it'll be much more illuminating to compare algebraic effects to a more traditional `mtl`-style approach.
Your question just isn't answerable. It's like asking if lambdas create a mess over time because you can now write in continuation passing style, or if having mutation in a language creates a mess over time because you can create globally mutable variables. How would you answer those questions?
Well, some are messier than others, of course. If I use gotos all over my code, it'll be messier than writing everything with functions, much less pure functions.
You mean a situation where the effect handler for effect A invokes effect B? I wonder if the compiler is able to detect and prevent "circular" event invocations.