I think the BEAM languages "pure functions... well except for message passing" is perfect for concurrency. With haskell you have to use monads which are less convenient. And idiomatic BEAM defaults to actor model if you consider OTP to be "out of the box (you should)". Finally, pattern matching function guards are incredibly useful for parsing incoming messages that might be polymorphic.
Haskell is kind of designed to make programming as pure as possible and the BEAM was designed with concurrency as the first priority; it's "pure functional" to the point where its advantages (referential transparency) help concurrency and the impurities are the precise set of compromises you need to make concurrency easy.
Well, there are trade offs in both directions. Haskell has a steep learning curve and no clear one choice for concurrency, while Erlang is more approachable, has a built-in answer for concurrency, and well-established patterns for building fault tolerant applications at scale.
On the other hand, Haskell’s system has more flexibility, offering a few powerful primitives which can be used as building blocks for higher level abstractions. On top of that it is a general purpose language capable of implementing traditional imperative patterns, etc, so you only need to use the concurrency when it makes sense, rather than using it for all stateful and IO operations as in Erlang/Elixir. Its performance ceiling is certainly higher. I don’t think monads in Haskell are a problem except in terms of the learning curve.
All in all, which one to use, if either, will depend on the circumstances. But both of them should be a part of any thorough discussion of languages which are “good at concurrency”. ;)
Haskell is kind of designed to make programming as pure as possible and the BEAM was designed with concurrency as the first priority; it's "pure functional" to the point where its advantages (referential transparency) help concurrency and the impurities are the precise set of compromises you need to make concurrency easy.