I think the proper answer here is, and I will probably receive a few downvotes just for saying this: forget the term dependency injection. Just forget it. It's a trendy buzzword from the OO world, but nothing more.
Let's solve the real problem. Keep in mind that you are solving a problem, and that problem is the particular programming task at hand. Don't make your problem "implementing dependency injection".
We'll take the example of a logger, because that's a basic piece of functionality many programs will want to have, and there are lots of different types of loggers: One that logs to stderr, one that logs to a file, a database, and one that simply does nothing. To unify all them you want a type:
type Logger m = String -> m ()
You could also choose a fancier type to save some keystrokes:
class PrettyPrint a where
pretty :: a -> String
type Logger m = forall a. (PrettyPrint a) => a -> m ()
Now let's define a few loggers using the latter variant:
noLogger :: (Monad m) => Logger m
noLogger _ = return ()
stderrLogger :: (MonadIO m) => Logger m
stderrLogger x = liftIO . hPutStrLn stderr $ pretty x
fileLogger :: (MonadIO m) => FilePath -> Logger m
fileLogger logF x =
liftIO . withFile logF AppendMode $ \h ->
hPutStrLn h (pretty x)
acidLogger :: (MonadIO m) => AcidState MyDB -> Logger m
acidLogger db x = update' db . AddLogLine $ pretty x
You can see how this builds a graph of dependencies. The acidLogger
depends on a database connection for the MyDB
database layout. Passing arguments to functions is about the most natural way to express dependencies in a program. After all a function is just a value that depends on another value. That is also true for actions. If your action depends on a logger, then naturally it is a function of loggers:
printFile :: (MonadIO m) => Logger m -> FilePath -> m ()
printFile log fp = do
log ("Printing file: " ++ fp)
liftIO (readFile fp >>= putStr)
log "Done printing."
See how easy this is? At some point this makes you realize how much easier your life will be, when you just forget all the nonsense that OO has taught you.