Somewhere in 2011 I started a game with the working title “Three is a Crowd” (TIC for short). The game is a version of Reversi, but now for three players. The main goal of creating this game was: learning and using new technologies, keeping my tech-knowledge up-to-date. In that respect, it reflects my personal interests.

TIC was originally written in C#. At some moment I was interested in a better way to write the AI, and that started me on learning F#. Quickly I came to the conclusion, that it would be best to rewrite the TIC-webservice in F#. This webservice handles the full game, while uncoupled GUI’s may connect, to display the game’s current state, or to invoke a player’s move.

When rewriting my game to F#, I stumbled upon the first challenge that immutability gives: cyclic data reference. The game-board consists of hexagons, and the game rules require that you traverse a line from a starting tile, in a specific direction, while checking some condition. So concerning the data, we cannot do without each tile being aware of its neighbours, if available. As all hexagon tiles are connected to each other, this dataset contains cyclic references. We can choose a start-tile, move via a neighbour-link to another tile, repeat this a few times, and return to the tile we started. It is cyclic because this scenario is possible.

To reduce this problem into its (al)most simplest form:

(a cyclic reference from A to B would be even simpler, but it just happens to be the case that I like triangles)

So how would we model this in F# code?

Let’s get deeper into the problem first.

Copy/paste the following into an F# script file and run it in the F# Interactive:

The old value of “a” is discarded, and a new value for “a” is created. However in memory, there is still a reference to the old value of “a”, which is the deepest nested object in the result above: (“A”, Empty). In other words, we still have a “linked list” instead of a cycle.

If we did the same thing in C#, and “a” was a mutable variable instead of an immutable value, then we would have been finished now. We can also make it mutable in F#, however we would need this mutability only at initialization. After initialization, we don’t want it mutable anymore. But if we make it mutable, it will be mutable forever and we then open the door for side-effects.

So if we go back to the problem that immutability gives us, what is the problem exactly? It is a chicken-egg problem:

When we first create “A”, we cannot link to “C”, because it does not exist;

After creating “C”, we cannot change the reference in “A”, because its immutable;

Now let’s make a bold statement. If we create “A”, we cannot link it to “C”, because it does not exist. However: we do know that we want to link to “C”, when we create “A”. We already have the idea in our head. The moment that the link was laid - when we got the idea - is in the past, we are just trying to realize it in the machine.

So if we see the creation of objects, and linking them together as separate concerns, then we have solved this problem. In the immutable world, you cannot link directly, if your data allows cyclic graphs. So linking becomes a step-in-between.

The value “links” can be created before, or after the data is created. If one of the elements needs to change, for example, the object with name “A” is renamed to “G”, then this change will only affect the List “data”. If we want to add element “K” to our data, then it involves operations on both “data” and “links”.

In this example we use an integer to identify a data object, which acts as a lookup key. Of course this scheme can be simplified, or enriched, according to your requirements.

Although the Hexagon board is a little more complex, in essence it is based upon the above principle.