The difficulty one might find comprehending Haskell is probably because of the semantics rather than syntax - particularly if you have a background in languages like C++ and Java - the first thing you'll be attempting to do is find parallels between this new obscure syntax and what you already know - but they don't necessarily fit, because the language is fundamentally different.
A common example of misunderstanding for beginners is function signatures - in Haskell, one simply defines a function name, followed by two colons, followed by a type declaration which states the function's type. It's as simple as
add :: Int -> Int -> Int
If you're attempting to draw the parallel to the equivalent in another language such as C#, you might think this is the same as int Add(int a, int b) {
...
}
While pretty close, the Haskell equivalent of that is really a coupled argument. add :: (Int, Int) -> Int
The C# equivalent of the original is closer to this Func<int, Func<int, int>> add = a => (b => ...);
At this point it should become a bit more obvious why that "cryptic" function signature is the way it is - it's because all functions in Haskell are secretly single argument functions, and additional arrows indicate that the return type is another function. In other words, the arrow, -> associates to the right, which makes it unnecessary to parenthesize the returned functions - but you can optionally write them for clarity: add :: Int -> (Int -> Int)
As a result, you can partially apply add with a single value, e.g. `add 5`, and a valid function which adds 5 to its argument is returned, e.g. `(add 5) 6 == 11`, and because function application (denoted by a space) associates to the left, you can omit the parens and simply say `add 5 6`.Given that you have some Erlang background, the syntax for implementing functions should not be foreign to you, because they're quite similar, except perhaps "do-notation", which will won't be very intuitive until you grok monads.