[Haskell-cafe] Solving the configuration problem with parametrized modules

Joachim Breitner mail at joachim-breitner.de
Mon Sep 5 19:43:29 CEST 2011

Hi Cafe,

this is an idea that has been floating in my head for a while, and I’m
wondering about its feasibility and, if feasible, complexity (in the
range from „trivial“ over “blog post” over “paper” to “thesis”).

Application authors in Haskell often face the problem of run-time
constants, e.g. values that are expected to be determined once during
program start and then stay fixed for the remainder of the run. Good
examples are user configuration values (--verbose, certain paths,
debugging level, etc.).

Usually in Haskell, you’d determine them in the main function and then
pass them in an argument to all functions needing them, or you wrap that
in a monad. This works and has the advantage of being explicit. One can
locally change the value when passing it to another function – this can
be a good thing (more powerful) or a bad thing (if the programmer had
runtime-constant behavior in mind, an invariant not enforced by the type
system or the compiler).

The big downside is the verbosity of the approach: A lot of parameters
need to be passed, and if one such value is suddenly required in a
function where it was not before, this function’s signature and all
functions using it have to be modified. Also, I expect that the explicit
passing causes a small performance penalty.

A less idiomatic approach would be something like this:

module M
confRef = unsafePerformIO $ newIORef (error "not set yet")
conf = unsafePerformIO $ readIORef confRef
f = ... conf ...
import M
main = do
  writeIORef confRef theValue
  ... f ...

This has the nice effect that the programmer can use "conf" as if it is
a proper constant value. It could also be quicker, as nothing needs to
be passed on the stack. But besides the subtle issues about inlining,
this has the big issue of glaring unsafeness: There is no guarantee that
confRef is actually set before conf is evaluated, and any code can
easily change the confRef anywhere during the runtime.

I’d like to propose (on the theoretical level for now, don’t worry) an
extension to the language to support _parametrized modules_, which work
internally similar to the example above, but with the compiler
statically ensuring correctness, where correctness means
 * The parameter is not evaluated before it is set.
 * It is set at most once.

Rouch syntax sketch:

module M parameters (conf1, conf2)
f = ... conf ...
import M
main = do
  M.setParameters someVal1 someVal2
  ... f ...
where setParameters is a symbol generated by the compiler.

The tricky part is, of course, ensuring the correctness. For example
> main = do
>     M.setParameters 1 2
>     ...f...
should be easy to check, how about
> main = do
>     id $ M.setParameters 1 2
>     ...f...
or even
> main = do
>     bool <- someIOAction
>     guard bool $ M.setParameters 1 2
>     ...f...

I envision a ghc extensions that would allow to one to hook into the
type checker and attach bits of information (here: „uses conf“ and
„initizalizes M“) to the types, and also check certain conditions (e.g.
a >>= b is invalid if a and b both have „initializes M“ attached). If
this extension was loaded when id was compiled, it should probably
accept the second case, but when no such information is available, or in
the third case, reject the code. A framework for such attached bits
would surely enable more extensions that statically check some condition
that is hard or unwieldy to express in the type system.

I have more ideas in that direction, but before I start brabbling, maybe
I should first wait for your reactions.

Do you think this could be useful (from a user point of view)? Has this
idea maybe already been proposed? 


Joachim "nomeata" Breitner
  mail at joachim-breitner.de  |  nomeata at debian.org  |  GPG: 0x4743206C
  xmpp: nomeata at joachim-breitner.de | http://www.joachim-breitner.de/

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110905/72b1097f/attachment.pgp>

More information about the Haskell-Cafe mailing list