Algebraic Effects for the Rest of Us
51–60 of 106 posts
Re: Algebraic Effects for the Rest of Us
#52Earlier quoted context omitted.
JS's generator functions have a yield operator that that works in a very similar way - a function can 'pause' and return a value and then resume from the same place the next time it's called. I think that's closer to Lua's yield than the effect Dan is talking about in the article. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Except that in js all of the call stack must be marked as generators. Lua thread can yield through any careless function, iterator and even C routine (if the latter does a simple continuation trick).
Re: Algebraic Effects for the Rest of Us
#53Near the end of the article: > Because algebraic effects are coming from statically typed languages, much of the debate about them centers on the ways they can be expressed in types. This is no doubt important but can also make it challenging to grasp the concept. That’s why this article doesn’t talk about types at all. I'm only remotely familiar with algebraic effects, but I thought the whole point was to have a nic…
In e.g. Haskell, you often Dont explicitly write out types, letting the compiler infer them for you. This could essentially cascade all the way up. Meanwhile, if you want to add logging in Haskell via a monad, you don't just need to change the type of each calling function to make it monadic, but you need to rewrite the function to make it monadic. That is harder work than changing some types. Moreover it is harder t…
Monads have the problem that they don't commute, which is usually not what you want for handling events (if you've got handlers for two different types of event it shouldn't matter which event handler was registered first) Maybe the algebraic effects solve this problem.
Re: Algebraic Effects for the Rest of Us
#54This sounds like a terrible idea. Especially given the nature of Javascript, this basically would mean that you would have to write every single bit of code to be re-entrant. What if you 'perform' and then the 'resume' doesn't happen until every single assumption made about the entire program state for the entirety of the function in which the perform occurs has been invalidated? After doing a 'perform', you would have to operate under the presumption that nothing done in the first portion of the function has any relevance any longer, no? The enumerateFiles example later in the article is an even better example. It performs in multiple places, but carries on like it's a normal function, not considering that at each of those performs, the entire state of the program could be changed, and none of the conditions established prior to those lines can be relied upon to still hold.
Re: Algebraic Effects for the Rest of Us
#55The author ought to look into and write about the Common Lisp condition system, which allows error handlers to invoke restarts at different parts of the call stack. [1] The long-story-short on them is that they decouple the treatment of exceptional situations (or conditions ) into three orthogonal roles: signaling the condition (akin to “throwing”), handling the condition (akin to “catching”), and recovering from the…
Smalltalk also had resumable exceptions, and I remember implementing then in ruby too, with callcc, but I think algebraic effects are more general and by focusing on exceptions the author has sort of hidden that, even if he kept saying it's just an example.
Not an expert on algebraic effects, but I suspect they are both more and less general.
On the one hand, "algebraic" hints at some constraints in the name of static typeability. Such restrictions wouldn't be present in Common Lisp.
On the other hand, Common Lisp only has single-shot downward continuations, so you won't get, e.g. nondeterminism-as-an-effect.
Re: Algebraic Effects for the Rest of Us
#56Earlier quoted context omitted.
Smalltalk also had resumable exceptions, and I remember implementing then in ruby too, with callcc, but I think algebraic effects are more general and by focusing on exceptions the author has sort of hidden that, even if he kept saying it's just an example.
Like reikonomusha said, CL's condition system is pretty general in itself. The naming choice isn't an accident - the thing that's being "raised" is a "condition" (of which "error" is just a subtype), and what you do with a condition is "signal" it. In CL, most of the time it's used for exception handling, but I've seen code using this system for tasks not related to errors. As a simple example, you can imagine data p…
Re: Algebraic Effects for the Rest of Us
#57Earlier quoted context omitted.
Except that in js all of the call stack must be marked as generators. Lua thread can yield through any careless function, iterator and even C routine (if the latter does a simple continuation trick).
Seemed like a JS specific problem to me, because it's single threaded.
^ except rare cases when embedded with lua_lock() defined as a thread locking routine. Then it becomes thread-safe, but still not multithreaded.
Re: Algebraic Effects for the Rest of Us
#58Am I the only one, that thinks that that is not a good feature. Instead A calling B calling C and having a well defined hierarchy and encapsulating complexity you have A calling B calling C calling maybe B calling maybe C again. I mean I see real value in have unidirectional call graphs because they are some much more easier to reason about. I feel like this is another gimmick to break abstractions and increase archi…
As with all language features though, idiots will always take things too far.
Re: Algebraic Effects for the Rest of Us
#59From that perspective, algebraic effects make sense and look very interesting.
Re: Algebraic Effects for the Rest of Us
#60The author ought to look into and write about the Common Lisp condition system, which allows error handlers to invoke restarts at different parts of the call stack. [1] The long-story-short on them is that they decouple the treatment of exceptional situations (or conditions ) into three orthogonal roles: signaling the condition (akin to “throwing”), handling the condition (akin to “catching”), and recovering from the…
And the author (gaeron, aka Dan Abramov) replied:
> As far as I understand, the difference is that effects are actually typed (as part of your function signature), which I didn't go into — and so you have a lot more guarantees about what a function can or cannot do.