TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Algebraic Effects for the Rest of Us

239 点作者 alaaf将近 6 年前

26 条评论

reikonomusha将近 6 年前
The 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 <i>conditions</i>) into three orthogonal roles: <i>signaling</i> the condition (akin to “throwing”), <i>handling</i> the condition (akin to “catching”), and <i>recovering</i> from the condition (which has no resemblance in popular languages). The signaler, the handler, and the recoverer can be three disjoint bodies of code sitting in different parts of your call stack.<p>Doesn’t have a cool name like “algebraic effects”, and doesn’t have cool operational semantics written out, but it does something quite similar to what the article describes. Here is a little example I cooked up for a Julia programming audience. The code offers an API for computing roots of functions, and has a DIVERGENCE-ERROR condition and a handful of different restarts which handlers of said error can invoke. [2]<p>If you want to see what languages will look like in N years, it’s always wise to see what Common Lisp or Scheme are up to.<p>[1] <a href="http:&#x2F;&#x2F;www.gigamonkeys.com&#x2F;book&#x2F;beyond-exception-handling-conditions-and-restarts.html" rel="nofollow">http:&#x2F;&#x2F;www.gigamonkeys.com&#x2F;book&#x2F;beyond-exception-handling-co...</a><p>[2] <a href="https:&#x2F;&#x2F;github.com&#x2F;stylewarning&#x2F;lisp-random&#x2F;blob&#x2F;master&#x2F;talks&#x2F;4may19&#x2F;root.lisp" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;stylewarning&#x2F;lisp-random&#x2F;blob&#x2F;master&#x2F;talk...</a>
评论 #20514048 未加载
评论 #20512737 未加载
评论 #20516332 未加载
评论 #20517169 未加载
评论 #20513270 未加载
评论 #20515168 未加载
评论 #20515336 未加载
dgudkov将近 6 年前
I, like many people in this thread, learnt about algebraic effects for the first time from the posted article. However, many commenters seem to be mislead by the explanation based on an example with exceptions. What I learnt from [1] linked below is that algebraic effects is a generalization of which language constructs like try&#x2F;catch, async&#x2F;await, or generators are just particular cases.<p>From that perspective, algebraic effects make sense and look very interesting.<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;ocamllabs&#x2F;ocaml-effects-tutorial" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ocamllabs&#x2F;ocaml-effects-tutorial</a>
评论 #20517588 未加载
评论 #20521234 未加载
konstmonst将近 6 年前
Am 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 architectural complexity. You can&#x27;t just for example take C and maybe rewrite it without having to know and touch B. This increases coupling and so is a bad idea in my book.
评论 #20514530 未加载
评论 #20523754 未加载
评论 #20513845 未加载
chombier将近 6 年前
Near the end of the article:<p>&gt; 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.<p>I&#x27;m only remotely familiar with algebraic effects, but I thought the <i>whole point</i> was to have a nice &amp; composable way of dealing with effects in the type system, as an alternative to monads that generally do not mix well.<p>Also, Daan Leijen&#x27;s papers on Koka are pretty accessible.
评论 #20513334 未加载
评论 #20517259 未加载
pwpwp将近 6 年前
Algebraic effects are similar to Common Lisp restart handlers, but in addition, they also receive the continuation of the invoker. This means, you can use algebraic effect handlers to implement higher-order control features like coroutines, probabilistic programming, and nondeterminism (which you can&#x27;t in Common Lisp).<p>However, what most people get wrong: you do not need higher-order control if you just want to resume after an error. This is demonstrated by Common Lisp, which doesn&#x27;t have coroutines, algebraic effects, nor continuations, but _can_ resume after an error.<p>The main example of the article could be done just fine in Common Lisp, because it doesn&#x27;t use any higher-order control.
评论 #20514171 未加载
fjfaase将近 6 年前
I doubt if you need any new language construct to introduce this. Could you not simply pass an error handling function&#x2F;object with all your functions&#x2F;methods, which is called when an error occurs? This function&#x2F;object could then resolve the error or throw an exception if it cannot resolve the error. It is possible, and relatively easy, to chain such error handling functions&#x2F;methods to implement complex error handling methods.
评论 #20512809 未加载
评论 #20518719 未加载
评论 #20512815 未加载
评论 #20512962 未加载
评论 #20512946 未加载
itsbits将近 6 年前
I worked on schooling project for Algebraic effects using Eff. I would surely recommend it if you want to know more on it.<p><a href="https:&#x2F;&#x2F;www.eff-lang.org&#x2F;try&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.eff-lang.org&#x2F;try&#x2F;</a>
mehrdadn将近 6 年前
Is it safe to say this is basically a more practical version of EXCEPTION_CONTINUE_EXECUTION? [1]<p>Also, on another note, it&#x27;s not really true that &quot;things in the middle don’t need to concern themselves with error handling&quot;. That&#x27;s what exception-safety is about. You very much do need to concern yourself with exception handling if you want to allow the possibility of a caller handling a callee&#x27;s exception. Also see [2].<p>[1] <a href="https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;exception-handler-syntax" rel="nofollow">https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;debug&#x2F;excepti...</a><p>[2] <a href="https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;oldnewthing&#x2F;20120910-00&#x2F;?p=6653" rel="nofollow">https:&#x2F;&#x2F;devblogs.microsoft.com&#x2F;oldnewthing&#x2F;20120910-00&#x2F;?p=66...</a>
评论 #20513142 未加载
chc4将近 6 年前
Maybe I&#x27;m missing something, but isn&#x27;t this essentially just coroutines? In Lua you can do `myFile = coroutine.yield(&quot;get a file&quot;)` to pause your coroutine, and when the caller does `coroutine.resume(someFile)` it&#x27;s resumed with the value passed in.<p>EDIT: I guess the difference would be in Lua, yields return to where they were resumed each time, while in algebriac effects they return to the nearest handler for that case. You&#x27;d need some boilerplate to bubble up all effects you don&#x27;t care about up another level at each handler in Lua.
评论 #20515689 未加载
评论 #20513025 未加载
评论 #20513534 未加载
fermigier将近 6 年前
In Python:<p><a href="https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;effect&#x2F;" rel="nofollow">https:&#x2F;&#x2F;pypi.org&#x2F;project&#x2F;effect&#x2F;</a> (Effect library)<p><a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fM5d_2BS6FY" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=fM5d_2BS6FY</a> (talk from PyConNZ 2015).<p>(Shameless plug: this is one of the libraries listed in <a href="https:&#x2F;&#x2F;github.com&#x2F;sfermigier&#x2F;awesome-functional-python" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;sfermigier&#x2F;awesome-functional-python</a> ).
pron将近 6 年前
I&#x27;m far from convinced of the utility of algebraic effects, but if you like them, implementing them in Java (or any Java platform language) would be possible soon thanks to Project Loom [1]. The scoped (ALA multi-prompt) delimited continuations provided by Loom are intended for other uses, but they could also be used to implement algebraic effects.<p>[1] <a href="https:&#x2F;&#x2F;wiki.openjdk.java.net&#x2F;display&#x2F;loom&#x2F;" rel="nofollow">https:&#x2F;&#x2F;wiki.openjdk.java.net&#x2F;display&#x2F;loom&#x2F;</a>
xvilka将近 6 年前
Well, OCaml it the only mainstream language that works on the integration of the algebraic effects. But the work[1] is being done is very slow for a project of such importance (it is also a part of multicore). Nevertheless, OCaml loses some points to Rust, due to its lack of proper parallelism. So I hope Rust ecosystem would put more attention to the efforts[2][3][4] to bring algebraic effects to the language.<p>[1] <a href="https:&#x2F;&#x2F;github.com&#x2F;ocaml-multicore&#x2F;ocaml-multicore&#x2F;projects&#x2F;3" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ocaml-multicore&#x2F;ocaml-multicore&#x2F;projects&#x2F;...</a><p>[2] <a href="https:&#x2F;&#x2F;github.com&#x2F;pandaman64&#x2F;effective-rust" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;pandaman64&#x2F;effective-rust</a><p>[3] <a href="https:&#x2F;&#x2F;kcs1959.jp&#x2F;archives&#x2F;4387&#x2F;general&#x2F;algebraic-effects-for-rust" rel="nofollow">https:&#x2F;&#x2F;kcs1959.jp&#x2F;archives&#x2F;4387&#x2F;general&#x2F;algebraic-effects-f...</a><p>[4] <a href="https:&#x2F;&#x2F;qiita.com&#x2F;__pandaman64__&#x2F;items&#x2F;9fd47af5a39f0d2a6bbb" rel="nofollow">https:&#x2F;&#x2F;qiita.com&#x2F;__pandaman64__&#x2F;items&#x2F;9fd47af5a39f0d2a6bbb</a>
azangru将近 6 年前
Brandon Dail from the React team gave a talk about what they mean by algebraic effects at React Rally a year ago: <a href="https:&#x2F;&#x2F;youtu.be&#x2F;7GcrT0SBSnI" rel="nofollow">https:&#x2F;&#x2F;youtu.be&#x2F;7GcrT0SBSnI</a>
amelius将近 6 年前
Where does the name come from? The word &quot;effects&quot; makes me think of &quot;side effects&quot;, which is something I&#x27;d usually like to avoid.
评论 #20515234 未加载
wvlia5将近 6 年前
What is &#x27;algebraic&#x27; about algebraic effects?
评论 #20515004 未加载
otakucode将近 6 年前
&gt;It turns out, we can call resume with asynchronously from our effect handler without making any changes to getName or makeFriends:<p>This 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 &#x27;perform&#x27; and then the &#x27;resume&#x27; doesn&#x27;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 &#x27;perform&#x27;, 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&#x27;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.
gumby将近 6 年前
Instead of ES2025 he should have used &quot;ES1978&quot; because the early lisp signalling systems were more general than just errors and had continuable exceptions. This evolved into the Common Lisp Object System when Common Lisp was standardized in the early 1980s.
arsdragonfly将近 6 年前
Can anyone tell me the relationship between this and call&#x2F;cc?
transfire将近 6 年前
I wonder how much of this is more easily (or less easily) handled with Ruby-like blocks. One can pass in a procedure as an argument to handle the conditional execution.
dusted将近 6 年前
Interesting sideeffect of Dijkstras rant :)<p>&quot;Imagine that you’re writing code with goto, and somebody shows you if and for statements.&quot;<p>10 for a = 0 to 10<p>20 if a = 5 then goto 40<p>30 next<p>40 end<p>50 print &quot;5&quot;<p>60 goto 30<p>I lack imagination.<p>That said, algebraic effects sounds interesting indeed.
zbentley将近 6 年前
I&#x27;m not wild about this article; it gives lots of &quot;you can go from code like this, to code like this!&quot; examples with non-equivalent functionality, which is confusing if you&#x27;re skimming.<p>Totally separate from stylistic quibbles, I also think effect systems are often oversold by folks who like them (usually, in my experience, folks from a functional background).<p>Fundamentally, a lot of the code we write <i>is</i> the effectful IO plumbing. By that I mean: there are very few complicated algorithms, or really any hand-written algorithms at all, in a large amount of code written for modern systems. Instead, the complexity and value of the code is in the way it coordinates different external IO sources&#x2F;sinks. This is pretty well illustrated in the article&#x27;s toy directory enumeration&#x2F;file handling example: with the IO&#x2F;system specific stuff extracted into the effect receivers (processors? handlers?), the remaining code is not just simple, it&#x27;s <i>vacuously</i> simple. The complexity and trickiness of handling IO, dealing with error conditions, etc. all remains, though, in the effect receivers. This is subjective, but that seems more akin to the &quot;over-extracting methods to the point where all you do is increase the line count&quot; school of refactoring than the &quot;improving the comprehensibility&#x2F;maintainability of the code&quot; school. Generifying IO interactions behind an effect system in a codebase that is primarily occupied with gluing together external systems results in moving so much of the code into effect receivers that nothing useful remains behind.<p>Put another way: often, <i>what</i> we&#x27;re doing is intimately coupled with <i>how</i>: like, sure, I&#x27;m technically &quot;piping data from a source into a sink with a transformer in between&quot;, but they don&#x27;t pay me to write &quot;source |&gt; transformer |&gt; sink&quot;, they pay me to write (for example) the SELECT statement in the source, the column mapping&#x2F;reformatting logic of the transformer, and the POST-to-endpoint in the sink. If those things already existed, it would be the one-liner above, but they don&#x27;t for the business domain, so we make them. Once they&#x27;re written, by all means, modularize them and make them easily usable in a streamable, convenient way. But most of the interesting code, once you peel back the curtain on &quot;source&quot; or &quot;sink&quot; is still going to be in its effectfulness.<p>Then there&#x27;s the argument from modularity&#x2F;swappability: that you can replace effect handlers with equivalent handlers for doing other things. If you&#x27;re writing a system with many swappable backends, this may be useful. However, most systems don&#x27;t have that property. Datastores and effect receivers change much less often than the data flow itself. And past a certain point you end up with &quot;old Java&quot;-style modularity: things abstracted so far away in service to unneeded pluggability that the code becomes harder to follow and maintain (especially given that the code may be primarily&#x2F;near-exclusively concerned with specifics of IO flow).<p>To be sure, there are some cases where effect systems can really help. I just don&#x27;t think those are as numerous as FP proponents think they are.
dvfjsdhgfv将近 6 年前
&gt; Algebraic Effects are a research programming language feature. This means that unlike if, functions, or even async &#x2F; await, you probably can’t really use them in production yet. They are only supported by a few languages that were created specifically to explore that idea. There is progress on productionizing them in OCaml which is… still ongoing. In other words, Can’t Touch This.<p>WalterBright: &quot;Challenge accepted!&quot;
ragerino将近 6 年前
In Java you simply extend an Exception class (checked or unchecked) and handle it properly regardless of the error message.<p>Modern IDEs can detect exception types which don&#x27;t exist yet, and create them on the fly while you try to use them for the first time.
评论 #20513606 未加载
layoutIfNeeded将近 6 年前
Those Game of Thrones references are super cringey.
wruza将近 6 年前
Now conditions&#x2F;restarts. How much more decades should we wait till they rediscover all the programming tools? Please, rewrite your browser legacies once to support non-trivial execution model and allow any decent language to stop this madness.
评论 #20513358 未加载
phoe-krk将近 6 年前
&gt; The best we can do is to recover from a failure and maybe somehow retry what we were doing, but we can’t magically “go back” to where we were, and do something different. But with algebraic effects, we can.<p>This is <i>literally</i> Common Lisp&#x27;s condition system which a) decouples signaling conditions from handling conditions, b) allows you to execute arbitrary code in the place that signals, c) allows you to stack independent pieces of condition-handling code on one another so they run together, and d) allows you to unwind the stack or <i>not</i> unwind the stack at any moment, so your code may continue running even if it ends up signaling.<p>ANSI Common Lisp was standardized in 1994. This post is from 2019. That&#x27;s reinventing a 25+ year old wheel the author is likely unaware of.
评论 #20513503 未加载
评论 #20513103 未加载
评论 #20513394 未加载
评论 #20513342 未加载
评论 #20513476 未加载
评论 #20513093 未加载
评论 #20514404 未加载
评论 #20516357 未加载
评论 #20513228 未加载