I haven't developed this thesis fully, but I've been thinking that Rust's model is a better version of functional programming, and we lack a good term for it (since it's obviously not a pure functional language). The point of functional programming is to avoid shared mutable state by eliminating all side effects and using a rich type system that's hopefully easy for the programmer to use. Rust avoids unsafe shared mutable state, without requiring the avoidance of all side effects, and by using an even richer static-analysis system that tracks exactly what side effects are safe.

Of course, there are a lot of useful things a pure functional programming language gets you, like Haskell's implicit IO scheduling and threading, that Rust doesn't. But for many use cases where functional programming languages are great, they're great for specific reasons that Rust is also great at.

I've had similar thoughts. Rust does a really good job of asking, are you really sure you want that shared mutable state? It's possible to break out but I've found the friction involved has guided me towards better solutions.

It's worth noting that Haskell has "shared xor mutable" via the ST Monad. It effectively providing mutable memory cells that aren't allowed to "escape" a scope in much the same way as `&mut`.

Also having actual purity knowledge (something Rust punted on before 1.0) can sometimes be useful. Although honestly 99% of the time it's only for the benefit of the compiler, which isn't a big deal if you have the tools to write code that's efficient from the get-go.

e.g. list fusion is enabled by purity, but is largely uninteresting in Rust because lazy iterator chaining already orders operations and avoids intermediate lists just like list fusion.

A common point I've seen is that "Functional programming sees the aliasing vs mutability issue and declares that the solution is to avoid mutability altogether. Rust goes in a different direction, saying that only aliasing XOR mutability is allowed".

It's solving the same problems, and the solution ends up having many similarities with functional programming.

When people keep writing "aliasing XOR mutability", don't they actually mean "aliasing NAND mutability"? And if yes, is there a reason to use XOR here? And if no, isn't it the case that if it's worth communicating, it's worth communicating clearly?