Live data from Hacker News

Algebraic Effects for the Rest of Us

overreacted.io

11–20 of 91 posts

Re: Algebraic Effects for the Rest of Us

#11
I was completely baffled by "algebraic effects" for years. They looked far too confusing for me to want to spend my time on them, and took the "Don’t feel like you have to [get curious about them]" approach.

But then at some point it struck me: underlying all these effect systems is just passing stuff in. So I developed my own effect system for Haskell, Bluefin[1], based on capabilities, which means the "capability to perform some effect" is represented by just passing stuff in (that is, a function can do some effect as long as it has been passed the capability to do it).

From this point of view it's hard to understand the excitement over "resume with" and "the part you can’t do with try / catch. It lets us jump back to where we performed the effect, and pass something back to it from the handler". Programming languages have had that feature since forever: a "resumable exception" is a "function call". A dynamically chosen "resumable exception" is the call of a dynamically chosen function, i.e. the argument to a higher order function.

So I don't know why people love the complexity around "algebraic effects". Maybe the mystique has a certain allure. But if you want the most straightforward possible approach I can recommend you try out Bluefin. I'm happy to answer questions on the issue tracker[2].

(Caveat: Bluefin is able to simplify things dramatically by dropping support for "multi-shot" continuations. But mostly you don't want multi-shot continuations.)

EDIT: I was too pessimistic, bazoom42 has noticed this :) https://news.ycombinator.com/item?id=48334067

[1] https://hackage.haskell.org/package/bluefin

[2] https://github.com/tomjaguarpaw/bluefin/issues/new

Re: Algebraic Effects for the Rest of Us

#12

Everything he lists is solved by effect-ts [1] bar, obviously, the language support (effect has its own fiber-based runtime like ZIO's scala). I've been using it for 5+ years and my 4 men team can scale to supporting 6 different products (each running millions $ in business, sometimes daily), as we reuse the same patterns and architecture. This would not be possible without Effect, even though I'm lucky to have terri…

Effect is pretty nice, I'm not sure how worth it it is for the frontend, but I've heard good things on the backend, but sadly I don't use TypeScript for backend work, mainly Rust, and would love to see something like that there. I'm not sure how much Rust's type system would make it possible though however. I know parts of Effect like its schema are incrementally adoptable but if you use it substantially with many of…

It does tend to naturally bubble upwards as you point out, but you can decide where to stop.

E.g. you could describe a complex effect that has retry, scheduling, etc and run it only once with `Effect.runFork(yourEffect)` in a random place of your existing code.

That's in general how teams adopt it, in general there's a champion in the team that sells using one feature, and as people get accustomed and the champion does a good work mentoring it slowly takes over whole projects.

Re: Algebraic Effects for the Rest of Us

#16

So this looks like dynamically scoped callbacks. Instead of passing callbacks along as parameters they are declared as “handlers”, and any function down the call stack can invoke them. Is this a correct understanding?

Yes. dynamically scoped, and statically typed.

Re: Algebraic Effects for the Rest of Us

#17

Everything he lists is solved by effect-ts [1] bar, obviously, the language support (effect has its own fiber-based runtime like ZIO's scala). I've been using it for 5+ years and my 4 men team can scale to supporting 6 different products (each running millions $ in business, sometimes daily), as we reuse the same patterns and architecture. This would not be possible without Effect, even though I'm lucky to have terri…

Effect is unreasonably effective. Pun etc.

The problem with these concepts is a) they are completely opaque to the common chud programmer and b) they are just not available to people in languages that anyone actually uses. There are a bunch of effect libraries in Haskell, even special efforts to make them work better in GHC, but it's nearly all wasted effort because it's just academic circlejerk.

Effect brings these capabilities to the masses by implementing them in the most popular programming language on the planet. Obviously, there is quite a learning curve -- it is essentially a programming language unto its own inside another programming language -- but it's doable. I've onboarded juniors with close to 0 FP experience into an Effect codebase. The guardrails help a lot. The language server which helps with best practices, the type errors themselves help quite a lot.

Arguably the best way to do Effect would be a separate programming language, but that would just give us the problems Haskell has: nobody would use since there would be no ecosystem, and there will be no ecosystem since nobody would use it.

Re: Algebraic Effects for the Rest of Us

#18

I’ve used effects in scala3 with cats-effects and haven’t been impressed. All in all, the way it was used was just to reimplement a very similar interface to exceptions.

Cats Effect is monadic effects. What is discussed here is sometimes called "direct-style" effects, and is an alternative representation.

I think you've missed the point regarding effect systems. Concurrency and resource handling, implemented in a way that is composable and reasonably easy to reason about, are two of the big ticket features.

Re: Algebraic Effects for the Rest of Us

#20
post #11

I was completely baffled by "algebraic effects" for years. They looked far too confusing for me to want to spend my time on them, and took the "Don’t feel like you have to [get curious about them]" approach. But then at some point it struck me: underlying all these effect systems is just passing stuff in . So I developed my own effect system for Haskell, Bluefin[1], based on capabilities, which means the "capability…

Continuations (“function calls”) reduce the amount of optimisations you can do around memory - both space wise and computationally
Post reply on HN