Functional programming and decoupling

I struggled with this question for years before I realised that I was looking at it the wrong way. Coming from object-oriented development and Dependency Injection, I kept looking for a functional alternative to Dependency Injection. I finally realised that Dependency Injection makes everything impure, which means that you can’t use that approach (not even partial application) if you want to apply a functional architecture.

The red herring is to focus on the dependencies. Instead, focus on writing pure function. You can still use the Dependency Inversion Principle, but instead of focusing on actions and interactions, focus on data. If a function requires some data, pass it as an argument. If a function has to make a decision, return it as a data structure.

You don’t provide any examples of where you’d want to use a list of Category values, but a function that depends on such data would have a type like this:

Category list -> 'a

Such a function is completely decoupled from the source of the categories. It only depends on the Category type itself, which is part of the Domain Model.

Ultimately, you’ll need to get the categories from somewhere, but this work you push to the boundary of the system, e.g. Main:

let Main () =
    let categories = getCategories ()
    let result = myFunction categories
    result

Thus, if you change your mind about how to get the categories, you only have to change one line of code. This kind of architecture is akin to a sandwich, with impure actions surrounding the pure heart of the application. It’s also known as functional core, imperative shell.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)