Dynamic recursive API in F#
[<AutoOpen>] | |
module StateMachine = | |
type State = | |
| StateA | |
| StateB | |
| StateC | |
| StateD | |
| End | |
type Transition = | |
{ TargetState: State | |
Continuation: unit -> TransitionResult } | |
and TransitionResult = | |
{ CurrentState: State | |
Transitions: Transition list } | |
type Actor = | |
{ DecideTransition: TransitionResult -> Transition } | |
let transitions = function | |
| StateA -> [StateB; StateC; StateD] | |
| StateB -> [StateA] | |
| StateC -> [StateB; End] | |
| StateD -> [StateC; StateD] | |
| End -> [] | |
let rec transitionsOf state = | |
[for targetState in state |> transitions do | |
yield { TargetState = targetState | |
Continuation = fun () -> | |
{ CurrentState = targetState | |
Transitions = transitionsOf targetState }}] | |
let start = | |
{ CurrentState = StateA | |
Transitions = transitionsOf StateA } | |
[<AutoOpen>] | |
module Actor = | |
let random = System.Random () | |
let decideTransition result = | |
let randomIndex = random.Next(result.Transitions.Length) | |
result.Transitions |> List.item randomIndex | |
let actor = { DecideTransition = decideTransition } | |
module Engine = | |
let runWith actor = | |
let rec loop result = | |
if result.CurrentState = End then | |
() | |
else | |
let nextTransition = actor.DecideTransition result | |
printfn "Next: %A" nextTransition.TargetState | |
nextTransition.Continuation () |> loop | |
start |> loop | |
Engine.runWith actor |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment