Wednesday, February 17, 2016

Selling Haskell in the pub

Summary: A Haskell sales pitch without any code.

I often find myself in a pub, without pen or paper, trying to persuade someone to try Haskell. In these situations I tend to use three arguments:

Low cost abstractions: In Haskell the cost of creating a helper function is low, because the syntax for functions is very concise (a single line) and the optimiser often removes all overhead of the function (by inlining it). The power of such helper functions is greatly enhanced by higher-order functions. In many languages each function must be top-level (within a file or class), but Haskell permits functions local to a small block, providing encapsulation and less necessity for good names. In most languages there is a much higher cost per function, and thus trivial functions are insufficiently valuable. By reducing the cost, Haskell encourages both less repetition and describing problems in a more abstract way, which is very helpful for taming program complexity.

Refactoring works: In Haskell, refactoring is easy, safe and common. Most projects involve writing a chunk of code, then continually changing it as the project evolves. In other languages most refactorings have complex side conditions that must be met. In Haskell, most refactorings are simple, and even refactoring tools can have complex refactorings mechanically proven correct. Any code which violates the expected side-conditions is considered "dangerous" and libraries are expected to provide robust abstractions. The static type checker ensures that most refactorings have been carried correctly. It is common to change a fundamental type in the middle of millions of lines of code, quickly make the changes required and have a high degree of confidence that it still works. The ability to easily refactor means that code can evolve with the project, without accumulating technical debt.

Language polygots: There are few programmers who know only Haskell. I know Haskell programmers who are also experts in Perl, PHP, C, Javascript, C++, Fortran, R, Algol - pretty much any language you care to name. In contrast, when my wife has attended other programming language meetups, many of the participants knew only that language. There are many reasons Haskell programmers know lots of languages, not least because Haskell has rarely been taught as a first language. I find it interesting that many people who are experts in both Haskell and other languages typically prefer Haskell.

In response to these arguments, if people are starting to get convinced, they usually ask:

  • Are there lots of libraries? Yes, 9000+. There are more R libraries for statistics, more Perl libraries for Bioinformatics etc - but most of the standard stuff is covered. Wrapping a C library with the foreign function interface (FFI) isn't too hard.
  • What's the performance like? It's usually somewhere between C and Python. If you carefully optimise you can get close to the performance of C. The profiling tools are reasonable. Performance is not usually a problem, but can be solved with C and FFI if it is.

Many of the above arguments are also supportive of other statically typed functional languages. I tend to find my pub interventions are usually aimed at Python/Java/C++/PHP programmers, where I'd consider it a win if they tried O'Caml or Scala instead.

2 comments:

Unknown said...

Maybe I'm not your target audience, but does the low cost abstractions get much traction? Maybe you are dealing with more sophisticated programmers than I'm used to.

I find the safety aspect most appealing to people in this situation. I know lots of people writing scripts and finding out part way through that the list they thought they were getting is actually a dictionary, at which point the script crashes.

Knowing (and fixing) this before they pressed "run" would be a god send.

Neil Mitchell said...

A lot of the developers I talk to are big fans of DRY (Don't Repeat Yourself), and have had to fight with junior developers to force them to introduce functions for shared functionality, even though the DRY formulation is longer than the normal formulation. They've seen plenty of bugs due to copy and paste. Cheap abstraction is a way of selling them on making the things they are trying to force people to do easy.

I absolutely love the safety, but selling it through refactoring has been easier when I've tried it. When you first write a script, there's a reasonable chance it won't work, either in Haskell or in an untyped language, because you got the design/spec wrong. You debug it. You write tests. Types help, but they don't solve the problem. It's when you get to refactoring a big system that you may not know how to fully exercise that the types turn certain refactorings from impossible to easy. Large projects get to this stage quite quickly.

So I guess my arguments are targeted at people who work on big code bases? That probably says more about the people I go to the pub with than anything else.