For those that attended my last evening presentation about F# at Ronua Roadshow in Timisoara (but not only), here is the demo I’ve shown, and one that I planned to show but didn’t due to lack of time. The purpose of these demos was to shown simple Windows Forms applications written in F#.

Mandelbrot Fractal
A Mandelbrot set is a set of points in the complex plane, whose boundary forms a fractal. The fractal, known as Mandelbrot fractal, is obtain by associating a color with each point in the complex plane (or rather a subset of it). The color is chosen based on the result of computing the value of the complex quadratic polynomial Z(n+1) = Z(n)^2 + c for a number of iterations (100, 200, etc.). You can read more about it on Wikipedia.

The program that I shown exhibits traits of both functional (for computing the fractal) and object oriented (for displaying the fractal) paradigms. It is a variation of the program available here, for which I kept the functional part (computing the Mandelbrot set is not very fast, I must warn you), but redone the user interface part. You can use the mouse to drag the fractal and the wheel to zoom in and out.

You can download it from here.

Game of Life
I blogged about this two years ago, when F# was still far from a final release. In the meantime, syntax has changed, classes have changed, so if you try to run that implementation of mine you’ll run into some errors. I have updated the code to run correctly with Visual Studio 2010.

You can download it from here.

, , , Hits for this post: 12641 .

In this post I want to show how you can implement common list operations: union, intersection, difference and concatenation.

Concatenation is the simplest of them all, because type List already has a function call append that does everything for you.

let concat left right =
    List.append left right

The union of two lists is a list containing all the distinct elements from the two original lists. We can implement this operation by concatenating the two lists firsts, and the filtering the distinct elements.

let union left right =
    List.append left right |> Seq.distinct |> List.ofSeq

The intersection of two lists is a list containing all the elements of the first list that also appear in the second list. We can implement this by interating through the elements of the first list and checking whether the element appears in the second list. To do this in the shortest possible time, with constant lookup time, we can use a HashSet collection. The result is an O(m+n) complexity instead of O(m*n) if you used brute force.

let intersection (left:list< 'a >) (right:list< 'a >) =
    let cache = HashSet< 'a >(right, HashIdentity.Structural)
    left |> List.filter (fun n -> cache.Contains n)

The difference of two lists is a list containing all the elements from the first list that are not part of the second list. The implementation of difference is very similar to the implementation of the intersection. All that differs is the lambda used for the filtering.

let difference (left:list< 'a >) (right:list< 'a >) =
    let cache = HashSet< 'a >(right, HashIdentity.Structural)
    left |> List.filter (fun n -> not (cache.Contains n))

Let’s see all these put to a use:

let main() =
    let c = concat [4;3;2;1] [2;3;5]
    printfn "%A" c

    let u = union [4;3;2;1] [2;3;5]
    printfn "%A" u

    let i = intersection [4;3;2;2;1] [2;3;5]
    printfn "%A" i

    let d = difference [4;3;2;1] [2;3;5]
    printfn "%A" d

main()

This program yields the following output:

[4; 3; 2; 1; 2; 3; 5]
[4; 3; 2; 1; 5]
[3; 2; 2]
[4; 1]

Notice that these operations work with unsorted lists. You don’t have to sort the lists first to apply them.

In order to use the HashSet, you need to add a reference to the FSharp.PowerPack.dll assembly. This sample was build with F# 1.9.7.8 for Visual Studio 2008.

UPDATE: You can read about similar implementations but using operators on this post by Jason Kikel. He also deals with repetitions, regular expression binding operator and null coalescing binding operator.

, Hits for this post: 10606 .

The Game of Life is a cellular automaton devised by the John Horton Conway in 1970. It is the best-known example of a cellular automaton. It consists of a collection of cells which, based on a few mathematical rules, can live, die or multiply. Depending on the initial conditions, the cells form various patterns throughout the course of the game.

Here you can learn more about the game:

I decided to implement this in F#. With all the code involving the user interface, it was nearly 300 lines of code. Pretty neat!

Using the game

The life’s arena can take several sizes:

  • Tiny: 15 x 10
  • Small: 30 x 20
  • Medium: 60 x 40
  • Large: 120 x 80
  • Huge: 150 x 100

The size can be changed from the Game > Size menu.

The following commands are available from the menu:

  • Reset (Ctrl + R): Resets the game, all cells die
  • Randomize (Ctrl + G): Randomly initialize alive cells
  • Start/Stop (Ctrl + B): Starts or stops continuos creation of new generations
  • Step (Ctrl + N): Creates a new generation of cells

In addition the followin commands are available from the File menu:

  • Save (Ctrl + S): saves game to a bitmap file called gameolife_.bmp; this file is created in the working folder
  • Save As… (Ctrl + Shift + S): saves the game to a file, giving you the possibility to chose the location and format (bmp, jpg, gif and png)

Note: The state of the game can be changed (killing cells, making others alive) simply by clicking with the mouse on the game panel.

Implementation in F#

Some comments on the implementation of the game. For more have a look at the code.

I defined two records, one called Cell and one called World. The cell reprezents a cell and has a flag called Alive (which is self explanatory), and World represents the ‘arena of life’, containing a matrix of Cells.

type Cell =
 { Alive : bool;}

type World =
 { Width : int;
   Height : int;
   Cells: Cell[,];}

Various arena sizes are defined in a descriminated union and the mapping between that and values for width and height are done in this function:

type GameSize =
   | Tiny
   | Small
   | Medium
   | Large
   | Huge

let sizeMapping (size:GameSize) =
   match size with
   | Tiny -> (15,10)
   | Small -> (30, 20)
   | Medium -> (60, 40)
   | Large -> (120, 80)
   | Huge -> (150, 100)

A next generation of cells is computed based on the rules of the game. For each cell the number of alived neighbors is computed and then the state of the cell is changes (if necessary).

let nextGeneration (world:World) =
   let alive = {new Cell with Alive = true}
   let dead = {new Cell with Alive = false}
   let newcells = Array2.create world.Width world.Height dead
   for i = 0 to world.Width - 1 do
      for j = 0 to world.Height - 1 do
         let ncount = neighbors world j i
         match world.Cells.(i,j).Alive with
         | true -> if ncount = 2 || ncount = 3 then newcells.(i,j) <- alive
                   else newcells.(i,j) <- dead
         | _ -> if ncount = 3 then newcells.(i,j) <- alive
                  else newcells.(i,j) <- dead
      done
   done
   { world with Cells = newcells}

For computing the number of neighbors, I considered 9 cases:

  • cell is one of the four corners
  • cell is on one of the four edges (not a corner)
  • cell is anywhere else in the matrix

Depending on this position a list of neighbors is created and folded to compute the number of alive neighboring cells.

let sum (neighbors:Cell list) =
   neighbors |> List.fold_left (fun sum x -> if x.Alive then sum+1 else sum) 0

let neighbors (world:World) row col =
   match row, col with
   | _,_ when row = 0 && col = 0 -> sum [world.Cells.(1,0);world.Cells.(1,1);world.Cells.(0,1)]
   | _,_ when row = 0 && col = world.Width-1 -> sum [world.Cells.(world.Width-2,0);world.Cells.(world.Width-2,1);world.Cells.(world.Width-1,1)]
   | _,_ when row = world.Height-1 && col = 0 -> sum [world.Cells.(0, world.Height-2);world.Cells.(1, world.Height-2);world.Cells.(1,world.Height-1)]
   | _,_ when row = world.Height-1 && col = world.Width-1 -> sum [world.Cells.(world.Width-1, world.Height-2);world.Cells.(world.Width-2, world.Height-2);world.Cells.(world.Width-2,world.Height-1)]
   | _,_ when row = 0 && col > 0 && col < world.Width-1 -> sum [world.Cells.(col-1,0);world.Cells.(col-1,1);world.Cells.(col,1);world.Cells.(col+1,1);world.Cells.(col+1,0);]
   | _,_ when row = world.Height-1 && col > 0 && col < world.Width-1 -> sum [world.Cells.(col-1,row);world.Cells.(col-1,row-1);world.Cells.(col,row-1);world.Cells.(col+1,row-1);world.Cells.(col+1,row);]
   | _,_ when col = 0 && row > 0 && row < world.Height-1 -> sum [world.Cells.(0,row-1);world.Cells.(1,row-1);world.Cells.(1,row);world.Cells.(1,row+1);world.Cells.(0,row+1);]
   | _,_ when col = world.Width-1 && row > 0 && row < world.Height-1 -> sum [world.Cells.(col,row-1);world.Cells.(col-1,row-1);world.Cells.(col-1,row);world.Cells.(col-1,row+1);world.Cells.(col,row+1);]
   | _,_ -> sum [world.Cells.(col-1,row-1);world.Cells.(col,row-1);world.Cells.(col+1,row-1);world.Cells.(col+1,row);world.Cells.(col+1,row+1);world.Cells.(col,row+1);world.Cells.(col-1,row+1);world.Cells.(col-1,row);]

The rest is basically user interface code. But I made a parallel version of the game, when then computation of the next generation of cells is parallelized with the Parallel FX framework. Here is how the function looks.

let nextGeneration (world:World) =
   let alive = {new Cell with Alive = true}
   let dead = {new Cell with Alive = false}
   let newcells = Array2.create world.Width world.Height dead
   Parallel.For(0, world.Width, (fun i ->
      for j = 0 to world.Height - 1 do
         let ncount = neighbors world j i
         match world.Cells.(i,j).Alive with
         | true -> if ncount = 2 || ncount = 3 then newcells.(i,j) <- alive
                   else newcells.(i,j) <- dead
         | _ -> if ncount = 3 then newcells.(i,j) <- alive
                  else newcells.(i,j) <- dead
      done
   ))
   { world with Cells = newcells}

Source code

Here are the available downloads

, , , Hits for this post: 17381 .