Joachim Breitner's Homepage
On the drive back home from BelHac I thought about the configuration problem in Haskell: The issue is finding a convenient way to work with values that are initialized once and used in many places all over the code.
Assume you have a large module of pure code that, using many custom functions and combinators, parses some data structure. Later you noticed that somewhere far down in the parser, you need to react differently depending on some user preferences – say, his preferred language. The usual solution is to add a new parameter to that function and, in consequence, to each and every function that calls or might call directly or indirectly this function. This is often very inconvenient.
Other solutions include:
- Using mutable references and some hacking with unsafePerformIO, which always gives the programmer a bad conscience.
- Using a Reader monad, requiring a rewrite of the whole program in monadic style.
- Using implicit parameters which is ok if you did not write type signatures, but if you did, you still have to modify them a lot.
- Some advanced type hackery.
The solution I thought of and implemented uses Template Haskell, the Haskell library to modify code at compile time, to turn the style you prefer to write in (pure code that uses configuration values as if they were global constants) into the style that is semantically correct (pure code with configuration values as an additional parameter). I uploaded the resulting code as seal-module to hackage and added plenty of comments and examples to the SealModule module (⅔ are comments according to ohcount). I refrain from copying that into this blog post, so if you are curious, please continue reading there.