[Haskell-cafe] Reinventing a solution to configuration problem

Krzysztof Skrzętnicki gtener at gmail.com
Fri May 10 07:45:41 CEST 2013


Hello Cafe,

I came up with (actually reinvented [1]) a solution to configuration
problem. For example configuration:

data Config = Config { port :: Int, verbosity :: Int, logfile :: FilePath }
deriving Show

the basic idea is to use implicit parameters:

runServer :: (?config :: Config) => IO ()

The problem is that it is tiresome to decorate all functions in this way.
It is also non composable. For example if we switch to using two separate
configuration entities like this:

data LogConfig = LogConfig { verbosity :: Int, logfile :: FilePath }
data NetConfig = NetConfig { port :: Int }

we suddenly have to fix types all over the place. Yuck.

The extended idea here (compared to [2]) is to use type synonym with all
required parameters. This is simple (but requires at least Rank2Types):

type ConfIO a = (?config :: Config) => IO a

All the functions requiring config will now be simply in ConfIO monad which
is really IO with a bonus. A great feature of this solution is that we
don't need to use liftIO anywhere.

The core *problem* with this approach is that at least current version of
GHC fails to propagate implicit parameters the way it propagate typeclass
requirements. For example I would like the following function to have
(inferred) type

-- printConfig :: (?config :: Config) => IO ()
printConfig = print (?config :: Config)

Instead GHC will complain about unbound implicit parameter. Similar problem
from GHCi session:

Prelude> let f = print (?conf :: Int)
<interactive>:11:16:
    Unbound implicit parameter (?conf::Int)
      arising from a use of implicit parameter `?conf'
    In the first argument of `print', namely `(?conf :: Int)'
    In the expression: print (?conf :: Int)
     In an equation for `f': f = print (?conf :: Int)

For reason I don't fully understand this is fixed by disabling monomorphic
restriction. The documentation mentions the problem but in a different
context:
http://www.haskell.org/ghc/docs/latest/html/users_guide/other-type-extensions.html#idp49108928

*TL;DR*: A nice solution to configuration problem is to use implicit
parameters and type synonym for IO monad extended with implicit
configuration parameters. It requires Rank2Types for defining the synonym
and NoMonomorphismRestriction for lightweight use.


Best regards,
Krzysztof Skrzętnicki


[1] I only realised this after starting the writing of this email. The
implicit parameters solution is given at least in [2]. Somehow I didn't
came across it before.
[2] "Global Variables in Haskell
(2004)"<http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.23.145&rep=rep1&type=ps>
by
John Hughes
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20130510/acec806a/attachment.htm>


More information about the Haskell-Cafe mailing list