The basic idea is that you write code like this:
main = do parameters <- readConfigurationParametersSomehow forever $ do myData <- readUserInput putStrLn $ bigComplicatedFunction myData parameters bigComplicatedFunction d params = someFunction params xyz where x = function1 params d y = function2 params xd z = function3 params y
You read the parameters in the "main" function with an IO action, and then pass these parameters to your work function (s) as an additional argument.
The problem with this style is that the parameter block must be passed to every small function that needs to access it. This is a nuisance. You will find that some functions at ten levels in the call tree now need some runtime parameter, and you must add this runtime parameter as an argument to all functions between them. This is known as tramp data .
The solution monad is to insert a runtime parameter into Reader Monad and make all your functions monoidal. This eliminates the explicit tramp data parameter, but replaces it with a monadic type, and under the hood, this monad actually performs data tracing for you.
The real world solves this problem with a global variable. In Haskell, you can sort the same as this:
parameters = unsafePerformIO readConfigurationParametersSomehow
The first time you use “parameters”, “readConfigurationParametersSomehow” is executed, and from then on it behaves as a constant value, at least as long as your program is running. This is one of the few righteous uses for unsafePerformIO.
However, if you need such a solution, you really need to think about your design. Most likely, you are not thinking well enough about generalizing your functions below; if some previously pure function suddenly needs a run-time parameter, then look at the reason and see if you can use higher-order functions in some way. For example:
- Pass the function created using the parameter, not the parameter itself.
- Let the worker function below return the function as a result, which receives which should be composed with a parametric function at a higher level.
- Restore the call stack so that the basic operations are performed at a lower level primitives at the bottom, which are composed depending on the parameter at the top.
In any case, it will be involved
Paul johnson
source share