Instead of explicitly threading a state through your code, I would suggest that monad transformers is a pretty standard way to handle this. You wrap whatever state you want in a
Control.Monad.State monad and inside the body of your functions, you have access to that state via
modify functions of said monad. At the top level of the program, you
runState, pass the initial state in and get the final state back. Or
evalState if you don’t care about the final state.
Or, if you feel really adventurous, extensible effects are all the rage these days. I find this blog post to be very helpful. And in PureScript land, I have been using
purescript-run for the past several weeks. It is a very capable library.
With it, the side effects are modeled as pure data and you can interpret them effectfully in the real program or purely in the tests. And they are composable. I ported the example in that blog post to
purescript-run and you may want to check it out here. It has pretty much everything: how to define your own effects, how to use them in the client code and how to interpret them effectfully and purely.
Of course, you can simply use predefined
Run.State analogous to
I’m not advocating one way or the other. The monad transformers and algebraic effects are both very capable. Your choice