UNPKG

@typed/effects

Version:

Generator-powered Effect management

44 lines (35 loc) 1.19 kB
import { Env, Resume } from '@typed/env' import { Capabilities, Effect, IteratorResultOf, Return } from '../Effect' import { Failure } from '../failures/Failure' export const runEffect = <A extends Effect<any, any>>( effect: A, ): Env<Capabilities<A>, Return<A>> => (c: Capabilities<A>) => { const generator = effect[Symbol.iterator]() as A return runEffectGenerator(generator, generator.next(), c) } const nextResult = <A extends Effect<any, any>>(value: any, generator: A): IteratorResultOf<A> => { if (value instanceof Failure) { return value.unpack( (e) => generator.throw(e), (a) => generator.return(a), ) } return generator.next(value) } const runEffectGenerator = <A extends Effect<any, any>>( generator: A, result: IteratorResultOf<A>, capabilities: Capabilities<A>, ): Resume<Return<A>> => { while (!result.done) { const resume = result.value(capabilities) if (resume.type === 'lazy') { return Resume.chain( (value) => runEffectGenerator(generator, nextResult(value, generator), capabilities), resume, ) } result = nextResult(resume.value, generator) } return Resume.of(result.value) }