As for implicit parallelization with no annotations at all, the main Haskell implementations don't seem to do it, so I guess it just doesn't work (the reasons probably being that there are penalties due to caches being CPU local and the cost of synchronizing threads that make automatic micro-parallelization much worse that explicit coarse-grained parallelization, unless the micro-parallelization is done in hardware by the CPU out-of-order logic).
And obviously a type system with controlled mutability like Rust's allows to express explicit parallelization just fine (in fact, writing a safe explicitly parallelized web browser in Servo was one of the main goals of it).
> What you really want is a static checker that only prevents shared, simultaneous mutability but admits everything else. The Rust borrow checker is an important step in that direction but it's not it.
Is there any example of a static checker that allows more expressive programs than Rust's while preserving the same guarantees? (and without requiring extra annotations like programmer-supplied proofs or using best-effort automatic theorem proving). Is that even possible?
Rust is easier to read because the visually natural distinction between words and punctuation has the same kind of meaning in Rust that it does in prose. Reading Haskell feels like reading a paragraph without any punctuation; there's no structure to grab onto. A lot of the time you can't tell whether something is a type parameter or a value.
Also $ is utterly alien compared to any other remotely mainstream language, . means something very different from what it usually does and what it usually means is rarely used ("subject verb object" is very rare in Haskell code), the :: type syntax is obscure, the mandatory split/duplication between function declaration and definition feels weird...
> […] the mandatory split/duplication between function declaration and definition feels weird...
I believe you just answered your own critique: you can always tell whether something is a type parameter or a value, because type and implementation are kept separate.
I'll just leave <'a> here then. Hard to resist. Sorry.
Certainly not for Result<> or Option<>.
No other language family has true macros. Lisp does, because it takes syntax seriously.
Forth?
I'm not convinced there is any sensible default for that. By now I think lazyness is something that will only be solved by interactive optimization.
No it's not. It's not a particularly sensible default (which you allude to) but it's not wrong. Modelling delayed resolution is very handy. For example, you'd not get far in Rust without Result<>, Option<> or Future<> which are all make use of delayed resolution for their value. And the more we move to parallel models, the more important it will be.
> because controlled mutable aliasing with linear types ... is what you really want
Again, no. It's less restrictive than pure immutability, and Rust has shown that statically managing some mutability is viable, which is great, but it's not what you really want.
What you really want is a static checker that only prevents shared, simultaneous mutability but admits everything else. The Rust borrow checker is an important step in that direction but it's not it.
> The third problem of Haskell is the weird syntax
I'm not one of life's Lisp apologists. Syntax is important, though not as important as semantics. But just because you find it difficult to read doesn't make it objectively difficult.
And if you're implying that Rust is easy to read, for a beginner, because it uses curly braces, I'm not entirely sure what to say.
I think Rust is an excellent language. I hope and believe it will be an influential language as it's a fantastic combination of innovation and pragmatism.
I'm also enormously grateful that a lot of the decisions are made in the open, I've learnt a lot and continue so to do. But it's a good language because the designers clearly have an appreciation of what has gone before. That's a good way to be.