Conclusion

Through this article, we have justified my friend’s statement that Free is merely the defunctionalisation of Monad in its most uncomfortable configuration:

That told us what Free is, but we’ve also seen why we’d want to use it: Free allows you to take simple DSLs and compose them comfortably, provided you butcher their ideal implementation a bit by adding continuations.

You’ll notice that these two things have rather important caveats: it’s the least comfortable version of Monad, and we have to butcher things a bit to make it work. This should be a pretty good hint that we’ve not quite found our ideal solution.

The intuition for a better solution is: maybe these two problems are symptoms of the same underlying issue. Maybe if we fixed the Functor constraint, everything would fall pleasantly in place. And since we have created the free monad over a functor, maybe we should consider whether we can come up with the free monad over any type constructor?

One way of achieving that is to realise that if we had the free functor over a type constructor, we could then combine it with the free monad over a functor and get the free monad ofer a type constructor. And the free functor over a type constructor exists, the extremely intuitively named Coyoneda. So, mixing Free and Coyoneda and working from there should lead us to our solution - but it’s very hard work. I think it’ll work, and have been told so by people who definitely know what they’re talking about, but I didn’t do it myself. I try to avoid hard work when I can get away with it.

The lazy solution is to realise that it might not be a coincidence that we’ve invented the free monad over a functor by defunctionalising a configuration of Monad that had a Functor requirement. Maybe if we drop the Functor requirement in the latter, it would also drop from the former? Maybe if we defunctionalised the other Monad configuration, via flatMap and pure, we’d get the free monad over a type constructor?

Following through on that intuition will lead us, rather easily, to a construct called Freer - the free monad over a type constructor. Which, anecdotally, looks very much like what Typelevel implements in cats (and called Free, presumably for a laugh) - probably a good sign that it’s worth studying next!