In Using the State Monad: Generating Random Values, we showed how to use the State monad to give ourselves access to random numbers in a way that is easy to use.
A drawback of the code we developed is that it’s leaky: Users know that they’re executing inside the State monad. This means that they can inspect and modify the state of the random number generator just as easily as we, the authors, can.
Human nature dictates that if we leave our internal workings exposed, someone will surely come along and monkey with them. For a sufficiently small program, this may be fine, but in a larger software project, when one consumer of a library modifies its internals in a way that other consumers are not prepared for, the resulting bugs can be among the most difficult to track down. These bugs occur at a level where we’re unlikely to question our basic assumptions about a library until long after we’ve exhausted all other avenues of inquiry.
Even worse, once we leave our implementation exposed for a while, and some well-intentioned person inevitably bypasses our APIs and uses the implementation directly, we have a nasty quandary if we need to fix a bug or make an enhancement. Either we can modify our internals and break code that depends on them; or we’re stuck with our existing internals and must try to find some other way to make the change that we need.
How can we revise our random number monad so that the fact that we’re using the State monad is hidden? We ...