Tuesday, 20 September 2016

State machines

Someone on the internet recently asserted that F# is “atrocious” for implementing state machines compared to C#. I just Googled C# state machine and found this. I translated the example into the following F# code:

type State = Inactive | Active | Paused | Exited
type Transition = Begin | End | Pause | Resume | Exit
 
let move = function
  | Inactive, Begin -> Active
  | (Active | Paused), End -> Inactive
  | Active, Pause -> Paused
  | Paused, Resume -> Active
  | Inactive, Exit -> Exited
  | state, transition -> failwithf "Invalid transition: %A -> %A" state transition

Here is their original C# for comparison:

using System;
using System.Collections.Generic;
 
namespace Juliet
{
    public enum ProcessState
    {
        Inactive,
        Active,
        Paused,
        Terminated
    }
 
    public enum Command
    {
        Begin,
        End,
        Pause,
        Resume,
        Exit
    }
 
    public class Process
    {
        class StateTransition
        {
            readonly ProcessState CurrentState;
            readonly Command Command;
 
            public StateTransition(ProcessState currentState, Command command)
            {
                CurrentState = currentState;
                Command = command;
            }
 
            public override int GetHashCode()
            {
                return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();
            }
 
            public override bool Equals(object obj)
            {
                StateTransition other = obj as StateTransition;
                return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;
            }
        }
 
        Dictionary<StateTransition, ProcessState> transitions;
        public ProcessState CurrentState { get; private set; }
 
        public Process()
        {
            CurrentState = ProcessState.Inactive;
            transitions = new Dictionary<StateTransition, ProcessState>
            {
                { new StateTransition(ProcessState.Inactive, Command.Exit), ProcessState.Terminated },
                { new StateTransition(ProcessState.Inactive, Command.Begin), ProcessState.Active },
                { new StateTransition(ProcessState.Active, Command.End), ProcessState.Inactive },
                { new StateTransition(ProcessState.Active, Command.Pause), ProcessState.Paused },
                { new StateTransition(ProcessState.Paused, Command.End), ProcessState.Inactive },
                { new StateTransition(ProcessState.Paused, Command.Resume), ProcessState.Active }
            };
        }
 
        public ProcessState GetNext(Command command)
        {
            StateTransition transition = new StateTransition(CurrentState, command);
            ProcessState nextState;
            if (!transitions.TryGetValue(transition, out nextState))
                throw new Exception("Invalid transition: " + CurrentState + " -> " + command);
            return nextState;
        }
 
        public ProcessState MoveNext(Command command)
        {
            CurrentState = GetNext(command);
            return CurrentState;
        }
    }
 
 
    public class Program
    {
        static void Main(string[] args)
        {
            Process p = new Process();
            Console.WriteLine("Current State = " + p.CurrentState);
            Console.WriteLine("Command.Begin: Current State = " + p.MoveNext(Command.Begin));
            Console.WriteLine("Command.Pause: Current State = " + p.MoveNext(Command.Pause));
            Console.WriteLine("Command.End: Current State = " + p.MoveNext(Command.End));
            Console.WriteLine("Command.Exit: Current State = " + p.MoveNext(Command.Exit));
            Console.ReadLine();
        }
    }
}

 

 

Monday, 19 September 2016

Relating PDFs

The F# Journal just published an article about processing documents:
"This article tackles the challenge of computing the relationships between a set of PDF files using the commonality of words within them. The iTextSharp library is used to extract the text in PDF documents and the StemmersNet library is then used to convert the words into word stems. A simple numerical method is used to compute the commonality between the word frequencies in different documents and the resulting relationships are visualized using GraphViz..."

To read this article and more, subscribe to The F# Journal today!