I found this tiny two lines in the erlang state machine docs that I've kept around for years because it's such a precise definition of how they need to work in practice:
"State(S) x Event(E) -> Actions (A), State(S')"
"If we are in state S and the event E occurs, we should perform the actions A and make a transition to the state S'."
The fn needs to yield both the new state and a collection of side effects of that transition that need to be handled somehow. You'll need side effects no matter what so might as well formally describe them in the SM, then handle them outside of it in a way that fits the language/framework/runtime. I think this is basically exactly what elm does and how a couple of the redux extensions work too.
"State(S) x Event(E) -> Actions (A), State(S')"
"If we are in state S and the event E occurs, we should perform the actions A and make a transition to the state S'."
The fn needs to yield both the new state and a collection of side effects of that transition that need to be handled somehow. You'll need side effects no matter what so might as well formally describe them in the SM, then handle them outside of it in a way that fits the language/framework/runtime. I think this is basically exactly what elm does and how a couple of the redux extensions work too.