import { pipe } from "../../Function"; import { some } from "../../Option"; import * as Ex from "../Exit"; import type { Cause } from "../Exit/Cause"; import type { Exit } from "../Exit/model"; import * as T from "../Task/_core"; import type { FiberId } from "./FiberId"; import type { Fiber, RuntimeFiber, SyntheticFiber } from "./model"; import { InterruptStatus } from "./model"; /** * ```haskell * _fold :: ( * Fiber e a, * ((Runtime e a) -> b), * ((Synthetic e a) -> b) * ) -> b * ``` * * Folds over the runtime or synthetic fiber. */ export const _fold = ( fiber: Fiber, onRuntime: (_: RuntimeFiber) => B, onSynthetic: (_: SyntheticFiber) => B ): B => pipe(fiber, fold(onRuntime, onSynthetic)); /** * ```haskell * fold :: (((Runtime e a) -> b), ((Synthetic e a) -> b)) -> Fiber e a -> b * ``` * * Folds over the runtime or synthetic fiber. */ export const fold = (onRuntime: (_: RuntimeFiber) => B, onSynthetic: (_: SyntheticFiber) => B) => ( fiber: Fiber ) => { switch (fiber._tag) { case "RuntimeFiber": { return onRuntime(fiber); } case "SyntheticFiber": { return onSynthetic(fiber); } } }; export const done = (exit: Exit): SyntheticFiber => ({ _tag: "SyntheticFiber", await: T.pure(exit), getRef: (ref) => T.pure(ref.initial), inheritRefs: T.unit(), interruptAs: () => T.pure(exit), poll: T.pure(some(exit)) }); export const succeed = (a: A): SyntheticFiber => done(Ex.succeed(a)); export const fail = (e: E): SyntheticFiber => done(Ex.fail(e)); export const halt = (cause: Cause) => done(Ex.failure(cause)); export const interruptAs = (id: FiberId) => done(Ex.interrupt(id)); export const interruptible = new InterruptStatus(true); export const uninterruptible = new InterruptStatus(false); export const interruptStatus = (b: boolean) => (b ? interruptible : uninterruptible);