Haskell has warts, as do all languages. Something that's tedious in one language might be a breeze in another. In Haskell, most of the baggage I've seen is around
- Cabal: seems the best advice is to just start with Stack - Delayed exceptions: due to lazy evaluation (which is a really great feature once you get used to it!), the site where you trigger an exception may not be anywhere near the actual exception-generating site. For example, if you call head on an empty list, then return that as a result only to have it be used far later, it will go "boom" at some later time. This is also true for I/O things: perhaps the file I/O way deep down in some thunk was closed due to an error, so some code that is not equipped to handle errors gets an exception.
Michael Snoyman has a great series of blog posts about this [0], i.e. "Haskell the Bad Parts 1-3". Most of this is managed by not using some of the defaults or with practice. Just be aware that like any language, there will be areas that may not have the greatest behavior.
That said, I think these confusing behaviors are very limited in Haskell, much more so than in C++ for instance.