I will write this answer in the flavor of your average Haskell library, as read by somebody who has learned the core language very well but not that library:
you <*$%^> everyone %%<#>%% experience
Are you really going to tell me you have never looked at code written with a package you haven't learned and initially found it to be unintelligible? If not, then I would guess that you are simply well-suited to Haskell. Again, I'm not saying Haskell is bad, but that it does have attributes that make it daunting to many people. The top-rated comment on here even talks about how easy Haskell is now that he's "over the hump." Even compared to a relatively esoteric language like Clojure, Haskell's hump is pretty big.
I believe the canonical example of a weird math-based library that makes beginners cry is Control.Arrow. Reading arrow-based code without having fully grasped both the idea of arrows and the API itself (do you think <&&&> could use a few more ampersands?) is an exercise in frustration. Even the humble monoid — simple as it may be — is hard for many people to grasp, because they're such a frustratingly generic idea with horribly unhelpful terminology attached to them.
Want more? Here's one of the top Haskell projects on Github — a library that does lenses, folds, traversals, getters and setters: https://github.com/ekmett/lens
You mean that the example would be more readable if it used proper function names instead of operators? You would still need to "learn the library", i.e. look-up what the functions do.
I mean that as a whole it's daunting and feels "unfriendly" to a lot of people. The heavy use of operators is part of it, but it's more than that. Haskell gets really abstract, which is cool, but it's hard to think about. Like I said, even monoids and monads seem hard to people learning Haskell despite being really simple. And look at the FAQ on that Lens library — it's an abstraction on top of things that are already pretty abstract in Haskell to offer "a vocabulary for composing them and working with their compositions along with specializations of these ideas to monomorphic 'containers'". That's cool and I really don't mean to criticize it, but it's undeniably esoteric and abstract.
Function names give you at least a vague idea of what the function does, but operators don't. I think Haskell's operators can make code more concise and elegant to someone who's familiar with them, but it does make it harder for a beginner to understand what's going on.
I'm pretty sure all the railing hard on the symbols above the number keys must be symptomatic of some sort of verbal learning disability in Haskell programmers...
I don't think that's fair. It allows for some really concise code that actually is quite readable once you're conversant. For example, I do not think Parsec would be better off if "<|>" were renamed to "parsecOR" or something like that. It's just, like I said, obscure and daunting.
The idea is that Parsec represents a grammar, similar to BNF with <|> giving alternative rules. So something like:
atom = many digit
<|> identifier
<|> stringLiteral
<|> between (char '(') (char ')') expression
I can't imagine any way this would look better with a name instead of the <|> operator. You could write it something like:
atom = many digit
`or` identifier
`or` stringLiteral
`or` between (char '(') (char ')') expression
but that's no clearer and a bit harder to follow. With a much longer identifier than "or", it would be completely unreadable. If you had to make "or" prefix (the `` let you use a normal function in infix position), it would be even less readable. Combine the two (a longer, prefix identifier) and you have an even bigger mess!
The operators let you see the structure of an expression at a glance. You don't have to read the whole thing to figure out what's going on. Moreover, the <|> symbol is pretty intuitive--it's clearly based on | which usually represents some sort of alternation.
I find the second one much clearer than the first one, because there is no ambiguity to me whether '<|>' means the same thing as '|'. It's also less ugly.
> chc: I do not think Parsec would be better off if "<|>" were renamed to "parsecOR"
> sanderjd: I do think Parsec would be better off if "<|>" were something like "parsecOR"
Do you think perhaps some people think about functions visually while others think about them auditorily?
An IDE could easily render function names however the human reader wants. The option whether to render function names as names or symbols would be customizable, just like the display colors for various element types are.
Within each option, there's further choices. For names, there could be a choice between various natural languages. For symbols, it could be restricted to ASCII e.g. <|>, or full Unicode, e.g. | enclosed by a non-spacing diamond.
For what it's worth, Emacs already does that last thing. As a contrived example borrowed from a post I wrote a while back[1]:
\ a b c -> a >= b && b <= c || a /= c
gets rendered as:
λ a b c → a ≥ b ∧ b ≤ c ∨ a ≢ c
However, this is a bit of a pain to do in general. It works well for common functions and syntax elements, but has to be built into the editor. Doing it more generally would require the author of the initial function to come up with multiple different names for it, which sounds unlikely.
If you're really interested in this, I'd encourage you to take some actual Parsec code and make this change, then compare the two for readability. My guess is that while it's conceptually nice, you'll find in practice it hampers readability more than it helps.
Thanks for the constructive suggestion - I don't have much invested in this particular little debate so I'm not sure I'll take the time to do that, but it's definitely a good idea.
I will say that in my opinion, the alternative in the reply above this (which I can't reply to) looks fairly nice, is clearer, and not even a little bit harder to follow. But I'll allow that as a very casual Haskell programmer, my opinions about Haskell are probably not particularly valid.
Haskellers like to use symbols for two argument functions because of precedence rules. You learn them for the modules you're using just as you would have had to learn the function names. But usually seeing how the symbol is named combined with it's type signature is enough.
As far as lenses, I personally don't like them so far. But not because of the (admittedly, questionably named) functions but rather that doing anything in lenses seems to require template magic.
Given a well-designed library that does something concrete related to a task you understand, I find that I generally don't have to learn the function names just to read code that uses it. Like, if see "HTTP.post(data, headers)" or "record.attach(file)", I have a pretty good idea what it's doing even if I don't know those particular libraries.
I believe the canonical example of a weird math-based library that makes beginners cry is Control.Arrow. Reading arrow-based code without having fully grasped both the idea of arrows and the API itself (do you think <&&&> could use a few more ampersands?) is an exercise in frustration. Even the humble monoid — simple as it may be — is hard for many people to grasp, because they're such a frustratingly generic idea with horribly unhelpful terminology attached to them.
Want more? Here's one of the top Haskell projects on Github — a library that does lenses, folds, traversals, getters and setters: https://github.com/ekmett/lens
With that library, you can write things like