5 ms·
The problem of effects in Rust (2020)
- svieira 5y agoThere are several languages that are working on solving the composable effects problem that I am aware of: * Pony - capabilities based language inspired by `E`. Effects are like Rust's (provided by the language, not extensible by end users): https://www.ponylang.io/ https://www.ponylang.io/ * Koka - effects are first class and higher order. `filter` is a higher order function that is "effectfully parameterized" as well as "parameterized over its types". Effects can be discharged at any level of the program and the effects "stack" is manipulable (in what appears to be a principled way) https://koka-lang.github.io/koka/doc/index.html https://koka-lang.github.io/koka/doc/index.html * Multi-core OCaml is also building parallelism on a version of effects that looks quite a lot like Koka (though I'm not familiar enough with it to say how close they are in practice). What other ones am I missing?
- valenterry 5y agoHow about the languages that have already "solved" the problem (in terms of ergonomically usage), such as Haskell, Purescript, Scala and a lot of other niche languages? That being said, Rust has a bit of a harder time due to the focus on performance and optimally zero-cost abstraction, whereas other languages are more lenient and focus rather on expressiveness and composability / code reuse.
- rrradical 5y agoWell, more attempts at this problem come along pretty often (speaking for Haskell at least, and I expect those attempts to be more mature than the other languages you mentioned), so I don't think you can say those languages have solved it. Like the other comment mentioned, it's an active area of research, and some of the research happens in languages designed to solve that problem, and some happens in languages that support solutions to the problem. (Just to add- there's a really wide range of ergonomics that you can support and it's hard to get everything right. And performance is super tricky!)
- sullyj3 5y agoI mean, monads famously don't compose - you have to write a bunch of monad transformers.
- sfvisser 5y agoTrue, but not a huge real world issue in nearly all the relevant cases. I can very easily have a fallible, asynchronous, multi-value, stateful, database connected computation that returns a Bool and use it in let’s say ‘filterM’. Most transformers are already written for me. Edit: switching between no effect and some effect is the tricky part though.
- sullyj3 5y agoI find in practice that even though I don't have to write the transformers myself, `lift`ing and `unlift`ing things is a pain in the ass. Once you try a proper algebraic effect system, it's hard to feel like transformers are an adequate solution.
- thinkharderdev 5y agoMost of the relevant plumbing is generic though. Check out ZIO or cats-effect in Scala which I think both provide highly composable effect systems.
- sullyj3 5y agoUnison has an algebraic effect system, under the name "abilities" https://www.unisonweb.org/docs/abilities/ https://www.unisonweb.org/docs/abilities/
- iso8859-1 5y agoFreer Monads, More Extensible Effects http://okmij.org/ftp/Haskell/extensible/more.pdf http://okmij.org/ftp/Haskell/extensible/more.pdf
- isaacimagine 5y agoThere's also the Eff programming language: https://www.eff-lang.org/ https://www.eff-lang.org/
- moomin 5y agoLet me tell you what I'm worried about with effects systems: One of the smartest people I know of has a library called Eff https://github.com/hasura/eff https://github.com/hasura/eff that efficiently implements effects through some modifications to GHC. The thing is, she's pretty much stopped working on because she found some really nasty semantic edge-cases that she couldn't resolve to her satisfaction. (I don't understand the problems well enough to describe them, and I think they're specific to lazy languages, but it has left me cautious about the effect model in general.)
- howling 5y agoDoes she have any writings online that describe those nasty semantic edge-cases?
- moomin 5y agoUnfortunately, mostly Twitter, and that’s profoundly unsearchable. Here’s the original announcement before it ran aground: https://mobile.twitter.com/lexi_lambda/status/1226209823664066560 https://mobile.twitter.com/lexi_lambda/status/12262098236640...
- iso8859-1 5y agoWhat makes you say it ran aground? I thought it was just waiting for [0]. [0]: https://github.com/nicuveo/ghc-proposals/blob/master/proposals/0313-delimited-continuation-primops.rst#examples https://github.com/nicuveo/ghc-proposals/blob/master/proposa...
- ithkuil 5y agoFrank: https://github.com/frank-lang/frank https://github.com/frank-lang/frank
- cies 5y agoSeams stale. The paper is a joy to read though... "Do, be, do, be, do" (those who read it will understand) This paper really opened my eyes for what's possible.
- still_grokking 5y agoFrank does it right, yes. They use "abilities" as a dual to effects. That's imho the crucial part. Most of the other effect systems only implement half the thing. But I would change two parts: First of all the co-effects should be proper "capabilities" in the sense of "capability security". The other thing would be modelling the co-effects as co-data. They already use some (ad hoc?) notion of "Interfaces". Those look like co-data definitions (resembling OOP Interfaces). I also thing co-data with co-pattern matching could solve some of the problems mentioned at the end of the paper. Inspiration could be taken form: https://www.cs.uoregon.edu/Reports/DRP-201905-Sullivan.pdf https://www.cs.uoregon.edu/Reports/DRP-201905-Sullivan.pdf
- momentoftop 5y agoLast I looked, Ocaml's upcoming effect system is untyped, so doesn't really belong in the discussion.
- andreypopp 5y agoUpcoming OCaml multicore won't expose effects at all. I believe the intention is to finish work on typed effects[1] and only then add it to the language. [1]: https://www.janestreet.com/tech-talks/effective-programming/ https://www.janestreet.com/tech-talks/effective-programming/
- pdimitar 5y agoThey have an effects branch but admitted it won't be ready in time for OCaml 5.0 (supposedly arriving around end of 2021 / early 2022) so they have a separate compiler variant with it where the progress can be tracked. Last I read, they really want to nail down the entire multi-threaded environment to the last detail first (which mostly means make sure no parallel bugs are introduced + single-threaded code won't become slower; both pretty huge goals).
- eklavya 5y agoKoka looks very promising to me. I wonder why it’s not getting more attention. Probably because of being research at this point.
- scns 5y agoFlix: https://flix.dev/ https://flix.dev/ (edit) c'n'p from their site: Why Flix? Flix aims to offer a unique combination of features that no other programming language offers, including: algebraic data types and pattern matching (like Haskell, OCaml), extensible records (like Elm), type classes (like Haskell, Rust), higher-kinded types (like Haskell), local type inference (like Haskell, OCaml), channel and process-based concurrency (like Go), a polymorphic effect system (unique feature), first-class Datalog constraints (unique feature), and compilation to JVM bytecode (like Scala).
- valenterry 5y agoHonestly, I find the announcements of 99% of new languages here at hackernews pretty boring, because they all feel like they didn't learn anything from the last 20 years or so. But this list actually makes me excited!
- scns 5y agoYeah, me too. They published quite a lot of papers using it [0]. The datalog integration is pretty nice too, haven't gotten to learning Prolog yet, but seeing how concise a sudoku solver can be implemented in it was an experience. (edit) you can import Java, Kotlin and Scala in it too, those are automatically Impure. Would enable purely functional architecture [1] and falling into the "Pit of success" [2]. [0] https://flix.dev/research/ https://flix.dev/research/ [1] https://blog.ploeh.dk/2016/03/18/functional-architecture-is-ports-and-adapters/ https://blog.ploeh.dk/2016/03/18/functional-architecture-is-... [2] https://www.youtube.com/watch?v=US8QG9I1XW0 https://www.youtube.com/watch?v=US8QG9I1XW0
- dwenzek 5y agoThanks for the link. Indeed a nice programming language proposal. I love the opinionated set of design principles https://flix.dev/principles/ https://flix.dev/principles/. There is also a former thread on HN: https://news.ycombinator.com/item?id=25513397 https://news.ycombinator.com/item?id=25513397
- 5y ago
- 3np 5y agoDoes Idris qualify? https://www.idris-lang.org/ https://www.idris-lang.org/
- cies 5y agoIdris is great.
- thinkharderdev 5y agoIt's not quite built into the language but Scala has a really well-developed ecosystem of effect libraries (ZIO, Monix, cats-effect) that solve this problem really nicely.
- michaelsbradley 5y agohttps://nim-lang.org/docs/manual.html#effect-system https://nim-lang.org/docs/manual.html#effect-system
- corebuffer 5y agoF* (f star) too! https://www.fstar-lang.org/ https://www.fstar-lang.org/ Maybe also ATS, but I'm unsure if it qualifies
- xucheng 5y agoCompared with Rust’s Result monad, which allows developers to clearly see the effects of error handling, there are two other hidden fallible effects in Rust that are much harder to tackle: * Panic rewinding. I am not sure how to ensure your Rust function being panic safe. It is quite easy to cause soundness issue if some invariants no longer hold due to panic. I see `PanicGuard` sometimes used in Rust std library. * Future cancellation. `tokio::select` is one of the infamous examples, where it is quite easy to introduce bug if the future cannot handle cancellation gracefully. When trying to handle them properly, it feels more like writing traditional C code than Rust.
- newpavlov 5y ago>I am not sure how to ensure your Rust function being panic safe. You could use the linking trick in which your panic handler uses non-existent extern fn. For example, this approach is used in the no-panic crate. Of course, this approach is nothing more than a clever hack with several significant limitations. >Future cancellation I would say it's a more general problem of Rust lacking linear types.
- api 5y agoIMHO both panics and async are a mistake. The latter should be a standard library with some macros and the former should be replaced by proper error handling everywhere. Yes out of memory errors should be able to be handled. You might not care when writing web backend slop designed to run under orchestrators but for systems code it is necessary sometimes and Rust is a systems language. It’s possible to work around both shortcomings but they contradict the languages mission and are warts. Async is a big “excessive cleverness” mistake.
- steveklabnik 5y agoIt is not possible to implement async/await efficiently and safely with macros, and so doing so would be “contradicting the language’s mission.” They were considered and even originally built that way, but empirically it was worse.
- 5y ago
- pornel 5y agoRust as a language is in a funny place — somewhere between C and Haskell. Whenever Rust adds new features, C users panic "it's going to end up like C++!", but at the same time from Haskellers' perspective Rust's type system is still not advanced enough. As the article explains, it's incredibly hard to add these high-level features while still preserving "portable assembly" aspect of the language.
- api 5y agoRust occupies the C++ space, and is a massive improvement over C++. It’s type system is relatively complex but in practice is simpler to use than C++ once you learn it and far less bug prone. The dogmatic C partisans who insist on building houses out of sand with tweezers will never like it. It’s basically C++ rebooted with ideas from Haskell, Go, and other modern languages. If Rust completely displaced C++ that would be a huge win for productivity and security / reliability.
- anacrolix 5y agoThere's nothing modern about Go.
- api 5y agoYes there is: simplicity and lack of needless cleverness. Overengineering is the great plague of modern software. Rust contains a little bit of needless cleverness but most of its complexity is essential to the problem domain of low level systems programming and intrinsic safety. Go operates at a different level with a fat library (almost a VM) and garbage collection, allowing for a very simple type system. Both languages are modern but fill different niches. Rust is new C++ while Go is closer to Python or early pre-complexity-orgy Java.
- Sharlin 5y agoOn the other hand, the type system of vanilla Haskell is not especially powerful compared to current stable Rust’s. It’s pretty much all GHC extensions where the real magic is.
- api 5y agoThings that take closures should support both paradigms, since pure function closures that cannot abort can enable certain kinds of compiler optimizations like vectorizing more easily.