Your browser may have trouble rendering this page. See supported browsers for more information.

|<<>>|50 of 273 Show listMobile Mode

Handling Dependencies in Functional Languages

Published by marco on

Out of curiosity, I looked up how dependency injection works in functional languages. I stumbled upon this amazing article series—Six approaches to dependency injection by Scott Wlaschin (F# for Fun and Profit)
—that presents five different techniques—from very simple and easily applicable to more complex, but potentially robust.

The article series applies various abstraction techniques to a program that reads input, processes it, and writes it out again. The reading and writing are impure operations and should be abstracted away to make it easier to reason about and test the actual program logic.

The first article details Dependency Retention (hard-code everything; appropriate for scripts and POC projects) and Dependency Rejection (make an impure/pure/impure sandwich that collects program logic in a testable “middle”).

The next article covers Dependency parameterization (passing as parameters and using partial application in a separate abstraction layer). These are all pretty usable techniques.

The next two articles—The Reader Monad and Dependency interpretation—are more…involved. With both, you end up writing a description of your program that you can then execute by passing in the appropriate parameters. The dependencies are separate from the logic—in kind of in a separate layer—but there are drawbacks to these approaches. For one, they are quite complex and require everyone on the team to understand the patterns very well.

This is an example of the program description using the Reader monad.

The final article applies all of these techniques to a slightly more complex problem domain, namely a user-profile update that receives an update request, reads from a database, compares data to determine updates, and sends an email to confirm address changes. This is complex enough that we can see how the techniques scale. As expected, the more complicated but functionally pure Reader Monad and Dependency Interpretation examples take up 2/3 of the implementation and explanation (with the later taking 50% all on its own).

All in all, this is impressive work that answered my question superbly. Highly recommended. I’ve only very lightly summarized the pros and cons and descriptions above. The original author does a superb job of explaining these in much more detail—without repeating himself.