Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I think Haskell is kind of hard to learn for these main reasons: what you know from imperative programming mostly doesn't transfer, you kind of need to know a pretty big set of library functions in order to be productive, and for practical programs you often need to know a few tricks that aren't obvious that allow you to mix pure code and mutable state (how to exploit laziness, how and when to use the ST monad, what should be in the IO monad, etc..).

Additional roadblocks are that the syntax is strange if you're not familiar with ML-derived languages, the type system is fairly complex and you need to understand quite a bit of it to make progress, laziness can cause performance problems (lost parallelism, excessive memory use) if you're not careful, and the tooling isn't always as user friendly as it could be.

That said, I'm glad I learned Haskell, and though I don't know everything about the language, these days I'd feel pretty comfortable using it for anything I'd use any other decently-performing garbage collected high-level language for.



I would add, Haskell is bad at naming stuff, especially function arguments and generic type parameters. It has a tradition of point-free style which deliberately avoids names, and when names are required, they're typically meaningless single-letters. This makes it hard to build intuition and to follow code.

For example, the main Haskell graph library (fgl) has two type parameters, named 'a' and 'b'. Instead of meaningless letters, why not 'NodeLabel' and 'EdgeLabel'? Now it's obvious what they mean!


Yeah, that example seems like not-very-good naming. The standard library uses a lot of terse names, but that's often because in a lot of cases the types could be almost anything. Might as well just call them a, b, and c.

There's another general principle that the length of the names of variables should scale with the size of the context in which they're meaningful. So, a 10,000 line program might use a four-or-five syllable name, whereas a one-line function that takes two arbitrary arguments can just call them "x" and "y".

I do agree that points-free style and terse code can be problematic. Haskell lets you use very high levels of abstraction, but if the next person to look at your code doesn't understand those abstractions it'll tend to look like gibberish. I think my own preference tends to be not to go out of my way to make the program extra terse unless there's some compelling reason, like avoiding a lot of repetition.

I think plain old low-level C code is (sometimes) easy to read just because it has a lot of visual cues like "for" loops that your brain can pattern match on to tell you what the general control flow is. In higher level code, you often end up with fewer visual cues. Which is good in the sense that it eliminates redundancy, but bad in the sense that it can take longer to understand what unfamiliar code actually does.

Something that seems to happen in Haskell more than other languages I've used is that sometimes you can kind of forget how the lower layers of abstraction actually work, and it sort of just does what you want as if by magic. For example, the Lens library let's you update data structures using a syntax similar to imperative languages, but behind the scenes it's actually constructing a new data structure from the root on down to the "edited" leaf, and (unlike in imperative languages generally) if something goes wrong you can just throw up your hands and error out, and the old data structure is still there. It's like the convenience of imperative languages, but with transactions practically for free. But the type signatures that the Lens library uses are fantastically complicated. Though I sort of understand what the Lens library does, I really have no idea how it works internally. And I've decided that that's actually fine.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: