I recently finished my first sizeable project in Haskell; or at least the first phase of that project, since software is rarely finished. I generally came out quite impressed with it. I’ll post some updates on the project itself presently, but in the meantime, a few thoughts on Haskell itself.
Even though it is having a fashionable moment, Haskell is not a new language. I first encountered it in an undergraduate class on functional programming more than twenty years ago, and according to wikipedia, the first release appeared when I was in school. My undergrad had a strong formal methods component, so the set theory and logic base didn’t seem obscure. The first programming assignments I did in it were neither traumatic nor particularly inspiring. It was good to know about these corners of computing, but the trademark evangelical fervour that functional programming inspires did not descend upon me.
Nevertheless, I had a few other cracks at it over the years. During this time period my day job was mostly in Java or Python, as well database-centric or Unix script scaffolding work along the way.
At the first attempt, in the early 2000s, I bounced off the awkwardness of I/O, and dealing with monads. I would have been using a basic windows text editor, ghc, and A Gentle Introduction To Haskell, which hasn’t changed much since. I found I could make pure functions do tricks for me, but I didn’t get how to stitch them into usable programs for reading and writing data. I dug into this new Agile Software Manifesto stuff instead and plunged into eXtreme Programming eXplained and the c2.com wiki.
Jump forward a decade or so. I had a chance to work with a team of terribly smart developers who owned a large near-real-time time-series database written in kdb+. Kdb+ is a blazingly fast column-based database with an associated functional programming language called
q is laconic almost to the point of esotericism, but its elegance and performance are mutually supportive structures, and for a long time there was nothing else that could match it in its high-performance niche. There’s been a much more general push towards functional programming constructs in many different programming contexts over the same period. Based on what I’d read, I tried weaving in more functional-style design in my everyday work. Python was an easier place to experiment with this, both because it’s had functional programming concepts like list comprehension for longer, and because it was used in tooling and scaffolding parts of the platform at my old job. Interesting Haskell people started slicing across my twitter feed. And there was always a kind of intellectual pride to working with it; a certain “1000 programming languages to use before you die” vibe taunting me. I gave the 2018 Advent of Code a go in Haskell and got a bit more comfortable with it, but didn’t need to venture much beyond running things in
Catching up to the current day, this most recent project had a number of elements that suggested a good match with functional programming. Firstly, it was a process mining project with a quite formal mathematical grounding, around a key central data structure, in this case as part of a paper I was working on for my current day job. Secondly, the idea I was working on involved formulating a number of transformation rules, and Haskell-style pattern-matching was a very clean way to translate them into code. Thirdly, I thought the discipline of the type system would help reinforce the formalization. The performance reputation of Haskell compared to other functional languages also didn’t hurt.
The programming experience was different to other languages, though it’s a difference of degree rather than a difference in kind. As is often related, more work is required to get the code to compile, mostly due to the strict static typing. I wouldn’t say that if it compiled it always just worked, and but things do work as expected at run-time much more frequently. This gives the whole experience a Calvinist quality. Only programs that are one of the Elect may be permitted to enter into runtime Heaven, but once they get there, they can have tea and cakes. (You can tell it’s Scottish.) This general edit/compile interaction loop holds until you hit a performance bug, which requires new levels of insight into the compiler internals. This knowledge level jump isn’t so dissimilar to dealing with performance bottlenecks in other languages, but so far my existing knowledge has been a bit harder to translate.
I had the monad-understanding problem in the past, but something clicked in this project. The intuition I ended up with was that it was an infinite stream. It might have helped that I worked a lot on event based systems since my first two encounters with the concept. I have done a bit of category theory reading, and will do more for various reasons, but that formal grounding didn’t seem like the key for this falling into place. Getting my hands dirty dealing with XML files was much more crucial.
On the library side, there is a decent set of libraries, but strings and unicode still seem like a bit of a mess. There was a very clear moment where I was able to show my basic idea, structure and algorithm working in prototypical pure Haskell code in about half a day. That was followed immediately by three days getting XML parsing to work. I didn’t deal with any network or database interaction.
The really striking thing about doing this project in 2020-21 was the leap forward in the Haskell library and tooling ecosystem. It’s also now centred as the entry point to the platform.
stack works quite well as an build orchestration tool, dependency management is pretty much solved, and there is a richer library ecosystem. Unit testing is no longer a third-class citizen (HUnit behaved pretty well for me). The community support to actually put those things in context also seems to have improved greatly. Learn you a good haskell is very deliberately written in a goofy and accessible style that contrasts with the traditional Free Church of Haskell austerity. Simply the availability of multiple texts helps, as is often the case in mathematics. The stackoverflow answers have also hit a certain critical mass, and bridge a craft gap expensive to cross solo. This was more for questions like “there are three libraries for this, what are the trade-offs” as for syntax things, though I certainly hit those too. Daniel Procida persuasively says there are four types of technical documentation. Historically Haskell really just had two: reference and explanation, and the explanations read like an overworked maths tutor. Stackoverflow fills the tutorial, how-to and recipe gaps in a way the old mailing lists never quite managed for me.
It’s still not the easiest community to enter. Historically, the theoretical strength of Haskell always socially undercut using it to actually build things. Functional programmers are a community where a running joke is “a monad is just a monoid in the category of endofunctors, what’s the problem?” and one of those
q programmer ex-teammates had a jacket with the motto “Dolce et decorum est pro computeria mori”. And a part of me does love that sort of thing, but another part of me just wants to get this unit test working without using a Latin dictionary. Even though huge strides have been made, you can still see a certain disdain for actually running things, or people that learn concepts examples-first instead of theorem-first. You will still run into stuff like the suggested windows installer being version 0.0.1 and not including stack. During the project I added the first runnable example code to a couple of stackoverflow questions about basic concepts like trace debugging; previous answers just linked back to the same terse reference documentation.
I had a good engineering match for this project, and I would want that before I used Haskell again. But overall I was pleasantly surprised with how much it has matured beyond its purely academic birth into a powerful engineering tool backed by robust theory. I can see it being much more important industrially in the future, and I’m definitely looking forward to using it again.