Skip to content

A simple "stateless" finite-state machine library for .NET.


Notifications You must be signed in to change notification settings


Repository files navigation


A simple "stateless" finite-state machine library for .NET, written in F#.

Now available through NuGet!

Maintainer wanted

I don't typically work in .NET anymore; if anyone is interested in maintaining this project please contact me. @BillSorensen on Twitter.

Quick start

C# example

(See also the Samples folder)

// Example does not include error handling.

// using TrueWill.Fsm;

// Could load text from database, configuration, etc.
string transitionTableText =
    # Turnstile

    Locked   | coin | Unlocked
    Unlocked | coin | Unlocked
    Unlocked | pass | Locked";

var transitions = TransitionTableParser.Parse(transitionTableText);

var fsm = new StateMachine(transitions);

string currentState = fsm.InitialState;
Console.WriteLine("Initial state: " + currentState);

IEnumerable<string> availableEvents =

// Typically a user would make a selection.
string selectedEvent = availableEvents.First();

Console.WriteLine("Selected event: " + selectedEvent);

currentState = fsm.GetNewState(currentState, selectedEvent);

Console.WriteLine("New state: " + currentState);
// Repeat.

// fsm.States is also available.

F# example

// Example does not include error handling.

open TrueWill.Fsm

// Could load text from database, configuration, etc.
let transitionTableText =
    # Turnstile

    Locked   | coin | Unlocked
    Unlocked | coin | Unlocked
    Unlocked | pass | Locked

let transitions = Parser.parse transitionTableText

Validator.validate transitions

let currentState = Fsm.getInitialState transitions

printfn "Initial state: %s" currentState

// Partially apply these functions to store the transitions.
let getAvailableEvents = Fsm.getAvailableEvents transitions
let getNewState = Fsm.getNewState transitions

let availableEvents = getAvailableEvents currentState

// Typically a user would make a selection.
let selectedEvent = Seq.head availableEvents

printfn "Selected event: %s" selectedEvent

let newState = getNewState currentState selectedEvent

printfn "New state: %s" newState
// Repeat.

// Fsm.getStates is also available.


I was reading Agile Principles, Patterns, and Practices in C# by Robert C. Martin and Micah Martin, and fixated on Uncle Bob's State Machine Compiler (SMC). That reads a state transition table and generates C++ code.

I wanted to write a functional library that would do the same - read a textual DSL (domain-specific language) that defined a state transition table, and create a Semantic Model (Fowler).

I borrowed parsing techniques from Fowler's book (see above link).

This project also is helping me to learn F#. :)

Keith Dahlby provided help and encouragement.


Visual Studio 2012, targeting .NET 4.0 under Windows. It doesn't need 4.5 features, and I don't want to restrict its use to Windows 7+.

The assembly should be CLS-compliant, and it should be natural to call from C# (to give it the widest possible audience). There are unit tests in both F# and C# to insure this.

I would prefer to avoid adding dependencies on other libraries to the core library. (The tests depend on, FsUnit, etc.)

Thread Safety

All public types, methods, and functions should be thread safe.

I make no warranties.

If you find anything that is not thread safe, please open an issue.

State Transition Tables



One per line.
The first state of the first line is the initial state.

Anything following a '#' is ignored (a comment). Blank lines are ignored.

Whitespace surrounding states and events is ignored, so you can line up delimiters if you prefer.

States and events are composed of letters, digits, and underscores, and may contain embedded spaces. They must start and end with a letter, digit, or underscore.

States may not differ only by case; neither may events.

By default, FSM will raise an exception if an event is received that isn't defined on the current state. If you want to ignore the event instead, define a transition for the event where the current state and the new state are the same.




This is a solution in search of a problem. That's not a good thing. Dogfooding will almost certainly improve the design.

The idea is that a web service would reference FSM. The state transition tables could be provided by callers, loaded from a data store, stored in configuration - it doesn't matter. The callers would be responsible for storing their current state, and would pass it to the service.

Say I have a simple workflow, defined in a state machine.

  1. Ask the service for the initial state
  2. Ask the service for the available events
  3. Display the available events to the user
  4. User makes selection
  5. Ask the service for the new state, given the old state and the event
  6. Repeat from #2

You'd want to combine this with a data store and security.

(See the Samples folder for an example of this.)

FSM machines are designed to be deserialized from text. This constraint makes it difficult to support actions or guards (behavior/code). While there are options (such as Roslyn), these would provide limited benefit without associating data with the state machine and supporting calling custom assemblies. It's a slippery slope that can lead to reinventing Windows Workflow Foundation. What's more, there are other libraries that already provide some of these features as internal DSLs (fluent interfaces, etc.).

I do not want to make FSM complicated. If you want to fork the project and add the ability to run custom code on transitions, feel free, but I probably won't accept that pull request. In particular, I want the DSL to be self-contained, without requiring binary references. (I'm willing to listen to ideas, though!)


The validate function may evaluate the transitions sequence multiple times. Since the parse function and the StateMachine constructor both do toList internally, this is not an issue in typical use.

Release notes

  • 1.0.0 Initial stable release
  • 2.0.0 Breaking change for F# clients - moved transitions to first parameter on several methods for partial application. This allows F# clients to store the transitions along with the function. Moved validation from parser to validator. F# clients will want to call the validator manually; C# clients will not be affected, except that some exceptions formerly thrown by the parser will now be thrown by the constructor of the state machine.
  • 2.0.1 Supports embedded spaces in states and events; improved validation.

To Do

  • Improved documentation (XML comments, exception thrown, etc.)
  • Psake build script?

Finally, I'm very new to Git and GitHub, so please be patient with me.



A simple "stateless" finite-state machine library for .NET.








No packages published