> One of the main reasons I don't care much about Haskell is because without any side-by-side comparisons of Haskell vs <insert procedural language> I don't understand what the Haskell advantages are, and I don't know when I'm dealing with a problem space where Haskell would help me.

This is one of haskell's biggest problems. It's just enough outside of the normal flow of imperative languages (yet usable for the same problems) that you can't tell how much of an improvement it is unless you try it. Also, people who write haskell are more inclined to share lofty/abstract/interesting-to-other-haskellers code rather than your normal day-to-day code that is massively improved/safer and benefited from haskell's features.

I've mentioned this before, but one example of where it became apparent to me how much haskell had changed what I expected from language was non-nullable types. It's starting to be really common in languages now (typescript, kotlin, etc), but if you are used to writing imperative languages, the worry of nil/None/null is ever present, and a concept like Optional<T> is actually quite foreign looking. If you really think about it, it means that none of your language is safe -- none of your functions are safe because they said they wanted a String but you might have gotten a null that looks like a String to the typechecker and will blow up at runtime.

Another key improvement in haskell is the removal of class-based code-sharing (i.e. inheritance) -- the separation of behavior and data is really important, and most languages are starting to come around to this now (go w/ structs + interfaces, java w/ data classes, kotlin w/ data classes, rust w/ structs + traits), but haskell (and other ML languages) have been there for a while.

Yet another key improvement in haskell is the errors-as-values paradigm that is everywhere. If some function has a possibility of failure, then it should return `Maybe TheThing` or `Either AnError TheThing` (see how nice and legible those types are?) -- this forces explicit checks on failure and allows cases where there isn't a chance of failure (just `TheThing`) to speed ahead without nullchecks and be fairly certain. This actually pressures you into trying to sequester failure across your codebase -- you try to write functions that have signatures like `TheThing -> SomeArgument -> OtherThing` (see how legibile that is?), to minimize on the amount of `Maybe x` or `Either error x` you have to deal with -- this is often if not always good for codebases.

Maybe this is something I can help with, I write about pedestrian haskell a bunch, and I've been meaning to do a blog post on why haskell is better <your language>, something to really rustle the jimmies.

BTW, the quote about resumable exceptions is actually referring to a concept called a monad, which can be incredibly hard to grasp if you don't look in the right places (there are a lot of bad tutorials out there), or don't give your brain long enough to marinate in the concepts. If I were to take a stab at explaining it simply, in this case it's like a combination of exceptions-as-values (i.e. not go's approach, and not java's approach) and the value that is being passed around has enough state in it to continue stop, fix itself, whatever else. When something goes wrong in most imperative languages, you kind of get the hell out of dodge, and you lose access (usually) to whatever work was done up until the function boundary -- it doesn't have to be this way but it usually is.