Using IxMonad to enforce good hamburger building in TypeScript
Because it’s not a burger if it doesn’t type-check
Credit: Original post Using IxMonad to enforce good hamburger building in Purescript by Justin Woo.
Recently I set myself up to finally try and understand Giulio Canti’s excellent fp-ts library. I believe this time I was finally able to, so I decided to try and put this newly acquired knowledge to the test, by porting Justin’s IxMonad article from Purescript to TypeScript.
Spoiler alert: It works like a charm.
How do you build a burger?
Not without types you don’t!
The first thing we will need are unique types for each possible hamburger-creation state. Like in Purescript, we do this by creating unique types for each representation. Sadly in this case we will not be able to avoid providing a data constructor.
All following code snippets will include the original Purescript code alongside its TypeScript version.
Making our indexed monad
Higher kinded goodness
Once again like in Purescript, we will define our indexed monad type, following the guidelines of fp-ts, and we will define the
runIxBurguerBuilder method. Afterwards, we will define the
ichain methods from
IxMonad3 respectively. We use the
3 variant because our indexed monad is of kind
* -> * -> * -> * .
Next we define the static version for these methods, as well as the remaining
Finally, we export the typeclass instances we implemented.
Adding commands to build our burger
Now that the type machinery is done, we can start writing the most fun part of the application: boilerplate!!!
As is starting to be the pattern, the TypeScript implementations follow the Purescript ones directly. The main difference is that I chose to provide the types as explicit type arguments to the
IxBurguerBuilder functions instead of adding type annotations. But the result should be the same, and it’s more of a matter of taste.
I reimplemented the complete source code, not just the excerpt from the blog post.
Let’s make a hamburger!
Now that we’re done with our definitions, we can begin to combine them by using the
ichain method, and make ourselves a well-formed hamburger.
And what would happen if we tried to make a hamburger that does not conform to our standards? Well, as we intended, the compiler will scream at our faces and shame us for trying to make such an abomination.
Takeaway (of fp-ts)
As we have seen, we managed to port Purescript code into TypeScript in an almost 1:1 fashion. This is cool. Very cool. fp-ts definitely does have its learning curve, especially if you intend to use it to define your own instances and typeclasses, but the end result is fascinating, and incredibly powerful.