Yesterday evening it occurred to me that two choices are possible when programming large monadic applications:
- A single common monadic state is shared among the modules while each module is written independently of this state and is given an accessor to access its local state in this global shared state. The application then defines the global states built from local states, and the accessors to go access these local states.
- Each module works on a state which presents primarily the local state of the module but which carries anonymously the global state. One way to do this is to "zipperize" the global state and walk over it with a "focus" (see . "Functional Pearl: The Zipper").
- The single global state and use of accessor per module is easier to implement but implies that the top level application design has visibility into all modules and that their assembly is not overly complex.
- Local module specific states with anonymous "left over global state" is more powerful and allows a finer anonymization through a module hierarchy. It is also more functionally pure. Nevertheless it has the shortcoming that as each module is working "relative" to its local state, and much functional glue must be included for each cross module call. My experience was that it is pretty tricky to to get all these conversions right because they are all relative. Although in practice the application most likely has a reference global state type and therefore this style of design revert to using code to convert from and to each local module state and global state (just like the accessor).