
On May 15, 2018, at 16:29, Dennis Raddle
wrote: I'm not sure what happens if I apply a StateT to an existing State or StateT monad. Not sure how 'get' and 'put' would function, or if I would need to lift get and put to choose which state to access.
The immediate answer to this question is “yes”. If you had StateT on top of StateT, you could access the different pieces of state by lifting to the appropriate level. As Ryan points out, this is admittedly a bit awkward, since it doesn’t work with the classes from mtl (due to the functional dependency on MonadState). Still, it’s possible. Extensible effects can solve this a little more cleanly. You can easily handle an effect locally, and you can have multiple state effects with different types. For example, using freer-simple: import Control.Monad.Freer import Control.Monad.Freer.State f :: Member (State StdGen) eff => Eff eff Double f = do r <- <do something pseudorandomly> r2 <- runState @Int 3 (deeperFunc r) <...> deeperFunc :: Members '[State StdGen, State Int] eff => Double -> Eff eff Double deeperFunc = <...> This works just fine. To others suggesting the OP make the state a product: this seems unsatisfactory to me. It means you have to carry around the state for every local computation you might use, even long after it is no longer needed. If the state is truly local, there’s really no need to carry it around after its lifetime is, semantically, over. We invented local variables for a reason. (Such globalization of state also won’t work in general for things like recursive functions, for the same reasons that local variables cannot be properly implemented without a stack.) One small disclaimer: I am the maintainer of freer-simple, though I can’t really claim to be the author, since it’s a fork, and others did the vast majority of the work. Take my bias as you will. Alexis