import * as E from "../Either"; import { modify, succeed } from "./constructors"; import { fold_, foldM_ } from "./fold"; import { map_ } from "./functor"; import type { XPure } from "./model"; import { chain_ } from "./monad"; /** * ```haskell * catchAll_ :: (XPure s1 s2 r e a, (e -> XPure s1 s3 r1 e1 b)) -> * XPure s1 s3 (r & r1) e1 (a | b) * ``` * * Recovers from all errors. * * @category Combinators * @since 1.0.0 */ export const catchAll_ = ( fa: XPure, onFailure: (e: E) => XPure ) => foldM_(fa, onFailure, (a) => succeed(a)); /** * ```haskell * catchAll_ :: (e -> XPure s1 s3 r1 e1 b) -> XPure s1 s2 r e a -> * XPure s1 s3 (r & r1) e1 (a | b) * ``` * * Recovers from all errors. * * @category Combinators * @since 1.0.0 */ export const catchAll = (onFailure: (e: E) => XPure) => ( fa: XPure ) => catchAll_(fa, onFailure); /** * ```haskell * update :: (s1 -> s2) -> XPure s1 s2 _ _ () * ``` * * Constructs a computation from the specified update function. * * @category Combinators * @since 1.0.0 */ export const update = (f: (s: S1) => S2): XPure => modify((s) => [f(s), undefined]); /** * ```haskell * contramapInput_ :: (XPure s1 s2 r e a, (s0 -> s1)) -> XPure s0 s2 r e a * ``` * * Transforms the initial state of this computation` with the specified * function. * * @category Combinators * @since 1.0.0 */ export const contramapInput_ = (fa: XPure, f: (s: S0) => S1) => chain_(update(f), () => fa); /** * ```haskell * contramapInput :: (s0 -> s1) -> XPure s1 s2 r e a -> XPure s0 s2 r e a * ``` * * Transforms the initial state of this computation` with the specified * function. * * @category Combinators * @since 1.0.0 */ export const contramapInput = (f: (s: S0) => S1) => (fa: XPure) => contramapInput_(fa, f); /** * ```haskell * either :: XPure s1 s2 r e a -> XPure s1 (s1 | s2) r _ (Either e a) * ``` * * Returns a computation whose failure and success have been lifted into an * `Either`. The resulting computation cannot fail, because the failure case * has been exposed as part of the `Either` success case. * * @category Combinators * @since 1.0.0 */ export const either = (fa: XPure): XPure> => fold_(fa, E.left, E.right); export const orElse_ = ( fa: XPure, onFailure: (e: E) => XPure ): XPure => foldM_(fa, onFailure, succeed); export const orElse = (onFailure: (e: E) => XPure) => ( fa: XPure ): XPure => orElse_(fa, onFailure); /** * ```haskell * orElseEither_ :: (XPure s1 s2 r e a, XPure s3 s4 r1 e1 a1) -> * XPure (s1 & s3) (s2 | s4) (r & r1) e1 (Either a a1) * ``` * * Executes this computation and returns its value, if it succeeds, but * otherwise executes the specified computation. * * @category Combinators * @since 1.0.0 */ export const orElseEither_ = ( fa: XPure, that: XPure ): XPure> => foldM_( fa, () => map_(that, E.right), (a) => succeed(E.left(a)) ); /** * ```haskell * orElseEither :: XPure s3 s4 r1 e1 a1 -> XPure s1 s2 r e a -> * XPure (s1 & s3) (s2 | s4) (r & r1) e1 (Either a a1) * ``` * * Executes this computation and returns its value, if it succeeds, but * otherwise executes the specified computation. * * @category Combinators * @since 1.0.0 */ export const orElseEither = (that: XPure) => ( fa: XPure ) => orElseEither_(fa, that);