Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

According to this article, in object-oriented programming / design dependency injection involves

  • a dependent consumer,
  • a declaration of a component's dependencies, defined as interface contracts,
  • an injector that creates instances of classes that implement a given dependency interface on request.

Let us now consider a higher-order function in a functional programming language, e.g. the Haskell function

filter :: (a -> Bool) -> [a] -> [a]

from Data.List. This function transforms a list into another list and, in order to perform its job, it uses (consumes) an external predicate function that must be provided by its caller, e.g. the expression

filter (\x -> (mod x 2) == 0) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

selects all even numbers from the input list.

But isn't this construction very similar to the pattern illustrated above, where

  • the filter function is the dependent consumer,
  • the signature (a -> Bool) of the function argument is the interface contract,
  • the expression that uses the higher-order is the injector that, in this particular case, injects the implementation (\x -> (mod x 2) == 0) of the contract.

More in general, can one relate higher-order functions and their usage pattern in functional programming to the dependency injection pattern in object-oriented languages?

Or in the inverse direction, can dependency injection be compared to using some kind of higher-order function?

share|improve this question

2 Answers 2

up vote 6 down vote accepted

An important concept in programming is the distinction between bound and free variables.

Dependency injection is concerned with converting free things into bound things. This makes the code more general, easier to test, easier to mock, reduces coupling because the code knows less about its dependencies, etc.

Examples -- first with free things, then with bound things:

In this example, the first Foo knows that Bar has a zero-arg constructor, and knows the exact type of the instance. The second example doesn't know anything about how bar is created, and could even be getting a subclass:

class Foo {
    private Bar bar;
    Foo() {
        this.bar = new Bar();
    }
} 

class Foo{
    private Bar bar;
    Foo(Bar bar) {
        this.bar = bar;
    }
} 

In this example, pred appears free in myFilter but bound in filter. Thus myFilter is far less general. (Side note: the value [] and the function : appear free in both functions -- if they were instead bound, the result could be even more general!):

-- assuming 'pred :: Integer -> Bool' is defined elsewhere
myFilter :: [Integer] -> [Integer]
myFilter  [] = []
myFilter (x:xs)
  | pred x        = x : myFilter xs
  | otherwise     = myFilter xs

filter :: (a -> Bool) -> [a] -> [a]
filter   _    []    = []
filter pred (x:xs)
  | pred x         = x : filter pred xs
  | otherwise      = filter pred xs

Here's a type-level example. The type constructor [] appears free in map, whereas in fmap, the specific Functor is bound. (I hope that example isn't too confusing; map itself is a higher-order function. :) )

map :: (a -> b) -> [a] -> [b]

fmap :: Functor f => (a -> b) -> f a -> f b

In both examples, the code with fewer free variables, and more bound ones, is a more general version.


tl,dr; yes, dependency injection is similar to higher-order functions.


More examples demonstrating bound vs. free variables (because I think they're interesting):

This function has no free variables, because every variable that is used in the body is a parameter:

flip                    :: (a -> b -> c) -> b -> a -> c
flip f x y              =  f y x

In this example, f and g are bound from the point of view of (.), but free from the P.O.V. of the lambda abstraction (\x -> f (g x)):

(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)
share|improve this answer
    
Very nice examples and explanation. Why do you say that the type constructor [] appears free in map? I would interpret is as a constant, whereas in the fmap example you have the variable f. –  Giorgio Oct 24 '12 at 17:18
2  
@Giorgio [] is free because it isn't defined or bound within map; f is a bound type variable -- more about this; yes, map is a special case for lists of the generic function fmap -- here are some more instances. –  user39685 Oct 24 '12 at 19:18
1  
I think I understand what you mean. From what I can remember from my logic class, in a term a variable can be free or bound, but a function (or constant, i.e. a 0-arity function) is neither free nor bound. I would have considered [] a function name. Are you referring to lambda-calculus (with which I am not very familiar)? Then, if I remember correctly, every name is a variable, and if it is not bound by a lambda, then it is free. I guess I'll have to dig out my books again. :-) –  Giorgio Oct 24 '12 at 21:19
1  
The examples you gave are OK. I am just brushing up my knowledge to understand them (actually they are giving me a lot of insight). My intuition of free / bound was coming from what I still remember about FO logic: you have terms in which certain symbols are variables (which can be quantified) and others are constants, function, or relational symbols. Since these are not quantified, only variables can be free or bound. So, I was a bit confused when I tried to consider [] a variable. But now I get it: in a term any name can be considered a variable. Good examples. –  Giorgio Oct 24 '12 at 21:32
1  
Ah, OK! I see it now, in fmap the type is quantified / bound! Great answer, unfortunately I have only one up-vote, which I have already used. I will accept your answer. –  Giorgio Oct 24 '12 at 21:53

Yes, your example definitely represents a simple form of dependency injection.

It's not very impressive in that form - you can do the same in an OO language by having methods that take their dependencies as parameters (or classes that require them in their constructor). This just gets rather unwieldy as you pass around dependencies everywhere. Thus dependency injection containers which are responsible for constructing entire object graphs with all dependencies injected. I'm not sure what the FP equivalent would be.

Or in the inverse direction, can dependency injection be compared to using some kind of higher-order function?

I'd say so, yes. The problem that dependency injection tries to solve is the lack of flexibility when dependencies are hardcoded, which is what would happen if you had separate removeOddNumbersFromList, getAdminUsersFromList etc. functions.

share|improve this answer
    
+1, Good observation: I would also be interested to learn how dependency injection containers (bundles of related functions) can be implemented in a functional language. Maybe one can just define a record whose fields are functions and pass that around. I am not sure if you can do something similar using module signatures in Ocaml because I do not know enough OCaml. –  Giorgio Oct 24 '12 at 10:03

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.