Lib | Creation | TypeCheck | cata | Serialisable |
---|---|---|---|---|
periodo,paldepind/union-type | Type |
✓ | - 1 | |
JAForbes/sum-type | ✓ | |||
fantasyland/daggy | tagged , taggedSum |
✓ | ✓ 2 |
action :: State → Args → State
Args = Any
┌──────────▶┏━━━━━━━━━━━━━━━━┓
│ ┃ in-between ┃
forward ┌──────┃ [Work] ┃────┐
│ │ ┃ ┃ │
│ │ ┗━━━━━━━━━━━━━━━━┛complete
│ reset │
│ │ │
│ ▼ ▼
┏━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━┓
┃ ┃ ┃ final ┃
┃ begin ┃◀───reset──────┃ [Number] ┃
┃ ┃ ┃ ┃
┗━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━┛
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);