import type { Alt, AltFn_ } from "@principia/prelude"; import { chainF, pureF, tuple } from "@principia/prelude"; import type { Applicative, BothFn_ } from "@principia/prelude/Applicative"; import type { Fallible } from "@principia/prelude/Fallible"; import * as HKT from "@principia/prelude/HKT"; import type { Monad } from "@principia/prelude/Monad"; import type { Semigroup } from "@principia/prelude/Semigroup"; import type { Erase } from "@principia/prelude/Utils"; import * as E from "../Either"; import { pipe } from "../Function"; export function getApplicativeValidationF( F: Monad & Fallible & Applicative ): (S: Semigroup) => Applicative, HKT.Auto> & HKT.Fix<"E", E>>; export function getApplicativeValidationF( F: Monad> & Fallible> & Applicative> ): (S: Semigroup) => Applicative, HKT.Fix<"E", E>> { return (S: Semigroup) => { const both_: BothFn_, HKT.Fix<"E", E>> = (fa, fb) => pipe( F.recover(fa), F.both(F.recover(fb)), F.map(([ea, eb]) => E.fold_( ea, (e) => E.fold_( eb, (e1) => F.fail(S.combine_(e, e1)), () => F.fail(e) ), (a) => E.fold_(eb, F.fail, (b) => pureF(F)(tuple(a, b))) ) ), F.flatten ); return HKT.instance, HKT.Fix<"E", E>>>({ unit: F.unit, map: F.map, map_: F.map_, both_, both: (fb) => (fa) => both_(fa, fb) }); }; } export function getAltValidationF( F: Monad & Fallible & Alt ): (S: Semigroup) => Alt, HKT.Auto> & HKT.Fix<"E", E>>; export function getAltValidationF( F: Monad> & Fallible> & Alt> ): (S: Semigroup) => Alt, HKT.Fix<"E", E>> { return (S: Semigroup) => { const pure = pureF(F); const chain = chainF(F); const alt_: AltFn_, HKT.Fix<"E", E>> = (fa, that) => pipe( F.recover(fa), chain( E.fold( (e) => pipe( F.recover(that()), chain( E.fold( (e1) => F.fail(S.combine_(e, e1)), (a) => pure(a) ) ) ), (a) => pure(a) ) ) ); return HKT.instance, HKT.Fix<"E", E>>>({ map: F.map, map_: F.map_, alt_, alt: (that) => (fa) => alt_(fa, that) }); }; }