News for hackers. Stuff that matters.
Re:Reflecting on Haskell in 2017 by wyager on Monday December 04, 2017 @08:48AM (#15843735)
> except for parts contained in Cell/RefCell/Atomic/Mutex.

This caveat is the problem. You lose a ton of properties when you have “interior mutability” (I.e. an object typed as immutable is, in fact, mutable). You probably can’t appreciate the benefit if you haven’t actually used a purely immutable language. Rust touts “fearless concurrency”, but it’s nowhere close to what you can get with Haskell’s guarantee.

> not powerful enough to write safe programs that are as efficient as C programs (since you can't modify memory)

Wrong on both counts. The vast majority of mutable algorithms can be expressed recursively and immutably. Consider haskell’s Vector library. It generates C-equivalent output a lot of the time despite being immutable and much higher level.

The one exception I’ve run into is algorithms that inherently rely a lot on random array writes (like in-place random shuffles), and in this case Haskell has the ST monad for externally pure, referentially transparent mutability that cannot escape into the rest of your program. The fact that haskellers almost never need or want to use ST is very strong evidence that, in fact, you don’t really need mutable semantics at all once you’ve figured out what you’re doing with immutable data.

Re:Reflecting on Haskell in 2017 by devit on Monday December 04, 2017 @09:43AM (#15844136)
Well, you could change Rust so that the names of types with interior mutability have to start with an "@" or something like that, and then it would be obvious, and could expose a trait to denote that (there is Sync and the internal Freeze, but they don't quite do that).

I think it hasn't been done because interior mutability is relatively rarely used, and being able to assert immutability in generic code is not actually that useful (and for things like hash map keys you'd need to implement Hash or other traits manually anyway, so you'll probably notice the issue).

In non-generic code, you have to call functions like "borrow()", etc. to access the internally mutable data, so you know it's mutable.

Regarding "fearless concurrency", the Sync trait ensures that, allowing "interior mutability" only if thread-safe (i.e. Mutex or Atomic).

Obviously you can have race conditions between modifications of different Mutex/Atomics, but that's an unavoidable fundamental problem: even transactional systems will have race conditions if you use two separate transactions where you should have used one, and single-threaded event based systems also have them if you "defer" part of the computation improperly.