See a typo? Have a suggestion? Edit this page on Github
Goal: how to get Haskell into your organization, and how to make your organization more productive and profitable with better engineering.
I wrote this content 1.5 years ago after conversations with people at LambdaConf 2018. I discussed it offline with some people (at least… I think I did). Then I promptly did nothing else with it. After having some conversations with people at Functional Conf 2019, I decided it was time to resurrect and post this.
If the ideas I’m sharing here resonate with you, and you’re interested in getting involved with spreading this further, please reach out to me (privately is great,
michael at snoyman dot com). I have additional, more concrete ideas on how to make some of this a reality, which I’ll be sharing with people offline.
Thanks to everyone at Functional Conf for the inspiration and motivation to move ahead with this!
Haskell is in many ways a revolutionary language. Many languages in widespread use today are incremental changes on previous languages. However, Haskell doesn’t fit this model. Concepts like referential transparency, purely functional programming, laziness, and immutability are a stark departure from common programming approaches today.
Most any Haskeller would argue that these radical changes are well justified, and deliver great benefit. At the same time, this inherent culture of making revolutionary changes attracts a certain mindset to the language. As a result, we end up in a situation where Haskell has essentially two distinct (and overlapping) subcultures:
- Explore interesting and revolutionary concepts in computer science, software engineering, and mathematics
- Make better software
Again, these are overlapping subcultures. The entire history of Haskell is cases of esoteric, academic, intellectual, and “useless” concepts becoming an elegant solution to challenging problems. Monads are probably the most prominent example of this, and we’re seeing a reality where many other languages are slowly adopting the concept to solve problems in concurrency and error handling.
On the other hand, not every new concept turns into one of these fundamental and useful techniques. And even for those that do: finding the most practical way to leverage the technique is an arduous, time-consuming process.
Exploring these concepts can be fun, rewarding, and—long term—a huge benefit for productivity. Short and medium term, however, this exploration can lead to slower and less reliable results. As a company or project manager assessing Haskell for a project, this uncertainty can thwart the possibility of adopting Haskell.
We’re now faced with a situation where Haskell is often eliminated for usage, representing a massive loss for two parties:
- Companies, projects, and managers who could have realized great benefits in productivity, reliability, and performance from the less revolutionary pieces of Haskell. Instead, they’re losing this competitive advantage.
- Engineers who would much prefer working in Haskell—even its less revolutionary subset—are unable to do so because of employer fears of choosing it.
We’d like to improve the situation.
The Boring Haskell Manifesto
Our claim is simple: for many cases of software engineering, a simple, well-defined subset of Haskell’s language and ecosystem will deliver large value for a project, while introducing little to no risk compared to alternative options. We call this subset, somewhat tongue-in-cheek, “boring Haskell.” Our goal is to:
- Define such a subset
- Provide straightforward documentation, tutorials, cookbooks, and libraries that encourage this subset
- Continue to evolve the subset to optimize its best practices
- Help interested engineers to learn how to use boring Haskell, and get it adopted in their companies
The most concrete step in this direction was creating the rio library, which is intended to capture these principles. If you want to embrace Boring Haskell today, we recommend using that library. The rest of this document discusses what we believe counts as “Boring Haskell,” and motivates these choices.
We want to analyze the features of Haskell that we recommend based on its power-to-weight ratio, also known as a cost-benefit analysis. Put more directly: we want to choose features which provide lots of benefits while minimizing costs. Let’s give some examples of these two sides:
- More maintainable code
- Fewer bugs in production
- Higher performance
- Higher productivity
- Learning curve
- Ongoing cognitive overhead
- Ongoing tweaking
- Slower compile time
- Poor performance
A concrete example of something with a great power to weight ratio are sum types. Sum types are a relatively simple concept to explain. Most people can grok the concept almost immediately. Pattern matching feels natural fairly quickly. And sum types solve large classes of problems people regularly encounter in programming tasks.
This section is draft quality at best, feel free to stop reading here :)
A recurring theme I hear from people in industry is the risk of adopting Haskell. Let me address some of the common concerns directly:
If I’m stuck, there’s no support available. Haskell has a number of companies specializing in consulting services who are able to help. I work for one of them.
We can’t find people to hire. This is a valid concern; there are fewer total Haskell engineers. However, you’ve got some great advantages in Haskell:
- There’s less competition on the hiring side versus larger languages.
- People who like Haskell are very motivated to find a job with it.
- If you’re willing to hire remotely, there’s a large pool of candidates.
- Training people to work with Haskell is a real option. (This is an area that I intend to talk about more in the future.)
I’m afraid that I’m going to hit a wall and Haskell won’t work anymore. This isn’t a major issue in practice; most common code people will write is absolutely fine in pure Haskell. However:
- If you need to use some other language because of library availability or something similar, you can always connect with other languages. Microservices architectures—even if I’m not a huge fan—come into play here.
- If you hit a performance concern, you can usually solve it in Haskell itself by going lower level. However, the FFI in Haskell is really easy to use, so calling out to something like C or Rust is pretty easy.
- If you’re having trouble finding a way to solve things in a functional style, you can always drop down to imperative Haskell. Writing in a full-on imperative style in Haskell, such as all code living in
IO, may not be idiomatic, but it works. As SPJ has said (quote may not be exact), Haskell is the world’s finest imperative language.
For now, I’m just sniffing out interest in this general topic. I have some follow up ideas, but I’d rather get feedback on this idea before going further. Be in touch, and stay tuned!
- The Warp Executable January 20, 2020
- Tokio 0.2 - Rust Crash Course lesson 9 December 5, 2019
- Down and dirty with Future - Rust Crash Course lesson 8 December 2, 2019
- Boring Haskell Manifesto November 21, 2019
- Haskell kata: withTryFileLock August 18, 2019
- How to lose weight July 15, 2019
- My new home network setup June 26, 2019
- Gym Etiquette Test April Fools', 2019
- Typing Resistance April Fools', 2019
- Shutting down haskell-lang.org February 18, 2019
- Call for new Stack issue triager February 12, 2019
- Mismatched global packages January 24, 2019
- Kids Coding, Part 4 January 18, 2019
- Kids Coding Interlude: the function game December 16, 2018
- Improving Commercial Haskell December 13, 2018
- FP Complete's opinion December 12, 2018
- New user empathy December 11, 2018
- Async, futures, and tokio - Rust Crash Course lesson 7 December 3, 2018
- Lifetimes and Slices - Rust Crash Course lesson 6 - exercise solutions November 28, 2018
- Lifetimes and Slices - Rust Crash Course lesson 6 November 26, 2018
- Rule of Three - Parameters, Iterators, and Closures - Rust Crash Course lesson 5 - exercise solutions November 21, 2018
- Why (I believe) Stackage succeeded November 20, 2018
- Rule of Three - Parameters, Iterators, and Closures - Rust Crash Course lesson 5 November 19, 2018
- Stack(age): History, philosophy, and future November 18, 2018
- Crates and more iterators - Rust Crash Course lesson 4 - exercise solutions November 14, 2018
- Crates and more iterators - Rust Crash Course lesson 4 November 12, 2018
- Proposal: Stack Code of Conduct November 7, 2018
- Iterators and Errors - Rust Crash Course lesson 3 - exercise solutions November 7, 2018
- Iterators and Errors - Rust Crash Course lesson 3 November 5, 2018
- Basics of Ownership - Rust Crash Course lesson 2 - exercise solutions October 31, 2018
- Basics of Ownership - Rust Crash Course lesson 2 October 29, 2018
- Kick the Tires - Rust Crash Course lesson 1 - exercise solutions October 24, 2018
- Kick the Tires - Rust Crash Course lesson 1 October 22, 2018
- Is it healthy? Depends on context October 19, 2018
- Introducing the Rust crash course October 18, 2018
- RAII is better than the bracket pattern October 8, 2018
- How I research health October 2, 2018
- Kids Coding, Part 3 August 28, 2018
- Kids Coding, Part 2 August 24, 2018
- Kids Coding, Part 1 August 23, 2018
- Post Fast Write-up July 15, 2018
- Thoughts on Fasting July 10, 2018
- Stop supporting older GHCs July 1, 2018
- Deprecating the Haskell markdown library June 15, 2018
- I am not snoyjerk May 28, 2018
- My open source goals May 28, 2018
- Building packages outside snapshots May 23, 2018
- Guide to matrix.org and riot.im May 14, 2018
- Stop breaking compatibility April Fools', 2018
- LambdaConf Haskell Hackathon 2018 March 28, 2018
- Quick guide to the Jewish Holidays March 25, 2018
- Haskell Ecosystem Requests February 18, 2018
- Stack Patching Policy February 14, 2018
- The Conduitpocalypse February 4, 2018
- SLURP January 24, 2018
- Breaking changes, dependency trees January 9, 2018
- Drop Conduit's Finalizers? January 3, 2018
- Review of The Bridge strength program January 1, 2018
- Dropped packages following LTS 10 December 25, 2017
- What Makes Haskell Unique December 17, 2017
- Stack and Nightly breakage December 7, 2017
- Future proofing test suites November 12, 2017
- Effective Ways to Get Help from Maintainers October 23, 2017
- Posture August 16, 2017
- Some Upcoming Crazy Thoughts July 16, 2017
- The Spiderman Principle July 5, 2017
- A Very Naive Overview of Exercise (Part 3) June 15, 2017
- A Very Naive Overview of Nutrition (Part 2) June 14, 2017
- A Very Naive Overview of Nutrition and Exercise (Part 1) June 13, 2017
- How to send me a pull request June 6, 2017
- Why I lift June 1, 2017
- Playing with lens-aeson May 29, 2017
- The Worst Function in Conduit May 7, 2017
- Stackage's no-revisions (experimental) field April 27, 2017
- Haskell Success Stories April 24, 2017
- Generalizing Type Signatures April 20, 2017
- Enough with Backwards Compatibility April Fools', 2017
- Better Exception Messages February 16, 2017
- Hackage Security and Stack February 14, 2017
- Stackage design choices: making Haskell curated package sets January 23, 2017
- Follow up on mapM_ January 19, 2017
- safe-prelude: a thought experiment January 16, 2017
- Foldable.mapM_, Maybe, and recursive functions January 10, 2017
- Conflicting Module Names January 5, 2017
- Functors, Applicatives, and Monads January 3, 2017
- Beware of readFile December 22, 2016
- Call for new Stackage Curator December 19, 2016
- An extra benefit of open sourcing December 13, 2016
- Haskell Documentation, 2016 Update November 28, 2016
- Haskell for Dummies November 23, 2016
- Spreading the Gospel of Haskell November 22, 2016
- Haskell's Missing Concurrency Basics November 16, 2016
- Designing APIs for Extensibility November 3, 2016
- New Conduit Tutorial October 13, 2016
- Proposed conduit reskin September 23, 2016
- Monads are like Lannisters September 12, 2016
- Using AppVeyor for Haskell+Windows CI August 31, 2016
- Restarting this blog August 24, 2016
- XSLT Rant Explained April 9, 2012
- Open Letter to XSLT Fans April 5, 2012
- Dysfunctional Programming: FindMimeFromData March 22, 2012
- First Post January 31, 2012