Skip to content

Instantly share code, notes, and snippets.

@awto
Last active July 11, 2019 07:17
Show Gist options
  • Save awto/d7b87297a1c3efc26301306ffafcbb99 to your computer and use it in GitHub Desktop.
Save awto/d7b87297a1c3efc26301306ffafcbb99 to your computer and use it in GitHub Desktop.
Single syntax layer effects using exceptions - React Hooks style
class Token { constructor(v) { this.value = v, this.results = [] } }
let context
const run = (of, chain) => (fun) => (...args) => {
const trace = []
const ctx = {trace}
return walk()
function walk(bound) {
const savedContext = context
ctx.pos = 0
try {
context = ctx
return of(fun(...args))
} catch(e) {
if (!(e instanceof Token))
throw e
const pos = ctx.pos
return chain(e.value,
(value) => {
trace.length = pos
trace.push(value)
ctx.pos = pos + 1
return walk(value)
})
} finally {
context = savedContext
}
}
}
function M(v) {
if (context.pos < context.trace.length)
return context.trace[context.pos++]
throw new Token(v)
}
const state = run(v => s => [v, s],
(arg, fun) => s => {
const [nextArg, nextState] = arg(s)
return fun(nextArg)(nextState)
})
function set(s) {
return M(_ => [s, s])
}
function get() {
return M(s => [s, s])
}
function incr() {
return set(get() + 1)
}
function incrX2() {
return incr() + incr()
}
console.log(state(incrX2)()(0))
const nonDet = run(function*(v) { yield v },
function* (arg, fun) {
for(const i of arg)
yield* fun(i)
})
function amb(...vals) {
return M(vals)
}
function* test() {
yield 1
yield 2
}
function* test2() {
yield 10
yield 20
}
function permut() {
return amb(M(test2()), M(test()))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment