import * as C from "./Cause"; import { failure, succeed } from "./constructors"; import { map_ } from "./functor"; import type { Exit } from "./model"; import { chain_ } from "./monad"; /* * ------------------------------------------- * Apply Exit * ------------------------------------------- */ export const ap_ = (fab: Exit B>, fa: Exit): Exit => chain_(fab, (f) => map_(fa, (a) => f(a))); export const ap = (fa: Exit) => (fab: Exit B>): Exit => ap_(fab, fa); export const apFirst_ = (fa: Exit, fb: Exit): Exit => mapBothCause_(fa, fb, (a, _) => a, C.then); export const apFirst = (fb: Exit) => (fa: Exit): Exit => apFirst_(fa, fb); export const apSecond_ = (fa: Exit, fb: Exit): Exit => mapBothCause_(fa, fb, (_, b) => b, C.then); export const apSecond = (fb: Exit) => (fa: Exit): Exit => apSecond_(fa, fb); export const mapBothCause_ = ( fa: Exit, fb: Exit, f: (a: A, b: B) => C, g: (ea: C.Cause, eb: C.Cause) => C.Cause ): Exit => { switch (fa._tag) { case "Failure": { switch (fb._tag) { case "Success": { return fa; } case "Failure": { return failure(g(fa.cause, fb.cause)); } } } // eslint-disable-next-line no-fallthrough case "Success": { switch (fb._tag) { case "Success": { return succeed(f(fa.value, fb.value)); } case "Failure": { return fb; } } } } }; export const mapBothCause = ( fb: Exit, f: (a: A, b: B) => C, g: (ea: C.Cause, eb: C.Cause) => C.Cause ) => (fa: Exit): Exit => mapBothCause_(fa, fb, f, g); export const mapBoth_ = (fa: Exit, fb: Exit, f: (a: A, b: B) => C): Exit => mapBothCause_(fa, fb, f, C.then); export const mapBoth = (fb: Exit, f: (a: A, b: B) => C) => (fa: Exit): Exit => mapBoth_(fa, fb, f); export const apParFirst_ = (fa: Exit, fb: Exit): Exit => mapBothCause_(fa, fb, (a, _) => a, C.both); export const apParFirst = (fb: Exit) => (fa: Exit): Exit => apParFirst_(fa, fb); export const apParSecond_ = (fa: Exit, fb: Exit): Exit => mapBothCause_(fa, fb, (_, b) => b, C.both); export const apParSecond = (fb: Exit) => (fa: Exit): Exit => apParSecond_(fa, fb);