Using IxMonad to enforce good hamburger building in TypeScript

Because it’s not a burger if it doesn’t type-check

Medium says people like high resolution images, so here’s a photo that I took

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 map and ichain methods from Functor3 and 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 IxMonad3 method, iof.

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 addIngredients and 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.

Once more I’d like to thank Giulio for his amazing work and Justin for putting up this simple example originally.