I often need to make a core function that\'s used in many places somehow configurable - i.e., it may use either algorithm A or algorithm B depending on a command-line switch; o
You can use the Reader
monad to get the same effect as passing a parameter around everywhere. Applicative style can make the overhead fairly low compared to normal functional code, but it can still be pretty awkward. This is the most common solution to the configuration problem, but I don't find it terribly satisfactory; indeed, passing the parameter around explicitly is often less ugly.
An alternative is the reflection package, which lets you pass around common configuration data like this around through typeclass contexts, which means none of your code has to change to plumb the additional value, only the types. Basically, you add a new type parameter to every input/result type in your program, so that everything operating within the context of a certain configuration has the type that corresponds to that configuration in its type. That type stops you accidentally mixing values using multiple configurations, and gives you access to the associated configuration at runtime.
This avoids the overhead of writing everything in applicative style, while still being safe, and allowing you to mix multiple configurations. It's a lot simpler than it sounds; here's an example.
(Full discloure: I've worked on the reflection package.)