M
Matt Parsons
parsonsmatt.org · Personal blog · on HN since 2016
Matt Parsons writes about production Haskell, type-level programming, type safety, and software design practices.
What HN saysHN commenters recommend it as a top Haskell resource and link its posts on application structure, type classes versus interfaces, and GADTs.
57HN people shared it
28linked it in comments
37stories submitted
557story points
3 months agolast shared
2016people per year2026
Most-shared posts
- 1Three Layer Haskell Cake8 people · 2 points · first shared 2018 · discussion on HN
- 2Type Safety Back and Forth (2017)7 people · 6 points · first shared 2020 · discussion on HN
- 3Names do not transmit meaning6 people · 55 points · first shared 2019 · 41 comments on HN
- 4Sum Types in SQL (2019)4 people · 4 points · first shared 2019 · discussion on HN
- 5Write Junior Code3 people · 175 points · first shared 2019 · 141 comments on HN
- 6Basic Type-Level Programming in Haskell3 people · 124 points · first shared 2017 · 20 comments on HN
- 7The Trouble with Typed Errors3 people · 2 points · first shared 2018 · discussion on HN
- 8Haskell Proposal: Simplify Deriving2 people · 7 points · first shared 2020 · discussion on HN
- 9The Magic of Folds2 people · 7 points · first shared 2016 · discussion on HN
- 10Proving with Types2 people · 5 points · first shared 2016 · discussion on HN
- 11How do Haskell's type classes differ from interfaces?2 people · 3 points · first shared 2017 · discussion on HN
- 12An Elegant Fizzbuzz (2016)2 people · 2 points · first shared 2016 · discussion on HN
- 13Making Life Harder with GADTs2 people · 1 points · first shared 2025 · discussion on HN
- 14Homepage2 people · first shared 2016
- 15Exploratory Haskell (2015)1 people · 140 points · first shared 2016 · 60 comments on HN
What HN people wrote when they linked it
verttii · 2019-10-06
The best resource for me has been Matt Parsons' blog:
https://www.parsonsmatt.org/
kreyenborgi · 2025-01-24
Some follow-ups:
Making My Life Harder with GADTs https://www.parsonsmatt.org/2025/01/21/making_my_life_harder_with_gadt…
Making my life easier with two GADTs http://systema10.org/posts/making-my-life-easier-with-two-gadts.html
ParetoOptimal · 2023-05-03
> In production Haskell you need to combine monads using e.g. monad transformers
In some workplaces, yes. However it's pretty tenable to use https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html with no or few additional monads.
Alternatively, you can have just a few people that understand how to compose Monads and many others writing code within them.
I'm not sure if I think it's a best practice by any means, but it's a pattern I've seen that avoids having to include monad transformers in onboarding.
bradrn · 2022-09-20
> A typeclass indeed is very similar to an interface in object oriented languages
Agreed — as I mentioned in the post, typeclasses and interfaces are pretty similar. However, typeclasses and classes (i.e. the things used to make objects) are entirely different. I’ve seen numerous times when the similarity in names has caused immense confusion to people familiar with OOP, so I thought it would be worthwhile to clarify this.
(As for similarities between OOP and FP in general, you may be interested in this article: https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html. I endorse their conclusion that typeclasses can be used to implement something which in principle is basically OOP. Also, starting from a different point of view, I will note that Smalltalk code tends to be pretty functional in its structure.)
pwm · 2019-08-16
If you are curious this is a good read:
https://www.parsonsmatt.org/2017/01/07/how_do_type_classes_differ_from…
Tarean · 2019-01-28
That's the expression problem. But you can have the best of both worlds with various approaches. One nice one is called tagless final encodings in fp and object algebras in oop.
In haskell this is called mtl-style classes and quite common. Here is a blog post that describes how to split applications into an imperative, oop and functional layer. The oop layer uses mtl-style classes: https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html
marcosdumay · 2018-02-23
GetData is `Maybe a` (what means it's not a function).
GetMoreData is `a -> Maybe b`. And so on.
What means that those variables do not do what their names are claiming they do. It's a case of an example that lost its meaning once carried to a too different context. By the way, if you are wondering how functions that actually get data would look, there's a great architecture here:
http://www.parsonsmatt.org/2016/11/18/clean_alternatives_with_maybet.h…
blacktriangle · 2021-08-04
So totally different function, I meant by double to turn [1,2] into [2,4], however that's a really neat example. I hadn't seen the family extension in Haskell before. You're right there is a ton more to type systems than I was aware of. I was following some links in this thread and found this as well: https://www.parsonsmatt.org/2017/10/11/type_safety_back_and_forth.html…
I was less than impressed with type systems because like the blog post says, they tend to just kick the can down the road. The blog post uses a technique like you did in your example where rather than emitting more complicated type, they use the type system to protect the inputs of the function thus moving handling with the problem to the edges of the system which seems like a huge win. Between your example and that post I'm starting to see what people mean when they talk about programming in types, as its almost like the type system become a DSL with its own built-in test suite with which to program rather than a full programming language.
Either way very thought provoking, thank you for your responses.
TheAsprngHacker · 2020-05-11
I think there's perhaps an analogy to be made between FP terminology that comes from math, and is therefore unfamiliar to non-math people, and type theory notation such as this. For example, an FP "functor" comes from the idea of (endo)functor from category theory, but people try to rename it (e.g. "Mappable") to make programmers understand it better. In the same way, you're proposing to rename the turnstile to an arrow symbol.
The article "Why 'Functor' Doesn't Matter" [0] is relevant.
In this case, the turnstile symbol comes from logic, and means "entails": Given the information on the left, you can derive the judgement on the right. There is an important distinction to be made between the turnstile and the double arrow [1].
For what it's worth, I haven't formally learned higher-level math, but I've been able to pick up type theory notation just by getting used to it. I can't necessarily explain how; it was just a gradual thing for me.
[0] https://www.parsonsmatt.org/2019/08/30/why_functor_doesnt_matter.html
[1] https://math.stackexchange.com/questions/286077/implies-rightarrow-vs-…
lmm · 2019-06-27
> Thank you, I've read the links, but without an example of Haskell/Scala code the benefits for any particular real problem are not clear to me.
Do you have cases where you've used AOP/reflection/metaclasses/decorators/macros or similar "magic"? (Exceptions or mutable variables sort of work as examples, but most people don't have experience of working on codebases that don't have them). It's hard to give simple examples because these things exist to solve complex problems - one should never reach for a monad where a plain function will do.
> Specifically, speaking of the second link, what happens if you need to get rid of two types of 'hell' at the same time?
There are several possibilities. First, it's worth noticing that most forms of "hell" are fine on their own, it's the interaction between two that tends to be surprising - e.g. https://glyph.twistedmatrix.com/2014/02/unyielding.html talks about how important it is to explicitly manage async, but it's making an underlying assumption that your language will have mutable variables. Unmanaged, pervasive mutation in a language without async is ok; equally, unmanaged, pervasive async is ok in a language without mutation. So often you can get away with managing one effect and letting the other happen naturally according to the program control flow. (This is less true in Haskell because laziness is built into the language, so Haskell has kind of "spent its freebie" there - but it can be a very effective style in…
endgame · 2018-04-20
> If you take FP to its logical conclusion, FP is a slippery slope that eventually leads to Monad-Transformer centric designs.
I don't understand what you mean by this, and I write production haskell for a living. We don't have teetering towers of transformers, and the best advice I've seen is often "put away the shiny tools and just use functions",
https://lukepalmer.wordpress.com/2010/01/24/haskell-antipattern-existe… . Similarly in http://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html , which is like one real transformer layer and a way of claiming only the capabilities you need in your impure code. His "invert your mocks" article talks about this, too.
Ed Kmett's comments on Scala make me worry that the "solid foundation" isn't as solid as it could be: https://www.reddit.com/r/haskell/comments/1pjjy5/odersky_the_trouble_w… . How much of this is true in more recent Scala versions?
mrkgnao · 2017-07-31
> "simplest way to do BasicAuth"
The simplest way to do BasicAuth in Haskell isn't Servant. I feel like you're intentionally misinterpreting what I'm saying.
As for resources, here's a great intro to type-level Haskell:
http://www.parsonsmatt.org/2017/04/26/basic_type_level_programming_in_…
> For some reason, functions that operate on types are called type families.
That's the kind of thing you need to know.
I doubt the average JS user knows how V8 optimizes execution of code, or whatever. That's what your insistent complaints about type theory amounts to: none of the articles I'm linking to mention inference rules or type judgments or what-have-you. That's what all the research papers about Haskell are for, which you do not need to read to use this language. Even advanced Haskellers don't do type theory (category theory, maybe, not type theory). Only a couple of people working on the compiler do.
More DataKinds:
https://stackoverflow.com/questions/20558648/what-is-the-datakinds-ext…
http://ponies.io/posts/2014-07-30-typelits.html
https://www.schoolofhaskell.com/user/k_bx/playing-with-datakinds
aban · 2016-10-23
I'm going to go out on a limb and suggest this stack (especially if you're into functional programming):
Haskell + Elm or PureScript + Postgres
The best part about it is that it helps you catch many errors at compile time, instead of having your app crash at run time.
For keeping your Haskell and Elm data types in sync while maintaining sanity, I recommend elm-export [0], which will automatically generate the Elm types and JSON decoders from your Haskell code, using GHC Generics. Watch the author talk about it [1].
Choosing Elm over JS already gives you a head start, but you might hit a productivity wall at some point, and PureScript gives you all that extra power with its advanced type system. Some related discussion here [2].
Check out Matt Parsons' blog [3] for more on Haskell, Elm and PureScript.
Lastly, for database you can use Persistent [4] which gives you a type-safe API for data modelling and data store, and can automatically generate and perform migrations for you.
[0]: https://github.com/krisajenkins/elm-export
[1]: https://www.youtube.com/watch?v=sh4H8yzXnvw
[2]: https://www.reddit.com/r/haskell/comments/569cax/
[3]: http://www.parsonsmatt.org/
[4]: https://hackage.haskell.org/package/persistent
P.S. Do take my suggestions with a grain of salt as I don't have much experience with any of the fancy JS frameworks.
mrkeen · 2025-08-15
No idea how common it is. It's never been my main work language but I've been using it at work for prototyping/scripting/automation/analysis etc for at least ten years now.
It looks like what I've done is most similar to https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html
And I think this was the post that proposed tagless-final over free-monads: https://markkarpov.com/post/free-monad-considered-harmful.html
hans1729 · 2022-06-08
At first sight I’ve read “an object-oriented Haskell book”.
[brief pause for contemplating the thought]
Naturally, someone went there: https://www.parsonsmatt.org/tutorials/
danidiaz · 2022-02-26
> If we need to compose these errors in a larger program we can simply wrap previous errors in a bigger sumtype
This approach is being adopted in GHC itself to compose errors happening at different stages of the compilation pipeline: each stage has its own error type which later becomes a branch of the global error type.
Another interesting post about errors-as-values in Haskell is "The Trouble with Typed Errors": https://www.parsonsmatt.org/2018/11/03/trouble_with_typed_errors.html
thewakalix · 2021-06-26
A response to the common proposal of “we should call functors Mappables instead”: Names Do Not Transmit Meaning, https://www.parsonsmatt.org/2019/08/30/why_functor_doesnt_matter.html
yummybrownies · 2020-09-15
Three techniques for sum types in SQL (absorption, separation, and partition):
https://www.parsonsmatt.org/2019/03/19/sum_types_in_sql.html
Also, here is a relational database system with native support for sum types (and also no "NULL" nonsense, which is also not part of pure relational algebra):
https://github.com/agentm/project-m36
agentultra · 2020-05-05
Because names don’t carry meaning, they’re pointers: https://www.parsonsmatt.org/2019/08/30/why_functor_doesnt_matter.html
“Functor,” points to a specific concept in Haskell and a slightly different one in Category Theory but otherwise it is fairly unambiguous given enough context. The concept not only refers to the type and the associated “map” operation but also the axioms of identity and composition and their properties.
“Mappable,” is a very common name people pick in these discussions but it doesn’t clarify the meaning any more than calling it “Rose.” It may in fact cause more harm than good if a name like Mappable exists in more contexts. There are plenty of objects one can apply a map operation to that are not valid Functors.
jeremyjh · 2019-10-18
The capability pattern that Data Has implements is definitely used in other projects[1], and notably is endorsed by RIO[2].
[1]https://github.com/input-output-hk/cardano-sl
[2]https://github.com/commercialhaskell/rio#monads
Elaboration:
https://www.parsonsmatt.org/2018/03/22/three_layer_haskell_cake.html
felixschl · 2019-06-24
I thought the first example in this blog post on TH was an interesting idea: https://www.parsonsmatt.org/2015/11/15/template_haskell.html
Parsonsmatt · 2016-11-19
Writing code. Failing. Trying again and again. Slowly, at some point, it starts clicking, and before you know it, you're much more productive than you used to be in Ruby or whatever else, and then you're cursed by lambda.
I wrote this as an exploratory bit of Haskell before I knew monad transformers : http://www.parsonsmatt.org/2015/05/02/scotty_and_persistent.html
Three months after that, I had a fulltime Haskell internship, and a year after that, I'm working full time doing Haskell.
yazzku · 2024-12-03
Engineer vs mathematician. Haskell is the schizophrenic product.
> If I come to an existing OCaml project, the worst thing previous developers could do to it is have poor variable names, minimal documentation, and 200+ LOC functions. That’s fine, nothing extraordinary, I can handle that. > > If I come to an existing Haskell project, the worst thing previous developer>s could do… Well, my previous 8 years of Haskell experience can’t prepare me for that
This is kind of like Go vs C++, or <anything> vs Common Lisp. The former is a rather unsophisticated and limited language, not particularly educational or enlightening but good when you need N developers churning code and onboard M new ones while you're at it. The latter is like tripping on LSD; it's one hell of a trip and education, but unless you adopt specific guidelines, it's going to be harder to get your friends on board. See, for example: https://www.parsonsmatt.org/2019/12/26/write_junior_code.html
default-kramer · 2022-02-26
> https://www.parsonsmatt.org/2018/11/03/trouble_with_typed_errors.html
Nice. I've asked for a way to do that in the past and never found a good answer, in any language! It's not exactly conventional Haskell though, is it? What I really want is first-class support in the language - something like checked and unchecked exceptions in Java, except that if a method declaration lacks a `throws` keyword then all the checked exceptions are inferred by the compiler. For example, the compiler might add `throws A, B, C` to a method that lacks a `throws` keyword. Now if you want to assert that a certain method throws a certain exception, you could write `throws A, *` which means "If this method does not throw an exception of type A, I want a compiler error. If this method throws additional exception types, infer them as usual." Omitting the asterisk (eg `throws A`) would disable the inference and thus would work like a normal `throws` in real Java. You should also be able to assert that a certain exception type is not thrown, for example `throws * except F, G` or something like that.
runeks · 2017-08-06
> The front end is beginning to 'get it' with the likes of Typescript, Flow, Elm, Reason, Purescript, etc, and I can only hope that their good work and excitement will eventually flow back to us on the back-end...
I really have to say it’s been a joy writing the backend for a Bitcoin-related app[1] in Haskell. It took me a while to adapt to Haskell — probably a couple of years or so — but in the end it has left me with such strong compiler guarantees that I can literally grep through my codebase for “error|throw” and see where a 500-error may be thrown by the server.
The only somewhat laborious part is categorizing all the exceptions, that can be thrown when performing requests, into retryable and non-retryable ones, so requests that throw these intermittent, retryable errors are automatically retried (the retry package makes automatic retrying super easy).
This post[2] gets to the crux of how my coding has adapted over the years: getting rid of runtime-decisions (e.g. looking at a Maybe value at runtime to figure out what to), by moving the relevant parameters to the type level, such that program flow is determined at compile-time by which type an operation is parametized over. For example, the app is parametized over two types: DB implementation and Blockchain implementation[3], which makes the compiler construct a program for these specific implementations at compile-time, rather than making it a runtime-decision based on reading a config file at startup.
[1]…
psd1 · 2026-08-08
Ftfy:
http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.…
https://www.parsonsmatt.org/2017/10/11/type_safety_back_and_forth.html
https://lwn.net/Articles/336262/
https://tomasp.net/blog/2015/library-frameworks/
https://ratfactor.com/cards/not-quite-the-same
https://matklad.github.io/2023/11/15/push-ifs-up-and-fors-down.html
drunkboxer · 2026-08-08
I have a similar list I like to share, had a few from Carl's list, will probably add a few from it.
http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.… https://www.parsonsmatt.org/2017/10/11/type_safety_back_and_forth.html
https://lwn.net/Articles/336262/
https://tomasp.net/blog/2015/library-frameworks/
https://ratfactor.com/cards/not-quite-the-same
https://matklad.github.io/2023/11/15/push-ifs-up-and-fors-down.html
nextaccountic · 2023-02-17
This is my pet peeve with SQL. I hope some day PostgreSQL gain support for native tagged unions.
I have saved some links about this
https://github.com/solidsnack/pg-sql-variants
https://thelyfsoshort.io/variant-types-in-postgresql-c63725f8678b
https://www.parsonsmatt.org/2019/03/19/sum_types_in_sql.html
https://typeable.io/blog/2019-11-21-sql-sum-types.html
Right now I think the ideal is a jsonb column (with a field that stores the tag) plus
https://github.com/supabase/pg_jsonschema. But this is only usable if your language translates to/from JSON and generates json schema for you.
Rust can do this with https://serde.rs/ and https://docs.rs/schemars/latest/schemars/