Using the StateT
monad transformer, I can create the type StateT s [] a
, which is isomorphic to s -> [(a, s)]
. Now I would prefer to use the STT
monad transformer instead, as I would like to have multiple mutable variables of different types, and would like to be able to instantiate them at will, depending on the results of earlier computations.
However, the linked documentation for STT
mentions explicitly:
This monad transformer should not be used with monads that can contain multiple answers, like the list monad. The reason is that the state token will be duplicated across the different answers and this causes Bad Things to happen (such as loss of referential transparency). Safe monads include the monads State, Reader, Writer, Maybe and combinations of their corresponding monad transformers.
So what are my options?
To be entirely clear:
- What I'm after, is non-determinism. I want to be able to fork my computation, giving each branch its own copy of the entire state.
- I don't mind much for parallelism, as performance is not my greatest concern.
- What I'm not after is concurrency: different branches of computation should not share mutable variables; rather, they should all work on their own copy of the original mutable variable.
EDIT:
(Edit to edit: the following counterexample is invalid, as ListT
should not be applied to the non-commutative monads ST
and State
.)
I've come to realize that an STT
monad transformer that behaves along the lines of StateT
is inherently unsafe. With it, we could build a type STT sloc (ListT (ST sglob)) a
. Here, sglob
is the name of the global state, while sloc
is the name of the local state.*
Now we can use the global state to exchange local state references between threads, thus potentially obtaining references to uninitialized variables.
*For comparison, the corresponding StateT
construction is StateT sloc (ListT (State sglob)) a
, which is isomorphic to sloc -> sglob -> ([(a, sloc)], sglob)
.