upvote
In Haskell it's only ever one of (A(B)(C) or (B(A)(C), and you can tell which based on which characters B is made up of. If B starts with one of !#$%&*+./<=>?@\^|-~` it's the second situation, otherwise it's the first.[0] All functions are unary in Haskell so A(B, C), B(A, C) and C(A, B) can never actually happen. The cases where it looks like A(B(C)), etc. are happening are actually cases of (B(A)(C), e.g. f $ g is a (B(A)(C) case where B=$. So the basic syntax of Haskell is actually very simple and consistent, but due to lazy evaluation the functions can affect control flow much more than in other languages.

0: OK, there are some additional non-ASCII Unicode symbols, but everything but string literals should be kept ASCII IMO.

reply
> the programmer can't tell if the program is actually

What do you mean, "can't tell"? If I see this in Python

    (A)(B)(C)
how do I know which of your 9 it means? Well, I'm a Python programmer so I know that it means

    A(B)(C)
which is the function A applied to B, which returns a function that gets applied to C. If you're a Haskell programmer you know that it means the same thing.

I grant you that it is odd to those who are unfamiliar and it took me quite a while to get used to it, but it's much better to write that way in Haskell when writing programs that use higher-order functions.

reply
Mmm.I think I understand where you are coming from. You can write incomprehensible code in Haskell very easily and I agree that some people tend to write Haskell in a way that is easy when writing but very hard during reading.

But that is a choice. I prefer not using complex function compositions and the lenses due to this, split complex expressions into a bunch of let bindings etc..

So you also can write very readable code in Haskell.

reply