
Joachim Breitner wrote:
...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... 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.
I'm struggling to understand what problem you are trying to solve. We're talking about passing a single parameter - a record type, or a shallow tree, or something else extremely simple. In the monadic case, we're adding a single Reader component to the transformer stack. I'm currently working on a large system, consisting of hundreds of modules and tens of thousands of lines of code. There are hundreds of configuration parameters, coming from configuration files, modules of compiled-in constants, and the UI. Different subsets of the parameters are needed in various subsystems. Doing that in Haskell has been an absolute pleasure, much much simpler than in any other language I've used for a system of this size. (I'll spare you the horror of what I had to do once for a large system written in C++...) I barely have to think about it - the types reflect the relationships between the configuration and the various parts of the system, and Haskell's type system does the rest automatically, guaranteeing correctness. What else could you ask for?
Also, I expect that the explicit passing causes a small performance penalty.
We're been processing gigabytes of data - doing non-trivial operations including a kind of image recognition and more - so far with nearly imperceptible delay. The bottleneck, if there is one, will certainly not be the configuration subsystem. I know some Haskell libraries use constructor hiding, or even the data-default package which uses generics, to add more flexibility to the configuration system. But I don't feel the need even for those. I certainly wouldn't dream of dragging in type-level olegery, unsafe coercion, implicit parameters and other experimental extensions. Simplicity just works. What case are you thinking about? A system several orders of magnitude more complex? Some special case that creates difficulty? Thanks, Yitz