When developing a Finite State Machine, it is often necessary to apply multiple transitions in tandem. To accomplish this in most Redux work flows requires at best, implementing multiple action handlers in separate reducers; or at worse, the need to duplicate logic for similar action handlers, sometime across multiple files. However when using a State ADT, we can easily combine these independent transitions by simply chain
-ing multiple discrete transitions into one transaction. We demonstrate this interface by transitioning two portions of related state with one transaction.
Instructor: [00:00] We start with these two attributes in our state -- left to keep track of the moves a player has left, and moves, which tracks the number of moves a player has taken. We also have these two state transitions -- decLeft, that decrements the moves left, and incMoves, that increments the moves taken, which we've defined here in our answer model.
[00:20] Back in our index file, we can log our call to decLeft, passing it unit as its input. We see we get back a state instance. To run our state, we call exitWith, passing our initial state, which decrements our left attribute.
[00:35] To marry these transactions into one transactions, we chain in incMoves to apply it. Now, both transitions are applied to our initial state. We can now create a single transaction that can be exported from our answer model, which will be a function that we'll call applyMove.
[00:53] ApplyMove is defined as a function that goes from a unit to state, app state of unit. To implement, we take in our unit, and mimic what we did before, calling decLeft with unit, and then chaining in incMoves.
[01:10] After a quick save, we can jump back into index and replace the two functions endports with one applyMove. Now, we just get rid of the old crusties downstairs, and replace with the hot, new applyMove, call it with unit.
[01:25] We now have one sole transaction that can easily be chained not only once, but as many times as our wee hearts desire, without fear of stepping outside of our defined range, due to our previously implemented clamping function.
[01:39] After we reset our index, let's jump back into our answer model and take a look at this transaction. If we look at the siggy for incMoves, we see that it's a Kleisli arrow that maps unit to unit. Upstairs, we see that decLeft is also the same Kleisli, which means we can do Kleisli composition on these functions.
[01:57] We can replace this fluent style with composeK, which will give us a new Kleisli that calls incMoves after decLeft, matching what we had before. Well, once we axe this bit, of course, and give it a save. We see they are equivalent.
[02:11] We should also verify that chaining still works as expected. Chaining one still works, and so does chaining many. As we want these to always change together, we could remove the exports and only provide applyMove.
[02:25] That way, we keep our model concerns in the model, and not have them leak out to other parts of our app.