I'm trying to understand the practical difference between a FRP graph and a State Machine with lenses- specifically for something like a game loop where the entire state is re-drawn every tick.
Using javascript syntax, the following implementations would both essentially work:
Option 1: State Machine w/ Lenses
//Using Sanctuary and partial.lenses (or Ramda) primitives
//Each update takes the state, modifies it with a lens, and returns it
let state = initialValues;
eventSource.addEventListener(update, () => {
state = S.pipe([
updateCharacter,
updateBackground,
])
(state) //the first call has the initial settings
render(state);
});
Option 2: FRP
//Using Sodium primitives
//It's possible this isn't the best way to structure it, feel free to advise
cCharacter = sUpdate.accum(initialCharacter, updateCharacter)
cBackground = sUpdate.accum(initialBackground, updateBackground)
cState = cCharacter.lift(cBackground, mergeGameObjects)
cState.listen(render)
I see that Option 1
allows any update to get or set data anywhere in the game state, however all the cells/behaviors in Option 2
could be adjusted to be of type GameState
and then the same thing applies. If this were the case, then I'm really confused about the difference since that would then just boil down to:
cGameState = sUpdate
.accum(initialGameState, S.pipe(...updates))
.listen(render)
And then they're really very equivalent...
Another way to achieve that goal would be to store all the Cells in some global reference, and then any other cell could sample them for reading. New updates could be propagated for communicating. That solution also feels quite similar to Option 1 at the end of the day.
Is there a way to structure the FRP graph in such a way that it offers clear advantages over the event-driven state machine, in this scenario?