import { NoSuchElementException } from "../GlobalExceptions"; import type { Option } from "../Option"; import type { _E } from "../support/utils"; import { isOption, isSync } from "../support/utils"; import type { Sync } from "../Sync"; import { runEither, runEitherEnv_ } from "../XPure/run"; import { fromOption_, right } from "./constructors"; import type { Either } from "./model"; import { chain_ } from "./monad"; export class GenEither { readonly _E!: () => E; readonly _A!: () => A; constructor(readonly E: Either) {} *[Symbol.iterator](): Generator, A, any> { return yield this; } } const adapter = (_: any, __?: any) => { if (isSync(_)) { return __ ? new GenEither(runEitherEnv_(_, __)) : new GenEither(runEither(_)); } if (isOption(_)) { return new GenEither(fromOption_(_, () => (__ ? __() : new NoSuchElementException("Either.gen")))); } return new GenEither(_); }; export function gen(): >( f: (i: { (_: Sync): GenEither; (_: Sync, r: R): GenEither; (_: Option, onNone: () => E): GenEither; (_: Option): GenEither; (_: Either): GenEither; }) => Generator ) => Either<_E, A0>; export function gen(): >( f: (i: { (_: Sync): GenEither; (_: Sync, r: R): GenEither; (_: Option, onNone: () => E): GenEither; (_: Option): GenEither; (_: Either): GenEither; }) => Generator ) => Either<_E, A0>; export function gen, A>( f: (i: { (_: Sync): GenEither; (_: Sync, r: R): GenEither; (_: Option, onNone: () => E): GenEither; (_: Option): GenEither; (_: Either): GenEither; }) => Generator ): Either<_E, A>; export function gen(...args: any[]): any { function gen_, AEff>( f: (i: any) => Generator ): Either<_E, AEff> { const iterator = f(adapter as any); const state = iterator.next(); function run(state: IteratorYieldResult | IteratorReturnResult): Either { if (state.done) { return right(state.value); } return chain_(state.value.E, (val) => { const next = iterator.next(val); return run(next); }); } return run(state); } if (args.length === 0) { return (f: any) => gen_(f); } return gen_(args[0]); }