Skip to content

Instantly share code, notes, and snippets.

@semmel
Created November 18, 2023 19:23
Show Gist options
  • Save semmel/96958c61d2c80254e7c63531643eed3e to your computer and use it in GitHub Desktop.
Save semmel/96958c61d2c80254e7c63531643eed3e to your computer and use it in GitHub Desktop.
State Machine with Sum/Union Type Libraries for JavaScript
Lib Creation TypeCheck cata Serialisable
periodo,paldepind/union-type Type - 1
JAForbes/sum-type
fantasyland/daggy tagged, taggedSum 2

FSM

action :: State → Args → State

Args = Any

     ┌──────────▶┏━━━━━━━━━━━━━━━━┓
     │           ┃   in-between   ┃
 forward  ┌──────┃     [Work]     ┃────┐
     │    │      ┃                ┃    │
     │    │      ┗━━━━━━━━━━━━━━━━┛complete
     │ reset                           │
     │    │                            │
     │    ▼                            ▼
     ┏━━━━━━━━━┓               ┏━━━━━━━━━━━━━━━┓
     ┃         ┃               ┃     final     ┃
     ┃  begin  ┃◀───reset──────┃   [Number]    ┃
     ┃         ┃               ┃               ┃
     ┗━━━━━━━━━┛               ┗━━━━━━━━━━━━━━━┛

paldepind/union-type

const 
	Work = Type({Work: {abort: Function, result: Promise}}),
	State = Type({
		Begin: [],
		InBetween: [Work],
		Final: [Number]
	}),
	// :: State → State
	reset = State.case({
		Begin:() => State.Begin,
		Final: x => State.Begin,
		InBetween: ({abort}) => {
			abort();
			return State.Begin;
		},
	}),
	// :: State → Number → State
	forward = State.caseOn({
		Begin: x => {
			let timer;
			const promise = new Promise(resolve => { 
				timer = setTimeout(
					resolve,
					1000,
					x * x
				);
			});
			return State.InBetween(Work.WorkOf({
				abort: () => { clearTimer(timer); }),
				result: promise
			}));
		},
		Final: (z, x) => State.Final(z),
		InBetween: (abort, x) => State.InBetween(abort),
	}),
	// :: State → Number → State
	complete = State.caseOn({
		InBetween: (abort, z) => {
			abort();
			return State.Final(z);
		},
	});
	
// application 
// forward → complete → reset
const
	state = State.Begin,
	computationState = forward(state, 9)
	[workResult] = computationState;
// :: Promise State	
workResult
.then(z => complete(computationState, z))
.then(reset);

Footnotes

  1. https://github.com/paldepind/union-type/issues/21

  2. https://github.com/Lian1230/serialize-daggy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment