
Philippa Cowderoy wrote:
On Sun, 21 Sep 2008, Andrew Coppin wrote:
Actually, none of these things were mentioned. The things people have *actually* complained to me about are: - Haskell expressions are difficult to parse.
This is partly an "it's not braces, semicolons and function(application)" complaint, though not entirely.
One person complained that "case compare guess target of" was unclear. Of course, you and I know that "case" and "of" are actually language keywords, and hence this is really "case (compare guess target) of", which makes far more sense. (Your suggestion about syntax hilighting is relevant here!)
- Several standard library functions have names which clash badly with the usual meanings of those names - e.g., "break", "return", "id".
For this one, I'm inclined to say "welcome to a new paradigm". Though having to tell my dad briefly that do isn't a loop construct was odd for a moment.
Haha! Nice... I think "return" is a rather bad choice of name. But on the other hand, I can't think of a better one. And let's face it, anything has to be better than (>>=). (Most cryptic name ever?)
- Variable names such as "x" and "f" aren't fabulously helpful to lost programmers trying to find their way.
So don't use them? Though I think f in particular has its place in higher order functions.
Idiomatic Haskell seems to consist *only* of single-letter variable names. When did you last see a pattern like (customer:customers)? No, it'd be (c:cs), which isn't very self-documenting. Ditto for type variables by the way. (Map k v, anyone?) It also seems to be Haskell convention to use "a" as a type variable; personally I always use "x". I guess that's the algebra in my blood or something...
The people I spoke to also seemed pretty confused about the usage of (.) and ($), even after I explained it a few times. Several people also voiced being puzzled about Haskell's layout rules
Pointless style is definitely newbie-unfriendly. I can understand being puzzled by layout: ultimately I had to go read the description in the Report to be happy.
I posted a snippet of code which included the phrase mapM_ (\(n,v) -> putStrLn $ "[" ++ show n ++ "] = " ++ show v) (zip [0..] vs) To somebody familiar with Haskell, that is as clear as day. But to a newbie... well *you* try explaining that you start at the left end, take the thing in brackets, process it from left to right, then take the other thing in brackets, process the right side of it, then pass that to putStrLn, oh, but that thing right at the left edge is the argument list, and then pass the whole lot to mapM_, which is... are you still with me?? As one experienced C++ programmer put it, "there is no clear flow from left to right or right to left". Personally I found that a little ironic comming from the language that gave us while (*x++ = *y++) { } which is every bit as non-linear! ;-)
Have you tried showing people code that's been syntax highlighted? It's likely to help, especially with things like "does function application bind tighter?" where the highlighting is something of a cue. So is marking out = as important!
I'd just like to mention that HPaste is invaluable here! ;-) Oddly, nobody seemed to take much notice when I did this though. (I guess most people had seen "oh look, another Haskell thread" and hit the thread-kill button by that point...)
Btw, (> x) reads much more easily as a predicate to most people than (x <=).
Er, yeah, you're probably right. IIRC, (> x) is actually implemented as (flip (>) x), whereas (x <) isn't. I doubt there's any efficiency difference though. (Surely GHC would inline such a trivial function...)