Created
July 22, 2019 00:30
-
-
Save Nymphium/47a168ece64ec69a6829d469769dc890 to your computer and use it in GitHub Desktop.
algebraic effects using stricter generator (is too hard or impossible).
This file contains hidden or 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
| interface Get { | |
| readonly _tag: 'Get'; | |
| readonly _ans: number; | |
| } | |
| interface Put { | |
| readonly _tag: 'Put'; | |
| readonly _ans: void; | |
| value: number; | |
| } | |
| interface Log { | |
| readonly _tag: 'Log'; | |
| readonly _ans: void; | |
| value: string; | |
| } | |
| type Effects = Get | Put | Log; | |
| type Answers = ({ [A in keyof Effects]: Effects[A] })['_ans']; | |
| const genEff = <E, A>(obj: { [A in keyof E]: E[A] }) => ({ | |
| ...obj, | |
| _ans: (undefined as any) as A, | |
| }); | |
| const get: Get = genEff({ _tag: 'Get' }); | |
| const put = (value: number): Put => genEff({ _tag: 'Put', value }); | |
| const log = (value: string): Log => genEff({ _tag: 'Log', value }); | |
| function run<R>(init: number, th: () => Iterator<Effects, R, Answers>) { | |
| const iter = th(); | |
| let val = init; | |
| function go(res: IteratorResult<Effects, R>): R { | |
| if (res.done) { | |
| return res.value; | |
| } | |
| const v = res.value; | |
| switch (v._tag) { | |
| case 'Get': | |
| return go(iter.next(val)); | |
| case 'Put': | |
| val = v.value; | |
| return go(iter.next()); | |
| case 'Log': | |
| console.log(`>>>${v.value}<<<`); | |
| return go(iter.next()); | |
| } | |
| } | |
| return go(iter.next()); | |
| } | |
| run(0, function*() { | |
| // TS inferres return values from `yield` as anything `any`, | |
| // or when explicitly typing this generator as `Iterator<Effects, void, Answers>`, always `number | void` | |
| const x: number = yield get; | |
| yield log(x.toString()); | |
| yield put(x + 10); | |
| const y: number = yield get; | |
| yield log(y.toString()); | |
| }); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment