Cauldron: a toy dependency injection framework

I’ve been playing at writing a toy dependency injection framework that uses dynamic types under the hood. The cauldron library is the result. Basically, it wires a bunch of component constructors for you, so you don’t have to do it manually at the composition root of your app.

By “components” (or “beans”) I mean a bunch of records-of-functions with effects in IO. A way of structuring applications that doesn’t even use the ReaderT monad. Components get their dependencies as regular parameters, and that’s it. (I’m actually curious about why this architecture isn’t more popular in Haskell-land. Why reach always for ReaderT, transformers, or other effect systems?)

Anyway, the good news is that it seems to work. The bad news is that it doesn’t seem less verbose that wiring things manually. For comparison, here is a manual wiring of some toy components, and here is the same wiring using Cauldron.

In any case, this project has helped me learn about dynamically typed Haskell. Type.Reflection, Data.Typeable, Data.Type.Equality and all that. It’s actually a fun and useful part of the language!


Seems relevant for the pattern I wrote about!

I’m not sure how to read your example, though. How might this actually look in a real scenario, e.g. to write a function that reads from a database and makes a network request?

At first glance, it looks similar to how Scala zio registers all the components in an application, and while it’s all located in one place, that one file is a huge mess of wiring things up. Maybe we just haven’t used the pattern at scale yet, but we haven’t had too many issues yet with regard to wiring up the different components.


This may help to explain that tendency:

…and “committing early” to the monadic style also helps to avoid the annoying monadic refactoring of regular (un-monadic) Haskell code later, particularly if there’s a chance of I/O being needed in the future :-(