-
-
Save bdaniel7/fe4514cc714810a6201099b585e5c82a to your computer and use it in GitHub Desktop.
State Machine Construction Kit in F#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module StateMachine = | |
type State<'Event> = | |
| Next of ('Event -> State<'Event>) | |
| Stop | |
let feed state event = | |
match state with | |
| Stop -> failwith "Terminal state reached" | |
| Next handler -> event |> handler | |
type StateMachine<'event>(initial: State<'event>) = | |
let mutable current = initial | |
member this.Fire event = current <- feed current event | |
member this.IsStopped | |
with get () = match current with | Stop -> true | _ -> false | |
let createMachine initial = StateMachine(initial) | |
let createAgent initial = | |
MailboxProcessor.Start (fun inbox -> | |
let rec loop state = async { | |
let! event = inbox.Receive () | |
match event |> feed state with | |
| Stop -> () | |
| Next _ as next -> return! loop next | |
} | |
loop initial | |
) | |
module DoorMachine = | |
open StateMachine | |
type Event = | Open | Close | Lock | Unlock | |
let configureDoor sound = | |
let rec opened event = | |
match event with | |
| Close -> sound "bang"; Next (closed false) | |
| Lock -> sound "clack"; Next opened | |
| _ -> Next opened | |
and closed locked event = | |
match event with | |
| Open when locked -> sound "dumdum"; Next (closed locked) | |
| Open -> sound "squeak"; Next opened | |
| Lock -> sound "click"; Next (closed true) | |
| Unlock -> sound "clack"; Next (closed false) | |
| _ -> Next (closed locked) | |
Next (closed false) | |
let test sound = | |
let agent = sound |> configureDoor |> StateMachine.createAgent | |
agent.Post Lock | |
agent.Post Unlock | |
agent.Post Open | |
agent.Post Close | |
[<EntryPoint>] | |
let main argv = | |
DoorMachine.test (printfn "%s") | |
System.Console.ReadLine() |> ignore | |
0 // return an integer exit code |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment