Abstracting Effects with Continuations
crowdhailer
55 points
2 comments
July 16, 2026
Related Discussions
Found 5 related stories in 58.8ms across 5,215 title embeddings via pgvector HNSW
- Stop Anthropomorphizing Intermediate Tokens as Reasoning/Thinking Traces nunodonato · 35 pts · August 19, 2026 · 45% similar
- Show HN: Segue – Save context in one AI, load it in another by a short handle csaguiar · 30 pts · July 28, 2026 · 44% similar
- Show HN: Discrete6502 – one thing led to another epatel99 · 11 pts · July 26, 2026 · 44% similar
- Knowing When to Stop: The Art of Making a Loop Converge gmays · 20 pts · August 22, 2026 · 43% similar
- Show HN: Arcaide – Explore code with multi-level call graphs aqula · 25 pts · July 09, 2026 · 43% similar
Discussion Highlights (2 comments)
Joker_vD
Well, yeah. You can do this, you can take pub fn simple_func(fetch: fn(String) -> String) -> List(Int) { let keys = ["a", " b"] list.map(keys, fn(key) { let key = string.uppercase(key) let value = fetch(key) string.length(value) }) } and manually convert it into a code that, instead of performing this computation, builds essentially an AST that could be interpreted to perform this computation. But the whole point of the research into async/await, algebraic effects, etc. is so that you , the programmer, don't have to because your original program is already an AST that could be interpreted to perform the computation! Your programming language already has semicolons, "foreach", and "return", so why force the programmer to use a combination of "continuation.then()", "continuation.each()", and "continuation.return()" instead? That's very much building a new programming language on top of an existing one and then solving the original problem at hand — well, perhaps the original programming language should just be better at solving the problems you want to solve?
hutao
First of all, nice post! I can tell that you put deliberate effort into using a concrete example, introducing a problem and then building up to how to solve it. However, the continuation monad has limitations. In your example, it serves a similar purpose to an abstract monad "typeclass"; where you can write an abstract "task" function and run it in the Result effect, or the Promise effect, or any other effect. However, this "task" function can only use map/bind/return, and cannot perform any specific "effectful" operation, such as throwing an error or performing async IO. At the point in the code where it performs an operation, it has to pick a concrete type for the continuation result type `t`. So, a function that performs async IO would need to return `K(Promise(b), a)`, and a function that throws an error would need to return `K(Result(b, Nil), a)`. What would be really useful would be to have a function can perform an effectful operation (such as throwing an error) and still return something like `M(b)` for some abstract effect `M`. This is one of the main problems of "effect systems," and to my understanding, what algebraic effects are currently trying to solve.