This terseness is what makes Haskell so hard to approach for beginners, unfortunately.
After you went through the effort of learning the syntax, it becomes very clear what it means, but I agree that dropping punctuation between a bunch of names isn't the clearest communication.
It becomes even worse when you start using third party libraries that abuse Haskell's ability to define custom operators, so you get entire APIs defined as arcane sigil invocations instead of readable functions.
That's why I gave up the idea of using Haskell for actual programming, and just took the functional programming philosophy from it to other languages.
As for the meaning, in a more conventional (rust) syntax, it'd be similar to this:
The problem with A -> B -> C is that it could be (A -> B) -> C or A -> (B -> C).
The -> operator in C is obvious. Though it does have left to right associativity, it's largely moot because only A would be a pointer-valued expression. The B and C would have to be member names:
A->left->value.
Even if the associativity went right to left, the semantic interpretation would have to be that the left member of A is selected, and then the value member of that.
When X -> Y means "mapping from X to Y", the associativity could be anything, and make sense that way. Moreover (X -> Y) -> Z is different from X -> (Y -> Z). One is a function which maps an X-to-Y function to Z, whereas the other is a function which maps X to a Y-to-Z function.
I disagree that the 'arcane sigil invocations' are necessarily a problem. Yes, they can be, but I also think they can definitely be preferable!
Naming everything as a function often leads to a problem of very deep visual nesting. For example, map-then-filter can be written as "filter p . map f" in Haskell, whereas in sigil-free languages you'd write a mess like (lambda (x) (filter p (map f x))) in Lisp or "lambda x: filter(p, map(f, x))" in Python.
Of course, function composition is a very simple case, but something like lenses are another less simple case where a library would be unusable without custom operators.
Right off the bat, the problem is that filter p . map f looks like it wants to be filter, then map. Nearly all modern languages that have pipelining, whereby nested function calls are extraposed into a linear formm, go left to right.
In the Lisp or Python, it is crystal clear that the entire map expression is a constituent of the filter expression.
After you went through the effort of learning the syntax, it becomes very clear what it means, but I agree that dropping punctuation between a bunch of names isn't the clearest communication.
It becomes even worse when you start using third party libraries that abuse Haskell's ability to define custom operators, so you get entire APIs defined as arcane sigil invocations instead of readable functions.
That's why I gave up the idea of using Haskell for actual programming, and just took the functional programming philosophy from it to other languages.
As for the meaning, in a more conventional (rust) syntax, it'd be similar to this: