> But you will need strict discipline and total control over your collaborators to pull that off because C++ is so permissive.

Except it's not. The key is proper encapsulation into classes and generous use of private instance variables.

The real problem is social: people want to get something done quickly, so instead of talking to the original author[1], they put a new method in the class (or declare a friend) and happily continue hacking, without thinking of far-reaching consequences of whether unrestricted (that's what public is) use of the newly introduced method violates class invariants in some way.

[1] I'm aware that the original author might not be there anymore. Which makes a good case for documenting design and intent of the code. A QA matter.

How does Haskell solve the social problem (directly hacking something into a module you don't own or fully understand)?

> What you don’t realize is that it will take you 10 years, if you’re lucky, to discover the “right way” of programming in C++

IMO, only novices and beginners look for "THE right way".
Advanced people realize that the "right" way depends on the broad context and look for (the) best compromise solution among a spectrum of solutions.

I believe this holds for other computing-related things (designing a LAN, database tables, etc.), as well as real life (sports, martial arts, even everyday things like sitting and walking as any person who has had a lower back problem will tell you).

The problem is again social: novices and beginners who refuse to "grow up" and who know just enough to be dangerous: they can produce working but messy code, and refuse to learn other ways of doing the same thing in an appropriate context. (E.g. when to use while vs for, or why copy-pasting large chunks of code between different functions is generally "bad".)

Somehow I'm not convinced that Haskell is the magic bullet which solves the underlying social/human issues.

> Haskell is not permissive, it won’t let you — or your coworkers — write unsafe code.

He never defines what "unsafe" is. Mutation is not unsafe per se.

> Don’t be fooled: accessing atomic variables is expensive.

I've seen recent slides where the measured cost of an uncontended locked cmpxchg on Haswell was ~20 cycles vs ~5 cycles unlocked. This is NOT expensive, unless unnecessarily you replace all memory accesses with their atomic equivalents.

> Most importantly though, threads are not a good abstraction for parallel programming

No, but they are an essential building block.

> Haskell is way ahead of the curve with respect to parallelism

First, a computation can be abstraceted into a data dependency graph.

Now, the reason that most of today's applications don't benefit a lot from the vast number of processors available is not that the underlying programming is somehow unsuited for parallelism.
It is because that there IS NO parallelism available in these applications: data dependency graph is mostly serial, and if parallelism is available, it is on such a small scale that superscalar CPUs already make use of the large part of it.
Also, with overly fine-grained parallelism you WILL end up in a situation where the overhead of atomic operations becomes non-negligible, even if it is only ~20 cycles.

I believe that if people more often thought about their designs in message-passing terms, the dependency graph would also emerge, and they would see that there often is very little parallelism to extract through explicit parallelization. (Note that writing to a shared variable is just an extremely simple and efficient method of sending a message).

This was also remarked on by Knuth: During the past 50 years, I’ve written well over a thousand programs, many of which have substantial size. I can’t think of even five of those programs that would have been enhanced noticeably by parallelism or multithreading. [http://www.informit.com/articles/article.aspx?p=1193856]

So, IMO, easier coding for shared-memory parallelism is one of the worst reasons to switch programming languages.

That's why I personally prefer Erlang-style concurrency (actors). Communication patterns and parallelism granularity is explicit, and communication cannot be decoupled from synchronization. [With shared variables, these two are decoupled.]