import { identity } from "../../../Function"; import * as Sy from "../../../Sync"; import { both, then } from "./constructors"; import { empty } from "./empty"; import type { Cause } from "./model"; /* * ------------------------------------------- * Monad Cause * ------------------------------------------- */ export const chainSafe_ = (fa: Cause, f: (e: E) => Cause): Sy.Sync> => Sy.gen(function* (_) { switch (fa._tag) { case "Empty": return empty; case "Fail": return f(fa.value); case "Die": return fa; case "Interrupt": return fa; case "Then": return then(yield* _(chainSafe_(fa.left, f)), yield* _(chainSafe_(fa.right, f))); case "Both": return both(yield* _(chainSafe_(fa.left, f)), yield* _(chainSafe_(fa.right, f))); } }); /** * ```haskell * chain_ :: Monad m => (m a, (a -> m b)) -> m b * ``` * * Composes computations in sequence, using the return value of one computation as input for the next * * @category Monad * @since 1.0.0 */ export const chain_ = (fa: Cause, f: (e: E) => Cause): Cause => { return Sy.runIO(chainSafe_(fa, f)); }; /** * ```haskell * chain :: Monad m => (a -> m b) -> m a -> m b * ``` * * Composes computations in sequence, using the return value of one computation as input for the next * * @category Monad * @since 1.0.0 */ export const chain = (f: (e: E) => Cause) => (fa: Cause) => chain_(fa, f); /** * ```haskell * flatten :: Monad m => m m a -> m a * ``` * * Removes one level of nesting from a nested `Cuase` * * @category Monad * @since 1.0.0 */ export const flatten = (ffa: Cause>) => chain_(ffa, identity);