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
Algebraic Effects for the Rest of Us
31–40 of 91 posts
Re: Algebraic Effects for the Rest of Us
#32I swear I'm not trying to be inflamatory, but this is the _worst_ programming language feature I could ever imagine. I'm not trying to be hyperbolic, if I try to reason about it there is nothing I can come up with that I would dislike more in the realm of recent features that have been pitched in the PL community I was already in the camp that try/catch is "considered harmful", I dislike the concept of having a secon…
To be clear, you still pay indirection cost: when you do opt in you have to hope the upstairs implementation is compliant to the contract. But that does also apply to interfaces/typeclasses.
Re: Algebraic Effects for the Rest of Us
#33It’s worth clarifying that for the most part, this article just discusses plain effects, ie. "reified side effects" or "resumable exceptions". Algebraic effects are about the composition (ie. algebra) of effects, exactly like algebraic data types are about the composition of types. This part is generally not meaningful in an untyped language like Javascript because effects are all YOLO and you never know what’s going to happen, what effects a function might throw, or whether there’s any handler up-stack to catch your effect.
Re: Algebraic Effects for the Rest of Us
#34Re: Algebraic Effects for the Rest of Us
#35Earlier quoted context omitted.
No, they are function colouring. That's the point. Someone writes a post lamenting red and blue functions, and everyone eats it up. Substitute colour for something meaningful and the idea becomes idiotic. "Top level function declares that it is non-blocking, but when I try to call a small blocking function from it, I have to change the declaration to blocking???" Yes, yes you do. Total functions can't call non-total…
‘Non-IO functions can't call IO functions.’ How do you handle logging then? If f() calls g(), how can I add logging to g() without having to change or recompile f() (and everything in the call stack above it)? ‘You can’t’ is not an acceptable answer.
Re: Algebraic Effects for the Rest of Us
#36I 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…
A real effect system allows you to do things like NOT continue execution after using the effect (like the error effect does - if you "implement" this by using Exceptions, you're not using effects at all, just using Exceptions with extra steps) or only continuing it after some asynchronous work happens (the Future effect), or even "continue" execution several times. That just cannot be done with "just passing stuff in…
> A real effect system allows you to do things like NOT continue execution after using the effect
Right, Bluefin's Request allows you to do that too. For example here is an example of handling the request by continuing or not, depending on what the value yielded to the Request is.
example :: Either String ()
example = runPureEff $ try $ \ex -> do
forEach
( \r -> do
request r True
request r True
request r False
request r True
request r True
)
( \case
True -> pure ()
False -> throw ex "Stopped"
)
> if you "implement" this by using Exceptions, you're not using effects at all, just using Exceptions with extra stepsNot sure I follow that. Above you can see I used an exception (Bluefin's Throw capability), but I couldn't have used only an exception because that would have aborted unconditionally. What am I missing here, that makes "using Exceptions" "not using effects at all"?
> only continuing it after some asynchronous work happens (the Future effect)
I'm not really sure what "a Future effect" is, but I don't see how it's not something that can be run as a function call, at least in Haskell.
> or even "continue" execution several times
Right, these are the multishot continuations which Bluefin doesn't support. I haven't discovered many particularly compelling use cases for multishot continuations but would be very interested in finding some. The developer of the Kyo effect system for Scala, Flavio Brasil, suggested parsing, with multiple parse results, which makes sense.
I'm also not entirely sure Bluefin couldn't simulate common use cases of multishot continuations with threads, but I haven't thought about it very hard.
> You still don't seem to have understood effects.
Possibly true, and part of my puzzlement! I'm always happy to try to improve my understanding. Can you help me see what I've missed?
Re: Algebraic Effects for the Rest of Us
#37Standard feature of Common Lisp condition system (over 30 years old). https://lisp-docs.github.io/cl-language-reference/chap-9/j-b...
The CL condition system always gets brought up when people unfamiliar with effects see effects for the first time (example: https://news.ycombinator.com/item?id=38813484 , another example: https://lobste.rs/s/12m2f0/algebraic_effects_another_mistake ). But while the condition system can do many things you can also do with effects, they cannot do everything. Here's another discussion on this: https://news.ycombinator.…
Nondeterminism is not a feature you want. Algebraic effects treat the execution stack (continuation) as data, you have total freedom over what you do with it. This flexibility is exactly where you get nondeterminism. This is how logic solvers or probabilistic algorithms work, but you don't want it as a programming language feature in general purpose programming language.
Re: Algebraic Effects for the Rest of Us
#38(2019) It’s worth clarifying that for the most part, this article just discusses plain effects, ie. "reified side effects" or "resumable exceptions". Algebraic effects are about the composition (ie. algebra) of effects, exactly like algebraic data types are about the composition of types. This part is generally not meaningful in an untyped language like Javascript because effects are all YOLO and you never know what’…
Re: Algebraic Effects for the Rest of Us
#39Re: Algebraic Effects for the Rest of Us
#40So 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?
You need stackful coroutine (like goroutine) for that.