A simple finite state machine in Erlang and F#

Con­sid­er­ing a very sim­ple finite state machine (FSM) such as a code lock which requires you to enter a 4-dig­it numer­ic code and upon which will open the lock for a brief few sec­onds.

imageSuch a FSM have two states: Locked and Open.

Every time a key is entered it checks the sequence of dig­its inputted so far and if the sequence does not match the secret code then it stays in the Locked state.

If the input sequence match­es the length of the secret code then the user is judged to have entered an incor­rect sequence and the input sequence is reset.

If, on the oth­er hand, the user has entered the cor­rect code then the FSM will change to the Open state for a num­ber of sec­onds before revert­ing back to the Locked state.

This post is intend­ed to show you how you can imple­ment this FSM eas­i­ly using F#’s agent and Erlang OTP’s gen_fsm behav­iour.

 

 

 

F#

First, let’s define the dif­fer­ent states that our FSM can be in:

image

and then the mes­sages that our agent can receive:

image

The actu­al FSM imple­men­ta­tion looks like this:

This imple­men­ta­tion is pret­ty straight for­ward, I’ve used a sim­i­lar tech­nique to the one Tomas Pet­ricek used in his Block­ingQueueAgent imple­men­ta­tion and rep­re­sent­ed the dif­fer­ent states using recur­sive func­tions.

One caveat with this FSM is the need to revert back to the Locked state after being in the Open state for a cer­tain amount of time. For sim­plic­i­ty sake, I’ve sim­ply spec­i­fied a time­out (3 sec­onds) when wait­ing for mes­sages in the Open state and use the Time­ou­tEx­cep­tion as cue to go back to the Locked state. The obvi­ous down­side to my imple­men­ta­tion here is that if a Get­State mes­sage is received it will reset the timer!

You can fix this eas­i­ly enough in a num­ber of ways, includ­ing using a muta­ble instance vari­able to keep track of the cur­rent state and let the async lamb­das mod­i­fy it dur­ing state changes and tran­si­tions, then the Get­State() method would no longer need to trou­ble the agent to find out what the cur­rent state is.

 

Erlang

Erlang’s OTP frame­work pro­vide a gen_fsm behav­iour which you can use to imple­ment a FSM, which will take care of most of the plumb­ing and orches­tra­tion for you leav­ing you free to focus on the impor­tant things – han­dling the dif­fer­ent ‘events’ that can be trig­gered dur­ing dif­fer­ent states.

This Erlang imple­men­ta­tion might look much big­ger than its F# coun­ter­part but keep in mind that I’ve includ­ed plen­ty of com­ments here and not been as con­ser­v­a­tive with write spaces as I was with the F# code. All and all, both ver­sions require rough­ly the same num­ber of LOC, the main dif­fer­ence being the lack of plumb­ing in the Erlang ver­sion, which if I have to be hon­est, can be con­fus­ing if you don’t have a decent under­stand­ing of how the gen_fsm behav­iour works!

You can down­load and play around with the full source code (with cor­re­spond­ing tests for each imple­men­ta­tion) from Github here. Enjoy!