How is algebraic effects better than adding a parameter?

I’m new to algebraic effects, but it seems that adding a parameter can do the trick.

Using algebraic effects (Javascript):

function throwingFunction() {
    // we need some data, let's check if the data is here
    if (data == null) {
        data = throw "we need the data"
    }
    // do something with the data
}

function handlingFunction() {
    try {
        throwingFunction();
    } catch ("we need the data") {
        provide getData();
    }
}

Using a parameter:

function throwingFunction(getData) {
    // we need some data, let's check if the data is here
    if (data == null) {
        data = getData();
    }
    // do something with the data
}

I have no idea what you mean by “adding a parameter”, could you give an example?

1 Like

Sorry. I just added an example.

In a way you are right in saying that the same thing can be achieved by adding a parameter; in fact, the effect of any control structure can be be achieved with just function calls, by writing code in continuation-passing style (CPS), for example (it’s actually how effect handlers are compiled by js_of_ocaml, the OCaml to Javascript compller).

The “extra parameter” solution has several drawbacks:

  • It is contaminant: any code which calls functions that may perform “effects” have to be written in this weird style. It is also how historically cooperative scheduling has been done in OCaml: since effects handlers were not part of the language before recently, libraries such as Lwt impose the constraint of writing the code in monadic style and to pass functions around as parameters.
  • The code is less straightforward than direct-style code, at least to the unaccustomed eye.
  • The code is harder to optimize for the compiler. Notably, the high number of functions passed as “continuations” tend to cause a lot of closure allocations.
  • Codes written to handle different types of “effects”, or “effect”-handling code and plain code, often don’t mix well. Suppose you need to use an iterator library written in direct, “normal” style: it will probably be very hard to use it in CPS code, for instance, without rewriting it in CPS.
3 Likes

From my understanding, algebraic effects is the introduction of delimited continuations into OCaml. As @otini points out, you can always achieve the same effect wiith a CPS. But it’s a lot more … compact to use these call/cc-like operators. You can read about the uses of algebraic effects in (for instance)

Olivier Danvy, Andrzej Filinski:
Abstracting Control. LISP and Functional Programming 1990: 151-160

That’s the paper where I first encountered shift/reset long, long ago.

In 1994, I implemented a Prolog tactic for Coq using shift/reset (coded using call/cc as implemented by Daniel de Rauglaudre in caml-light) in, like, a couple of hours. It was that easy. In 1995 at Cornell and later at IBM, I saw people implementing “green thread” systems for C using the same tricks. In 2007 I worked with people at SecondLife who implemented “green threads” in Python using (again) similar tricks.

The ability to grab your stack and copy it, then later reinstall it, is very powerful. It can be misused. But it’s very powerful.

3 Likes