Created
January 11, 2018 00:28
-
-
Save tonyhb/9c6a1bd44fb21170ac43413bd5993f1d to your computer and use it in GitHub Desktop.
fsm/dfa
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
/* result represents either a success or an error for an operation. It can hold | |
a resource of any type - ie. a user, treatment etc. */ | |
type result('resource) = | |
| Ok('resource) | |
| Error('resource, string); | |
/* Event represents a single event within our system */ | |
type event('data, 'resource) = { | |
/* The ID of the user authoring the event */ | |
author: string, | |
/* The string name of the event */ | |
name: string, | |
/* The input data to the event. For example, when submitting a TP form this will | |
be the TP data */ | |
data: 'data, | |
/* The resource that the event modifies. This may be a single type or a struct | |
containing many types for modification */ | |
resource: 'resource, | |
/* The apply function, which takes the event data and modifies the resource. This | |
returns the newly modified resource and a Result type representing whether the | |
event application was a success. */ | |
apply: ('data, 'resource) => result('resource) | |
}; | |
/** | |
Input data | |
========== | |
**/ | |
/* A super basic TP form */ | |
type tp = { | |
stages: int, | |
cadence: int | |
}; | |
/* A super basic type form */ | |
type onboarding = {concern: string}; | |
/** | |
System types (ie. models | |
============ | |
**/ | |
type status = | |
| Registered | |
| PreConsultation | |
| PostConsultation | |
| Consented | |
| InTreatment | |
| Dismissed | |
| Graduated; | |
type user = { | |
name: string, | |
status, | |
onboarding: option(onboarding) | |
}; | |
type refinement = { | |
number: int, | |
stages: int, | |
cadence: int | |
}; | |
type treatment = { | |
refinements: list(refinement), | |
startDate: option(float), | |
endDate: option(float) | |
}; | |
/** | |
Events | |
====== | |
These comprise our FSM/DFA | |
**/ | |
/* submitOnboarding generates a new event for submitting the onboarding form during | |
registration. | |
It accepts an author name (ie. their ID in a real system), the onboarding data | |
plus the user to modify | |
*/ | |
let submitOnboarding = (author, onboarding: onboarding, user: user) => { | |
author, | |
name: "submit_onboarding", | |
/* the input is an onboarding form */ | |
data: onboarding, | |
/* it modifies a user model */ | |
resource: user, | |
/* apply runs the modification */ | |
apply: (onboarding, user) => | |
/** Only allow the onboarding form to be submitted for certain user statuses **/ | |
( | |
switch user.status { | |
/* Update the "onboarding" property of the user */ | |
| Registered => Ok({...user, onboarding: Some(onboarding)}) | |
| PreConsultation => Ok({...user, onboarding: Some(onboarding)}) | |
| _ => Error(user, "User doesn't have a valid status to apply onboarding event") | |
} | |
) | |
}; | |
let submitTP = (author, tp: tp, tx: treatment) => { | |
author, | |
name: "submit_tp", | |
data: tp, | |
resource: tx, | |
apply: (tp, tx) => Error(tx, "TODO") | |
}; | |
/** | |
DEMOS | |
===== | |
**/ | |
/** The basic FSM applicator **/ | |
let apply = (event: event('a, 'b)) => event.apply(event.data, event.resource); | |
let result = | |
submitOnboarding( | |
"Kjeld", | |
{concern: "gaps"}, | |
{name: "tony", status: Registered, onboarding: None} | |
) | |
|> apply; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment