When I recommend learning Haskell to the uninitiated, I often get asked: “Why Haskell?” “Is it a practical language?” and “Is it something I can actually use?” My answer is definitely yes.
Haskell isn’t my primary language at work (I mostly write C code for embedded systems), I’ve still found it incredibly useful. And even if I never used Haskell at work, I would still consider learning it as time well spent. So, why Haskell?
1. Haskell Plays Well with C
It turns out Haskell is a very powerful tool for helping you write C. Haskell has let me do things I would normally not even consider to be, umm, practical.
Say one of my coworkers wants to find all the places in a legacy codebase that a variable
foo is used in the conditional of an
if. Thanks to the awesome language-c library and Haskell’s generics, I can write a Haskell function that takes the path to a preprocessed C source as input and outputs the source locations (if any) like so:
parseAndFindFoos :: FilePath -> IO (Either ParseError [Position]) parseAndFindFoos path = liftM (fmap findFooLocations) (parseCFilePre path) findFooLocations input = fmap posOf (listify isIfOfInterest input) isIfOfInterest (CIf cond _ _ _) = not (null (listify isFooIdent cond)) isFooIdent (Ident name _ _) = name == "foo"
Not including the type signatures, that’s just 4 lines of Haskell! The type signatures are usually inferred anyway, but it’s customary to include them as doc strings.
This is just a blog-post-sized toy example. I’ve I use Haskell to do far more complicated things, like extracting the names and types of functions and global declarations or performing a transformation that inserts bounds checks or logging functions in expressions that match certain criteria. There are not many other languages that would let me do this as succinctly and quickly as Haskell does.
I’m Not the Only One Making Tools for C in Haskell
One of my coworkers made an awesome tool called plunge that lets you compare preprocessed code c with the original and shows what each line in the original was processed into in the preprocessed version.
- atom – A DSL that performs compile-time task scheduling and generates code with deterministic execution time and constant memory.
- copilot – A stream (i.e., infinite lists) domain-specific language (DSL) in Haskell that compiles into embedded C.
- ImProv – An imperative programming language for high-assurance applications. ImProve uses infinite state, unbounded model checking to verify programs adhere to specifications.
And many others.
2. Haskell Changes the Way You Think
I really think the most immediately practical side effect *snirk* of learning Haskell is that it forever changes the way you think about code. Yes, yes, I know this sounds like warm, fuzzy, vague BS, but I’m serious! Learning Haskell has had more of an impact on the way I code, and the way I think about code, than anything I learned in school and any of my on-the-job experience.
Have you ever tried to write a complex function without using any mutation? At first it’s quite painful. But once you get some practice, not only does it get much easier, but you start realizing that your functions can get broken apart into much smaller pieces than you originally thought possible. That complex function will turn out to be not all that complex at all; it can be written as just three simple functions composed together!
It’s like if you only played soccer with your right foot. And then one day your coach forbids you from using your right foot. At first you suck at everything. But eventually you become just as good at using your left foot as your right, you and end up being a much better soccer player.
Haskell is so different that it forces you to think about your code differently. This is part of why it’s a hard language to learn, but also why learning it is so advantageous.
3. Haskell’s Steep Learning Curve Is a Good Thing
The most common complaint people have when learning Haskell is the steep learning curve. And they’re right, it does have a steep learning curve. It’s like learning programing all over again. It takes a bit to unlearn the patterns you instinctively want to use. No mutation! Static Typing! OMG they’re passing the value returned from that function as one of its arguments! WTF is going on!?
The hard part about learning Haskell is not the complex things, it’s the simple things. Like Monads; Monads are ridiculously simple. They’re just a datatype with an instance implementation of two very simple functions. Most implementations are just one or two lines! It’s the comprehending the implications, usefulness, and power of these very simple things that takes so much work. Profound things take time to learn. This is ok. It means you’re learning something that’s worth learning.
“Do you want to be locked into tricycles because they’re easy to learn?” – Douglas Englebart
Any recommendations for resources for learning it ? I started off with Learn You A Haskell, it made my head hurt, is it a good starter and I just have to persevere ?
Real World Haskell is also quite good.
Learn you a Haskell is a pretty good starter, but you could also try some of the options mentioned in this excellent stack overflow post: http://stackoverflow.com/questions/1012573/getting-started-with-haskell
There is also the very new School of Haskell here: https://www.fpcomplete.com/school
(all of the examples in the School of Haskell are interactive, which is really nice)
Also, if you want to tinker without installing Haskell you can use this: http://tryhaskell.org/
Just a tidbit.
You used “it’s” (“it is”) where you should have used “its”:
“OMG they’re passing the value returned from that function as one of it’s arguments!”
I’d also recommend looking at FP Complete’s School of Haskell. Lots of great tutorials, no signup required, edit and run Haskell code in your browser. Bartosz Milewski just put up one about monads and laziness.
So show us how to do simple things in it :)
I mean… give illustrated comparisons between the language and others. Real world things, not academic things.
The other day I had to build a thing that would tell me which points in an array of points were changing direction (where here, changing direction means changing its slope direction on the y axis).
This is what I came up with in ruby:
# array_under_question is an array of Point objects, which have an x and a y attribute
array_under_question.each_with_index.each_cons(3).inject() do |change_point_indexes, ((point_1, _), (point_2, this_index), (point_3, _))|
first_pair_direction, second_pair_direction = (point_2.y point_1.y), (point_3.y point_2.y)
(first_pair_direction != second_pair_direction) ? change_point_indexes + [this_index] : change_point_indexes
This struck me as intensely convoluted and that only people quite well versed in ruby would be able to understand it. Is the equivalent easier to understand in haskell?
I wrote a step by step translation of your Ruby code to Haskell, have a look: http://hpaste.org/83550.
Note that this is just one way to do it and that you don’t have to write out the type annotations, which I just added because they help me understand the program.
Here’s an example in more idiomatic haskell:
The focus is really on function composition and successive, simple transformations to get to what you want.
Job, were you familiar with Lisp (any variety) prior to learning Haskell? Many programmers say that learning Lisp also changes the way they think about code. I’m curious if learning Haskell after Lisp still gives that mind-expanding benefit, and likewise for learning Lisp after Haskell.
My gut feeling is that it probably does, because Haskell and Lisp are mind-expanding in different directions. I’d love to hear from someone who has learned both, in either order.
In my experience, yes. Common Lisp and Scheme have taught me different things than my time with Haskell so far. Haskell overlaps more with the things I learned from OCaml, but emphasizes laziness quite a bit more.
Not taking away from Haskell (played with several functional models over the years) … but
How would Haskel compare to F# … and would it make sense to “learn functional programming” in F# if you were a dotnet-er?
How would the Haskell versus F# experience differ?
You mentioned “embedded” … have you looked at Hume?
.. or the other versions?
The MOOC courses I’ve done online have been worthwhile. Two Coursera courses :
Functional Programming in Scala ( it is “in Scala” and about Scala but it covers functional programming.
Programming Languages ( 4 weeks ML, 2 weeks Racket + Ruby )
These will give you a much better idea of what thunks, laziness, closures, currying, etc are than any book I’ve seen. By and large, books concentrate on syntax but ignore semantics – bad, because a lot of FP languages share a fair amount.
The most common complaint people have when learning Haskell is the steep learning curve.
Why would anyone have problem with steep learning curve?
Maybe a good starting point would be to learn first what steep learning curve is … http://en.wikipedia.org/wiki/Learning_curve
more on language-c would be nice.
Haskell is a language that has everything that other languages have tried to avoid and recommend against. It is more of a wish than a language. A language that is still trying to get the very basic ideas right. The learning curve is opposite of the learning curves of other languages; that is the beginner starts at high up on the y axis and ends up very low on the same curve with x at infinity (yes, Haskell is equipped with infinity) very fast. Ideas are glued over other ideas and mistakes of the past are remedied by new mistakes. It is an ongoing process. Of course it works sometimes. That is why we are hearing about it and some people are learning it and some claim to know the language, but each and every one of them is using another language for doing anything that is worth doing and goes to Haskell as a mental exercise or hobby. In short it is a kind of language that cannot be explained. There are not many books on Haskell programming and the few that struggle to explain simple ideas, like Types and creating Types, supposedly the strongest point of the language Haskell fail miserably at every turn. The only part of Haskell that, as far as I know, is unique is lazy evaluation which in practice one never gets to making good use of anyway. I am of the humble opinion that spending hours or perhaps days and months just to write a straightforward algorithm or logic into n lines of code in something like Haskell that can be done in 1.001 n (that is multiplication Haskell style) lines of code in a saner and more humble language like C or Python is just a waste of time or time better spent at solving a Rubic Cube or solving entertaining mathematical puzzles or chasing member of opposite sex or climbing a rock or digging a hole in the backyard and refilling it. Of course those who have paid in nerve and time and Mana for Haskell will accuse me of laziness or not being equipped with sufficient mental faculties to learn Haskell or not fortunate enough to be faced with serious, hard unsurmountable tasks and problems and situations that call for something like HASKELL, but then again isn’t that what they claim Haskell is all for?
Comments are closed.