Question 1: Are monad stacks "transparent" -- that is, can one use a layer in the middle of a monad stack without thinking about other layers?
In learning about how to stack multiple monads (or more literally, how to stack monad transformers on top of a monad), I was expecting that in order to reach into the middle of the stack, one would have to stay aware of the order in which the stack was created, and unwrap outer transformers to get there.
That appears to be false. For instance, the program UglyStack.hs in
Chapter 18 (Monad Transformers) of Real World Haskell includes a function called "constrainedCount" that, in a ReaderT (StateT IO) stack, calls "ask", "get" and some IO functions as if no layer of the stack interferes with any of the others.
Is that true in general? That is, if I build on top of a monad M a stack of monad transformers T1 T2 T3 ... TN M, and each of the Tn have different functions associated with them, call I call those functions without even remembering the order in which the transformers were stacked? Does the order of the stack constrain the programmer in how they chain execution functions like runReader, but not otherwise?
Question 2: Does a monad's scope extend maximally upward through the call stack?
All the programs I have seen that use monads keep them at the top scope: The "main" function will use them, and perhaps functions it calls, but if one descends low enough into the call stack, one escapes from the monad context into pure functional code. Can one ever escape a monad in the reverse direction?
Stated differently: Monadic code can call pure code. Can pure code ever call monadic code?