12 ms·
Ask HN: Why Haskell?
I was hating on Haskell the other day. A lot of HN'ers apparently love it, because my comment was downvoted.
One of the replies said:
"I've seen experienced programmers failing at learning Haskell...the initial learning curve is very steep, and they don't see the value on climbing that wall...with Haskell, all those seemingly complex concepts come with a big reward." [1] [2]
My question is: I currently don't see the value proposition of learning Haskell. What is this great enlightenment I'm supposed to receive from studying Haskell? Can someone give me the TLDR version?
PS: If you say "functional programming", please elaborate. I know all about function pointers in C, and I've read the docs of Python's functools module [3].
[1] https://news.ycombinator.com/item?id=7478274
[2] I don't want this thread to degenerate into a favorite editor flamewar the way the other one did, so I'm leaving out the commenter's clearly preposterous claim that learning vim is worth your time.
[3] http://docs.python.org/3/library/functools.html
- bprajapa 13y agoShort Answer: The Actor Model
- quchen 13y agoHaskell is not about the actor model. It is possible to use it this way, but not what the language is about, or why you should learn it in particular.
- coolsunglasses 13y agoEdit: Before Haskell, I used Common Lisp, Python, and Clojure. I was impatient, generally more interested in hacking than math, and was happy using untyped programming languages. Haskell changes the equation, it (alone, for now) provides even better leverage and expressiveness than untyped languages like Clojure, Python, or Ruby. Further, it does so in a way that is more powerful and reliable because you have the leverage of the type system behind you. Learning to think about code in terms of types is a transformative experience. Types is where the future is headed. I've been getting people started with Haskell for the last ~3-4 months. It's not that hard to learn at all if you use proper learning material and do the exercises. Don't waste any time, just learn Haskell and find out for yourself. My guide for learning Haskell: https://gist.github.com/bitemyapp/8739525 https://gist.github.com/bitemyapp/8739525
- SamReidHughes 13y agoHave you ever used any other statically typed languages? How much of Haskell's benefit do you think it provides that simply having static typing doesn't provide?
- dllthomas 13y agoWhen you say "other statically typed languages" do you mean ML and Agda, or Java and C?
- SamReidHughes 13y agoAny. (Maybe not something as simple C or Go, and nothing like Agda, but something like ML or Java or C++.) There is something wrong with the grandparent post, because it's not making an argument that distinguishes Haskell from other statically typed languages.
- dllthomas 13y agoOk, well, for what it's worth I think that Haskell typing is equivalent in strength to ML. It's absolutely stronger than pre-generics Java; possibly isomorphic now. Roughly isomorphic to C++ with templates. In Haskell and ML, inference and clean syntax for type constructors makes it substantially easier to apply that power legibly (and structural pattern matching is a nice bonus). Monads let you extend that power to statements instead of just expressions.
- ibotty 13y agono, haskell (ghc) has many extensions that extend hindley-milner by a great degree.
- dllthomas 13y agoYes, I wasn't trying to make any strong claims of theoretical equivalence. In my experience with Haskell and OCaml and much more limited with SML, I've not found myself wanting to express a lot in those languages that I'd have been able to in Haskell, types-wise. Remember that the original question was "How much of Haskell's benefit do you think it provides that simply having static typing doesn't provide?" I should perhaps have been clearer.
- cjbprime 13y agoPerhaps three things: * Haskell is (very) strongly and statically typed and Python isn't. Haskell's type system can prove the correctness of many functions at compile time. In contrast, Python usually waits until runtime to throw exceptions, even for something obvious like a syntax error. * Because the types are known, there's an incredibly powerful testing framework called QuickCheck that is capable of e.g. generating tens of thousands of valid inputs and seeing if it can automatically disprove your assertions about your code. Python's typing is insufficient for this. * Qualitatively, writing Python feels like writing instructions for computing something, and writing Haskell feels like simply describing what something is, and the system works out how to compute it for you. It often feels compelling and magical. Lastly, some tone stuff: Function pointers have nothing to do with functional programming. And why hate on a language you haven't studied? And why does there have to be a TLDR version of a mind-expanding experience like learning a new programming style? Why form a strong opinion about something you don't know in the first place, and why feel entitled to challenge someone to explain it all to you? It's pretty frustrating.
- Ingon 13y ago> Because the types are known, there's an incredibly powerful testing framework called QuickCheck that is capable of e.g. generating tens of thousands of valid inputs and seeing if it can automatically disprove your assertions about your code. Python's typing is insufficient for this. I think immutability also helps on this front.
- SamReidHughes 13y agoJust being statically typed helps, there's nothing particularly special about Haskell that makes QuickCheck possible.
- coolsunglasses 13y agoHave you read the source to Haskell's QuickCheck? It can automatically derive automatic randomized generation of your data-types FOR you. No other generative testing library (such as for Clojure or Erlang) can do this. Further, the random data generation can be customized using the functional combinator API. Haskell QuickCheck's source code is a compelling example of what can be done with static types and typeclasses in Haskell.
- simplify 13y agoShort version: Most, if not all programming bugs are due to your code receiving something it did not expect. Haskell's type system helps eliminate this problem by forcing your code to declare exactly what it expects, and to handle all cases of said expectations. In other words, it's doesn't let you skip out by not thinking about the entirety of your code. It's the same line of benefits that TDD gives you, but TDD is, IMO, a stepping stone towards the pure, functional programming that Haskell provides. Note that I am by no means a Haskell programmer. To me, Haskell is the "last level" in learning development. I hope to one day reach such a level.
- SamReidHughes 13y ago> Short version: Most, if not all programming bugs are due to your code receiving something it did not expect. Haskell's type system helps eliminate this problem by forcing your code to declare exactly what it expects, and to handle all cases of said expectations. No it doesn't (force). It's about as good as C++ on this front, with better error messages. What it does do is make it a lot easier to program in a style that handles all cases, but without forcing you to do so. You can pattern match on something instead of making a visitor. But you can still call head or tail.
- coolsunglasses 13y agoYour comment misrepresents the reality for Haskell programmers.
- SamReidHughes 13y agoIf you wanted a useful reply you could explain how. The grandparent has things backwards -- it's possible for functions to force restrictions on their callers (by forcing them to pass a pure function as a parameter). The caller can't force the callee to consider all cases of its input.
- felipehummel 13y agoCan you elaborate on this: "and to handle all cases..".
- nbouscal 13y agoI've always disliked the notion that Lisp or Haskell are only worth learning because of some revelation they give you which makes you more productive when you inevitably return to a mainstream language. Yes, there are some good insights that both languages give you, but the real argument for using them is that you can be more productive in those languages, and that it is reasonable to use them in a production environment for that reason. I don't think the "return to mainstream languages" is inevitable at all, and I am very happily using Haskell in production at my current job. With that out of the way, what are the benefits? There are quite a few. The following is not a complete list, but I'll try to hit the main points. First, type safety. This is the primary argument for Haskell over something like Common Lisp or Clojure, and it is hands-down the strongest reason I choose to use Haskell. I used to hate static typing, because I thought static typing meant writing a bunch of boilerplate that didn't really get you anything and frequently got in your way. In Haskell this is not at all the case. As it turns out, type systems have improved dramatically over the past decades. In Haskell we have inference, so no boilerplate, and we have incredibly powerful facilities for polymorphism, so the type system provides real benefits. Being able to derive instances of type classes actually drastically decreases the amount of necessary boilerplate, even compared to dynamic languages. There's a common saying in the Haskell community that if it compiles, it probably does what you want it to. This has been my experience, and it is incredibly pleasant. Second, rigorous isolation of side effects. Countless programmers have independently realized how good this is over the course of their careers. Haskell enforces it. Knowing that a given pure function can't possibly break something in another distant part of the application is wonderful, and completely prevents entire classes of bugs. Third, the community. Haskell's community is often made fun of as being overly academic or too distant from the realities of programming, but in my experience the community's love of abstract mathematics is a massive benefit. One easy example is Edward Kmett's lens library. It is unabashedly abstract in its origins, and parts of it are still a little over my head. Despite that, it is perfectly usable without knowing the math behind it, and it is actually extremely useful in day-to-day programming. Things like functors, monoids, and monads are often poked fun at, but they are just way too useful for me to care. In this sense, the community is a huge asset, because people keep churning out these useful tools that you just won't see in other languages. Fourth, conciseness really is power. I often find myself writing one liners that would require a dozen or more lines in the other languages I've worked in. This frees me up to focus on the business logic, which is what actually matters. Parallelism is also a huge selling point, but I'll let someone else cover that because I don't have a ton of on-the-ground experience with it. Honestly, when I have to sum up in one sentence why I love using Haskell, it's because it makes my job easier. At the end of the day, it's really that simple.
- Ingon 13y agoI think if the curve is too steep probably you are trying to learn too much at a time. Focusing on small and well defined problems will help you out at least initially. For instance I used Project Euler[1] to study some of the basics, because the tasks there are well constrained and you cannot do too much architecturally. You will learn the mechanics of writing small functions, defining types, and then you can move onto something bigger, where high level concepts are involved. [1] https://projecteuler.net/ https://projecteuler.net/
- quchen 13y agoI don't think ProjectEuler is very helpful for learning a language. The first ten problems or so might be useful to learn the basic syntax, but after that it's really just about number theory, or optimizing brute force. If you're looking for Haskell beginner exercises, I recommend a) implementing functions from Prelude, Data.List, Data.Tree yourself b) doing the exercises given in RWH (even if you don't actually read the book - just do those you understand). RWH: http://book.realworldhaskell.org/read/ http://book.realworldhaskell.org/read/
- platz 13y agoexercism.io isn't bad either
- dustingetz 13y agoFunctional programming is where you end up if you ask the question, "how can I write better software more quickly with fewer bugs". I know of no shortcut to grokking why FP makes this possible other than just learning how to do it.
- AnimalMuppet 13y agoCribbing someone else's answer to my similar question (a couple months ago): Pure FP means no side effects. Side effects cause your state space to explode. (That is, no side effects means that the results of this function depend on its inputs only. Side effects means that the results of this function depend on its inputs, member variables of the object, file variables, global variables, the state of various things in the OS, user input read during the function, data read from the network, and maybe a few other things. It's much harder to understand such a function, get it working correctly, debug it, and prove that it correctly handles all corner cases.) The size of the program state space is your enemy, not your friend. Control it or die. FP dramatically helps you control it.
- clin_ 13y agoHere's a handful of things I really appreciate about Haskell, although some of this apply to other ML family languages as well: 1.) Algebraic Data Types let you enforce a huge amount of correctness in your programs simply by how you define your types. For example, say you have a data type that represents a player's state in a game. If the player is alive, he has a "HP" and "inventory" record. If the player is dead, he should just be dead—HP and inventory may or may not be set to 0 and None, respectively. In C or OOP languages, you just get a player object/struct and you have to enforce this state logic manually, and you can easily write a function that puts the player in an inconsistent state (player.alive = False, but player.HP = 15). In Haskell, you can define the player such that code that produces this kind of inconsistent state will not compile. Of course, you should still write tests in Haskell, but it's amazing to me that the type system can catch the vast majority of programming errors before your program even compiles. It takes longer to get something up and running, but you make up for this up front cost with long term gains in maintainability. 2.) Functional purity enforces two very useful properties: a.) Data is never mutated by accident. This ensures you never have to look beyond the scope of the function you're working on (or closing over, in some cases) to know what's going on. You can then compose these functions to create more complex programs. b.) When you do need mutability and side effects to happen, Haskell forces you to be very explicit about this and enforces a strict separation between "pure" and "effectual" code. This seems arbitrary until you realize that almost all of your errors not caught by the compiler happen because of IO. Whereas you have complete control over the pure part of your program, IO is nondeterministic and full of exceptions and edge cases. Separating this part of your code makes it far easier to reason about what's happening, adding to maintainability. As a side note on the last point: people make the argument that this separation makes Haskell impossible to do printf debugging. Not true—the standard library provides ways of circumventing the type system specifically for this reason. 3.) "Monads" and other fancy sounding abstractions can be hard, but with practice they become as intuitive as inheritance in OOP. The real barrier to entry is the awful, awful documentation everywhere. I make no apologies for that: it's just really shitty and the community needs to do a hundred times better.
- SamReidHughes 13y ago> In C or OOP languages, you just get a player object/struct and you have to enforce this state logic manually, and you can easily write a function that puts the player in an inconsistent state (player.alive = False, but player.HP = 15). False. In OOP you can do this using the visitor pattern. The difference is that Haskell makes this real convenient, with its algebraic types feature baked into the language, while OOP makes it very cumbersome. > As a side note on the last point: people make the argument that this separation makes Haskell impossible to do printf debugging. Not true—the standard library provides ways of circumventing the type system specifically for this reason. It's still far more annoying when the language is lazily evaluated and has Haskell syntax.
- maxcan 13y agoOne aspect that doesn't get mentioned much is recruiting from both sides. As an engineer, if you land a job coding haskell you're pretty much guaranteed to be an environment thats extremely engineering-centric, has minimal technical debt, and is staffed by lots of smart people. usedox.com, alpha heavy, jane street (ocaml but close enough), silk, tsuru, fobo are all exemplary examples of this. anyone of them is an amazing environment and you'll learn a ton. (the first one is my own company, so consider that one with a grain of salt) As an employer of engineers, if you put out a call for haskellers, you'll get a far smaller applicant pool than say ruby, python, java, or c#. But the signal to noise ratio is incomparably higher. Very few mediocre engineers will claim haskell as a skill.
- dustingetz 13y agoHi. At your company and other Haskell teams that say they hire elite engineers, is an engineer's compensation higher than comparable non-FP shops? Please forgive the bluntness; as a guy who is about halfway down "the road to Haskell", it seems like none of the shops that say they value FP are willing to pay more for it. For me, it's been easier to extract money from a javashop that's starved for talent and just figure out a way to install FP there. DK effect might also be clouding my self valuation.
- maxcan 13y agoDK effect? I can only speak to my current company (dox) and Jane Street, where I worked a long time ago. At JSC, comp was above market and everyone was quite happy but they've quadrupled in size since my time so YMMV. As Dox, we are currently bootstrapping off of a small round and everyone is working well below market in terms of cash but with commensurately higher equity. we will be raising a round later this spring and intend to roughly match or exceed comparable shops when that round closes. we've been completely transparent about that to the entire team as they've all taken pay cuts to work with us a this early stage, something we respect and are extremely appreciative of. If immediate salary is a principle concern, probably best to look at JSC, Stan Chart, or Barcap rather than a place like us or one of the other startups.
- dwc 13y agoA while back I was learning Haskell. I had a problem I wanted to poke at a bit, so I thought I'd give it a try. So I made various types in Haskell's nifty type system, which is NOT hard or tricky. I made some functions to work with the types. Easy. I worked all this stuff up and tried to compile, and being that I wrote a fair amount of code of course there were a couple of typos, etc. But then there was another part that wouldn't compile because I'd made an error, and the type system called me out on it. It's like getting the benefit of unit analysis (or dimensional analysis) from the compiler. That's one thing to like. A lot. There are other things. Polymorphism/overloading through type classes is so easy and clean it's hard not to love. The list goes on and on. For my part, I got hung up a bit on using monads. This was a few years ago, so maybe there are better articles/explanations now, but at the time there were a zillion monad tutorials, all of them written by people who almost but not quite "got it". I need to try Haskell again.
- quchen 13y agoThe Monad tutorial fallacy is an in-joke in the Haskell community nowadays, born out of what you observed: when people feel like they understand monads, they are so happy about it that they write a bad tutorial about it. My advice: Monad is a typeclass, and typeclasses unify things that act alike. Learn Monad instances (List, Maybe, State, ...) separately without worrying about how they are "monadic". After some time you will develop an intuition for what do, <-, return, >>= etc. have in common. And that's what Monad is.
- michaelochurch 13y agoHaskell encourages you to think upfront about the shape of your data, because you have to design the types upfront and your constraints are checked at compile time. You can build a level of reliability and quality into your software that's hard to achieve (not impossible, but rare without great programmers) with a dynamically typed language. There's a certain imprecision that you see with mediocre programmers. They don't know how things work, and get used to fooling around with a certain squishiness that's tolerated on large object-oriented projects as long as there's one good programmer ("architect") in the batch to clean up messes. That's good enough to get by in the business world, but not if you really want to understand what you're doing and call yourself a true programmer. Haskell forces you to build from the ground up, and a nice consequence of this is that, for any type, you can inspect its pieces and get down to the bottom. Functions will have easy-to-find type signatures and, sometimes, you can get a good sense of what the function does from its signature. In fact, in Haskell, the type system can be used to make assertions about functions like "this function doesn't have any side effects" and it's trivial to do so. In the long term, Haskell's heavy use of immutable data structures confers some major performance advantages as well. Is it the right language for every purpose? No, but it's very good for many, and it's a source of great ideas that have percolated into other languages, like Clojure and Rust. Additionally, it will force you to think rigorously about your data and what is happening to it.
- platz 13y agoI like the balanced tone you employ here. Not a fanatic but reasonable about the analysis.
- dllthomas 13y ago"[2] I don't want this thread to degenerate into a favorite editor flamewar the way the other one did, so I'm leaving out the commenter's clearly preposterous claim that learning vim is worth your time." Asserting that a "claim that learning vim is worth your time" is "clearly preposterous" is not exactly the straight and true path through the valley of flamewars.
- dllthomas 13y agoHaskell's biggest win is the power of its type system, including its ways of getting types places other languages simply can't. In C and Python, "a statement" is a different kind of thing than "an expression". Statements don't "have types" - the expression that makes it up may, but the value winds up discarded and the type doesn't matter (except maybe to produce a "unhandled value" warning, if you've set things up for that). In Haskell, statements are just another kind of expression, and the types of those expressions determine how they get chained together. This means I can leverage the type system to help me avoid new kinds of errors - want to be sure you don't try to do I/O in an STM transaction? Or access that variable from the wrong thread? Or... In Haskell, that's straightforward. In C, that's not something you can express and you have to check it all by hand.
- bsamuels 13y agoOne of the biggest perks of Haskell is that it has a very good static typing system. I wrote a blogpost awhile ago on the benefits of such a typing system, it's kinda long but you might find it interesting: http://bsamuels.net/blog/2013/11/20/StaticTyping.html http://bsamuels.net/blog/2013/11/20/StaticTyping.html
- jberryman 13y agoWhen haskell programmers say "functional" they mean "functions, like in math": yes, mathematics has higher-order functions (derivative, etc) but the main thing is a mathematical function doesn't fire missiles or mutate variables (what we call "side-effects"). Writing code that's like math is "declarative"; you describe what things are not what to do. Others have given lots of good views on the various upsides to using haskell, especially the ways in which the type system can catch bugs for you. But my favorite thing about the type system is it lets you create good abstractions. For example it's possible (and often quite easy) to create a library which cannot be used incorrectly. And because you finally have abstractions which are good (not brittle or leaky) you can build on them to create larger abstractions (by "abstraction" here, think: conceptual unit that is easy to reason about). And that's also one of the challenges with learning haskell: there's more to learn because we can create new abstractions that are worth learning. I like talking about haskell, but certainly won't presume to tell you you should learn it. But if you want to learn and are put off by what you've seen of it on HN for whatever reason, I can tell you that the community is incredibly generous and full of very kind and smart folks (though some humility and an open mind, as always, will get you far). The community is why I actually have something of a career in software today.
- BruceIV 13y agoI've spent the last two months wishing I'd written the project I'm working on now in Haskell instead of C++ - the main reason? Lazy evaluation. I'm working on developing a new algorithm, which is most easily defined as a set of constant functions over my data structure (a DAG with about a dozen node types). There's a fair number of places where I want shortcuts to not calculate things if they're not needed, and with Haskell's lazy evaluation I'd be able to just let the compiler handle most of those (the pattern matching constructs would make my functions-by-cases cleaner to define too). I'm doing some funny stuff with memo tables indexed by object pointers that would be trickier to do in Haskell, but I think there's likely a library I could leverage.
- coldtea 13y ago>If you say "functional programming", please elaborate. I know all about function pointers in C, and I've read the docs of Python's functools module That's maybe 1% of functional programming, if that. And from how you write about it, it seems like you haven't even tried to dabble with that (I mean, merely "read the docs of the functools module"?). But, if I may, I think the issue here is not about Haskell. Judging from the Haskell query, and what you write about learning Vim, I think you have a general aversion to anything that doesn't have an instant payoff and/or isn't trivial. Of course you can go on not knowing Haskell or Vim and 100 other things. Many do, and don't lose much, because there are other things. But if you go on avoiding anything that needs hard work and only offers a future pay-off, that is, anything with a learning curve, it will certainly hold you back. That is, if your ambition is to be a very good programmer (which might not be). If, on the other hand, you just want to have fun, and are content with easier stuff, there's really no reason to learn Haskell or anything hard for that matter.
- csense 13y ago> That's maybe 1% of functional programming, if that. I was asking where I can find the other 99%. > And from how you write about it, it seems like you haven't even tried to dabble with that Yes, I have. I use functools.partial all the time, and I've written programs that use function pointers in C before. I'm just trying to figure out whether "functional programming" means "passing functions around functions as objects and the sorts of hacks you can do with args/kwargs in Python," or if there's something more than that. For all the replies I've gotten in this thread, the best answer I've gotten is "it's all of the above plus immutable state."
- coldtea 13y ago>Yes, I have. I use functools.partial all the time Well, "I read the docs" doesn't convey that. And "partial" is just, well, a very small part of it. >and I've written programs that use function pointers in C before. I'm just trying to figure out whether "functional programming" means "passing functions around functions as objects and the sorts of hacks you can do with args/kwargs in Python," or if there's something more than that. For all the replies I've gotten in this thread, the best answer I've gotten is "it's all of the above plus immutable state." Only very superficially. Passing function pointers in C is just dipping your toes in functional programming -- if that. Let's say that those are the tip of the iceberg -- and that the whole idea lies in the interplay of functional concepts (much further than what people usually do in C, unless they implement their own ad-hoc Lisp in it). It seems like what you picked as "the best answer" from this thread is the one that reinforced a preconceived opinion, without having to actually try programming in a functional language. How about this reply you got above: "Lastly, some tone stuff: Function pointers have nothing to do with functional programming." -- and others like it.
- pekk 13y agoHow do you know why Haskell is superior to whatever you're using? Haskellers will tell you. It should be permitted not to think Haskell is the best thing ever, but in practice downvoting is heavily used for certain disagreements of opinion and this is one of them.
- deleted 13y ago[deleted]
- arh68 13y agoStateless programming is what the craze is all about. A lot of programmers grew up on C-style "x = 3;" kind of programming, so to write 500 good lines of code without an assignment operator can be a bit like walking down the street on your fingertips. There is nothing special about Haskell. Every single one of its qualities have been / will be reimplemented in other languages. Do not stare at the tree that is Haskell: talk about the forest that is PL research / features. For example, Shen is a great mindbender close in "power" to Haskell. It's a Lisp, it has an [inferential] static type checker, and only 2 functions in Klambda aren't referentially transparent. Personally I dislike Haskell's syntax and think Worse is Better, anyways. ;)