Introducing Haskell to a Company
Oct 2, 2018 - Brian Jones
A comment I wrote on r/haskell in reply to “How to introduce Haskell to a webdev shop?” prompted this post, which I hope ends up being helpful to others who may be considering introducing Haskell to their team.
This post makes the assumption that the reader understands why they themselves would want to use Haskell and what its benefits are, so instead focuses on how we’ve made it a successful part of our own company’s development culture.
First of all I think it’s important to understand the context of our team including where we came from and what we do. Hopefully this gives the reader reasonable expectations about what is written here as it may apply to their own company or team.
AlasConnect is a data center and telecommunications company which was founded in the 1990s in Fairbanks, Alaska. Since then it has expanded to become a Microsoft focused Managed Service Provider providing server hosting and tech support for businesses across Alaska and the Pacific Northwest. A few years ago AlasConnect was purchased by Matanuska Telephone Association, which provides broadband services in much of south central Alaska.
Until recently AlasConnect did not have a pure software development group to speak of, during which time my colleague Chris and I had worked for them as software consultants.
This history helps to illustrate that a relationship built on understanding of the company, its people, and its goals was established long before the development group was created. Without this, strolling in without knowing anything about the company and its existing environment, introducing Haskell would have more than likely been impossible.
I believe another reason it’s worth pointing all of this out is because we aren’t a singularly focused startup working on a single product. We are a small embedded development team working on a handful of applications spread across multiple companies, which means the amount of jumping around, maintenance, and outright non-standard applications we write are across the board on any given month. This type of scenario plays very well into Haskell’s maintenance and refactoring story. Moreover, the safety introduced by using a development stack based on Haskell reduces errors and bugs which could have a costly impact on an established businesses’ bottom line.
Points to Consider
These are the points from my r/haskell post, however, I should point out that they are mostly being made in a team setting. Solo/siloed developers will obviously have a completely different take on some of these points.
- You need to have enough buy-in within your organization to make Haskell adoption happen. Having solid understanding among your management, technical leads and others in the organization is key to successfully adopting Haskell in a production business environment.
- You need to expect pushback and resistance to change.
- Haskell is so incredibly different than most commonly used imperative languages, your team will need time to learn and hone their skills.
- If you are not able to teach Haskell techniques effectively (or do not understand full scale development in Haskell) you can expect to prolong this training timeline significantly.
- If your company can afford the time invested in the learning phase, you may be successful in this endeavor and see a number of benefits in terms of the quality your team is able to produce.
- You have to be the one to take initiative and build the first application, and then train people into it. A bunch of newbies to the language left floundering will start to resent it quickly as they will feel like they are not making any tangible contributions.
- Book resources are great, but they aren’t enough. You absolutely need a project for people to hack on so they feel productive while they are learning.
- You have to be diplomatic and understanding. Frustrating your coworkers are the fastest way to make them hate Haskell for life.
- Remember, it’s not just the language, but the ecosystem. What is the difference between cabal, stack, and nix? Hackage and stackage? Tools like hoogle exist.
- Can you explain Haskell’s warts? Nothing is perfect, and being able to show everyone that Haskell has bad points actually goes a long way to helping ground them.
The AlasConnect Software Team
When I started nearly two years ago AlasConnect itself had no standard development tooling or culture, and were just getting started with spinning up their own projects. The small group of members sounded interested in functional programming and were exploring Elixir at the time.
Being that we were constituting a new team we had several advantages, in that we needed to develop our standard development procedures (using a series of RFC’s circulated amongst the developers), decide on our common tooling for the team and implement our CI/CD platform from scratch. I started with getting buy-in from our CTO by pointing out how other standard development methodologies have failed us in the past, and showing that while Haskell may have a learning curve, the long term benefits can result in dollars saved and in the end a better quality product.
While building this team, we inherited maintenance obligations for a number of existing C#.NET applications, which makes sense given the enterprise nature of the companies we were dealing with.
That’s the big question of course, and it spawns a lot of sub-questions.
- What are the benefits of using Haskell period?
- Why would AlasConnect itself choose Haskell?
- Why would AlasConnect’s customers accept products based in Haskell?
Benefits of Using Haskell
To kick things off I wrote some slides to help explain the power of the language, although they feel slightly out of date now. The main point was to address some concerns everyone may have, and above all discuss some of the benefits of using Haskell.
I think the initial points are still valid.
- Reduce programmer cognitive overload
- Produce easy to reason about code
- Focus on the small, not the large
- Reduce the number of bugs with strong compile time checks
- Prefer catching problems at compile time
- Reduce testing surface
- Utilize strong types to build correct software
- Describe complex domains
- Runtime guarantees
- Ease of long term maintenance
- Refactor heavily without fear
- Types help guide compilation
However, the team and others did raise concerns about Haskell which they had heard rumored or read about, each of which had to be addressed in a direct and honest way:
- Haskell is a math language
- I have to learn lambda calculus (and category theory) to even use it!
- Haskell is a research language
- Only language researchers use it!
- Haskell is not used in production systems
- Haskell is incredibly hard to learn
- Haskell uses crazy terms like Monoid, Functor, Applicative, Monad
- Haskell is not a “corporate backed” programming language (like C#, Java, Go, Erlang, etc)
- Haskell has a high learning curve
- If I don’t grasp it in a day I will never be productive!
- Haskell has a smaller community compared to other popular languages
Time was spent talking about both the benefits and the drawbacks. As I mentioned earlier, being able to explain the warts of your chosen language helps people understand the benefits as well. If all you talk about are the ivory tower benefits, and then one day your team gets blindsided by things like terrible record syntax or poor documentation, they will likely begin to resent your choice.
Haskell at AlasConnect
The first step of course, was to lock in our development culture, processes, and tooling.
As I came on board the AC team was talking about using Elixir, a tool Chris had been utilizing for the past year and was somewhat happy with. (I recall him saying, “There is no way you will ever get me to write Haskell professionally” prior to me signing on. He is now our biggest Reflex advocate). Elixir/Erlang is definitely not a bad choice, but I spent some time showing people the merits of a strongly typed language like Haskell, and the benefits of having the compiler catch bugs long before the code ever reached production.
One of the favorite features of the development team was code sharing: The ability to use a cross section of code between a backend API and frontend SPA, which removes a large class of problems we had experienced when writing applications in two disparate languages in the past (Go and Angular.js).
Haskell in an Enterprise Environment
One of our customers had a large installed base of C#.NET code already in production and refactoring these systems into Haskell would not have been a productive use of time. However, in terms of net-new products and services (greenfield) we standardized on using our standard tooling, which meant integrating new with old, while maintaining legacy C#.NET code base.
Does it make sense to use Haskell in a large enterprise company? I would argue yes.
The majority of our work involves:
- Rewriting a public facing customer self service portal (billing, internet upgrades, etc)
- Writing new in-house tools which provide better UI/UX to processes which have been very manual up to this point
- Writing a large number of microservices which wrap some blackbox vendor APIs that are incredibly hard to work with directly
- Potentially writing some software which interacts directly with network devices over telnet, a place Haskell can truly shine (parsers!)
Honestly, either tool would be fine in most of these cases. However, the fact that the entire team is on the same page regardless of which company’s software they are working on is the biggest payoff of all.
It wasn’t just Haskell
I should point out that our primary Operations guru and I have pretty much seen eye to eye on things this whole time, and that having a solid set of modern day DevOps practices also helped get everyone on the same page.
- Everyone started seeing the benefits of GitHub PRs and code reviews, something they had never done before
- Everyone clearly saw the benefits of a CI server catching build errors long before the code reached production
- This is a great case for picking a compiled language, a large number of your problems can be caught with a compiler instead of tests
- Good service orchestration allowed us to make a solid microservice architecture instead of picking something like a heavyweight Enterprise Service Bus solution
- Even our more skeptical team members began to see the benefits of both Haskell and the surrounding tooling
- A monorepo, while not entirely necessary, has all of us looking at the Big Picture as we build and release new applications and common libraries
u/theindigamer asked a great set of follow up questions in my r/haskell post, which I will attempt to give better answers to here.
- How long did it take to go from zero Haskell to reasonably comfortable (mean +- stdev)?
- How did you manage different people learning at a different pace?
- Were people incentivized/nudged to learn Haskell? If yes, how?
- More generally, how did you offset the negative feelings people felt when they were unproductive as beginners? How did you manage expectations w.r.t. “yes, this will take more time to learn than you might anticipate”?
- How did you bootstrap, so to speak? By writing some non-critical code in Haskell? At the bootstrapping step, I’d think it would be hard to advertise ease of refactoring and have people take it seriously.
It probably helps to understand that we didn’t take all of our developers, drop everything, and then spend 6+ months learning Haskell while doing absolutely nothing else. That is a recipe for angry execs and unhappy customers, and a route we definitely did not go down. Instead, Chris and I started prototyping Servant + Reflex while everyone else continued working on their current projects, and once we reached that tipping point I mentioned earlier we immediately switched gears and started implementing a concrete project on top of our work up to that point. Everything has continued to evolve, of course, as it will, but by putting in that initial effort we’ve helped set the base structure for everything else we plan on doing in the near future.
How long did it take to go from zero Haskell to reasonably comfortable (mean +- stdev)?
I spent a couple months prior to officially signing on with AlasConnect tinkering with Servant and Reflex, because I knew they were going to be core tools we would use, and I wanted to be somewhat comfortable with using them before introducing a full team to the language and ecosystem. I also spent time compiling a list of useful resources such as books, relevant blog posts, and other web resources that could help the team learn.
The variation between going from zero to somewhat-productive in Haskell for everyone has been between 1-2 months, and seems to depend on prior development experience, temperament, interest, learning style, ability to unlearn imperative principles, and above all the ability to query mentors. When we first started almost 2 years ago Chris and I were a little shaky with our mentoring, these days the cumulative knowledge of the team is making it much easier to train developers new to the language.
How did you manage different people learning at a different pace?
Everyone learns differently. After throwing people at LYAH or HB, we then spend a solid day explaining our entire ecosystem (there’s a good chunk of non-Haskell specific stuff out there to understand), as well as some Haskell fundamentals and how it applies to our long term vision. From there, we have been assisting them with knocking out small features on existing projects.
That said, we did throw our resident intern off the deep end. He is implementing a brand new application from scratch (using our toolset) under the guidance of a mentor.
Were people incentivized/nudged to learn Haskell? If yes, how?
I think adding my own experience here may help. I feel that being as patient and understanding as possible, explaining things often, and doing pair programming went a long way towards getting people more comfortable with the language. Throwing someone Haskell Book and then expecting them to wade through ~1200 pages of college text book-like material on their own and coming out the other end as pros is unreasonable.
My biggest mistake was in the very beginning, where I asked people to attempt to write a small relevant tool in the language. They barely understood the concepts, if at all, let alone the ecosystem, the tooling (stack, cabal, nix), where the documentation was (if at all), or even knowing something like Hoogle existed. This was quickly adding up to be a recipe for disaster, but was remedied by Chris and I building the base for a core project and adding people after the fact instead.
More generally, how did you offset the negative feelings people felt when they were unproductive as beginners? How did you manage expectations w.r.t. “yes, this will take more time to learn than you might anticipate”?
This was probably the hardest hurdle to get over. For the few that knew absolutely nothing about Haskell, it was frustrating to learn that they couldn’t pick up the language in a day, let alone a week. There were a few strong rants against Haskell and its community at some point, however, I think the desire to not be “defeated” allowed them to overcome their misgivings.
I think the biggest thing that has helped is, again, giving people simple features to hack on with an existing project. This gives them the opportunity to examine the code written by others, and at the very least see some progress until they internalize some of Haskell’s core concepts. This approach is still a tough pill for some to swallow, some people don’t want to simply replicate how existing code works at first, they want to understand the underlying mechanics. This leads them down the rabbit hole, and ultimately to despair (imagine leaving someone to implement a basic lens, and when you turn back around they are reading books on category theory to understand the underlying code Edward Kmett wrote). I try to carefully explain that once the concepts become internalized things get easier, and gently guide them back to their primary goal.
In the beginning when we had absolutely nothing this was a little harder to deal with, but now that we have a large number of solid projects the concern is much lower these days.
How did you bootstrap, so to speak? By writing some non-critical code in Haskell? At the bootstrapping step, I’d think it would be hard to advertise ease of refactoring and have people take it seriously.
The recognition of the power of refactoring began to occur after we put that initial base code in place, and still continues to amaze people today. Recently someone said to me after I dropped a monster multi-project commit in place due to a change in a shared library, “If I had been doing this in Python I would have just scrapped it and wrote a v2, because there is no way I could have sanely refactored that many modules without breaking the entire thing.”
There’s no one-size-fits-all solution here. Successfully introducing Haskell into a company can be both challenging and rewarding.
Everyone’s situation is different, but if you attempt to introduce it to a team then it should be made clear that soft skills are one of the most important factors. Your ability to help guide and mentor your team will go a long way towards your eventual success.
On occasion I post on twitter (personal account), mostly about Haskell/technical things. Feel free to follow if you want to hear more about a company using Haskell in Alaska.