News for hackers. Stuff that matters.
Re:Why Algebraic Effects? by charcircuit on Friday May 23, 2025 @11:24PM (#44078519)
This doesn't give a focused explaination on why. I don't see how dependency injection is a benefit when languages without algebraic effects also have dependency injection. It doesn't explain if this dependency injections is faster to execute or compile or what.
Re:Why Algebraic Effects? by yen223 on Saturday May 24, 2025 @12:38AM (#44078818)
The way dependency injection is implemented in mainstream languages usually involves using metaprogramming to work around the language, not with the language. It's not uncommon to get errors in dependency-injected code that would be impossible to get with normal code.

It's interesting to see how things can work if the language itself was designed to support dependency injection from the get-go. Algebraic effects is one of the ways to achieve that.

Re:Why Algebraic Effects? by vlovich123 on Saturday May 24, 2025 @12:41AM (#44078828)
Don’t algebraic effects offer a compelling answer to the color problem and all sorts of related similar things?
Re:Why Algebraic Effects? by threeseed on Saturday May 24, 2025 @02:55AM (#44079264)
But they also introduce their own color-like problems.

For example with Scala we have ZIO which is an effect system where you wrap all your code in their type e.g. getName(): ZIO[String]. And it doesn't matter if getName returns immediately or in the future which is nice.

But then the problem is that you can't use normal operators e.g. for/while/if-else you need to use their versions e.g. ZIO.if / ZIO.repeat.

So you don't have the colour problem because everything is their colour.

Re:Why Algebraic Effects? by OtomotO on Saturday May 24, 2025 @03:15AM (#44079348)
But that's only a problem if it's a library and not done on the language level?!
Re:Why Algebraic Effects? by threeseed on Saturday May 24, 2025 @03:38AM (#44079477)
But in the research languages listed they still are colouring function types.

So it doesn't seem to matter whether it's a library or in the language.

Either everything is an effect. Or you have to deal with two worlds of code: effects and non-effects.

Re:Why Algebraic Effects? by vlovich123 on Saturday May 24, 2025 @04:01PM (#44083448)
Maybe but even if that's the case, you've now got just plain and colored vs before you'd have plain, color A, color B, color C if you go beyond just async as the only other color (e.g. whether you're accepting something by reference or value, whether it's a mutable reference, whether or not the function is compile-time, etc etc etc).

Still seems better to me if you collapse colors >= 1 into a single language system.

Re:Why Algebraic Effects? by sullyj3 on Saturday May 24, 2025 @07:49PM (#44084498)
Functions can be polymorphic in their effectfulness, so the coloring problem isn't. Functions only become incompatible where you've made them incompatible on purpose - the whole point of annotating functions' effectfulness is to statically know you're not accidentally invoking particular effects where you promised you wouldn't.
Re:Why Algebraic Effects? by jfecher on Saturday May 24, 2025 @10:50PM (#44085172)
Developer of Ante here. Functions in languages with effect systems are usually effect polymorphic. You can see the example in the article of a polymorphic map function which accepts functions performing any effect(s) including no effect(s). For this reason effect systems are one of the solutions to the "what color is your function" problem.
Re:Why Algebraic Effects? by charcircuit on Saturday May 24, 2025 @01:34AM (#44078985)
>It's interesting

Which is why I was asking for that interesting thing to be written in the article on why it would better.

Re:Why Algebraic Effects? by cryptonector on Saturday May 24, 2025 @03:12AM (#44079329)
It's the same as with monads:

1) Testing. Write pure code with "effects" but, while in production the effects are real interactions with the real world, in testing they are mocked. This allows you to write pure code that does I/O, as opposed to writing pure code that doesn't do I/O and needs a procedural shell around it that does do the I/O -- you get to write tests for more of your code this way.

2) Sandboxing. Like in (1), but where your mock isn't a mock but a firewall that limits what the code can do.

(2) is a highly-desirable use-case. Think of it as a mitigation for supply-chain vulnerabilities. Think of log4j.

Both of these are doable with monads as it is. Effects can be more ergonomic. But they're also more dynamic, which complicates the implementations. Dynamic features are always more costly than static features.

Re:Why Algebraic Effects? by charcircuit on Saturday May 24, 2025 @04:13AM (#44079649)
Again you are listing things that are possible but not explaining why it's better to do it via algebraic effects as opposed to the alternatives.
Re:Why Algebraic Effects? by cryptonector on Saturday May 24, 2025 @04:38AM (#44079722)
The only reason I can think of -but I'm not the right person to ask- is ergonomics, that in many cases it might be easier to push an effect handler than to build a whole monad or whatever. Elsewhere in this thread there's talk of effects solving the color problem.
Re:Why Algebraic Effects? by threeseed on Saturday May 24, 2025 @09:19AM (#44080923)
Take the following requirement:

"A user has made an API call. I want you to in parallel race two concurrent tasks: check if the data is in (1) cache and (2) database. Whichever returns fastest return to the user. Otherwise kill the other task mid-flight and make sure the connection resources for both are cleaned up".

This is trivial with an effect systems like ZIO and it will work flawlessly. That's the benefit of effect systems. Use cases like this are made easy.

But now with JVM Virtual Threads there are frameworks like Ox: https://github.com/softwaremill/ox which allow you to achieve the same thing without effects. And how many times do you really need that sort of capability ?

Re:Why Algebraic Effects? by iamwil on Saturday May 24, 2025 @07:24PM (#44084381)
Because Algebraic Effects are unfamiliar, we explain a part of it with something that's familiar to most developers.

This is just like the story of the blind men with the elephant. The elephant (algebraic effects) is a whole other different beast, but to help the beginner understand the first parts of it, we say the truck is like a snake (resumable exceptions) or that the ear is like a fan (dependency injection).

Algebraic effects are a new type of control flow. When an effect is raised, the handler (defined further up the call stack) has several options:

- handle the effect and resume the computation where the effect was raised.

- handle the effect, but resume the computation multiple times back to where the effect was raised.

- decide not to handle the effect, and just exit, at which point the execution resumes right when the handler was called further up the stack, and everything executed since then is as if it never happened. This is a way of doing back tracking.

In addition, what's algebraic about algebraic effects is that they usually come in a group, and are designed with a compositional algebra, so you can safely compose them in different ways. A common one is commutativity, so it doesn't matter what order you execute them in. Of course, not all algebraic effects have commutativity, as that has to be designed by the implementer. Monads are different in that they often don't compose without monad transformers, so that can be finicky.

Hence, with all these things together, you can use them to implement control flow in other languages that are typically baked into the language, such as exceptions, coroutines, generators, async/await, probabilistic programming, backtracking search, dependency injection. You might also invent your own!

But most commonly here, we use them to separate the *intent* to do a side-effect from the actual execution of the side-effect. That way, side-effects are controlled, and it becomes easier to reason about our code.