import { List } from "immutable"; import { BasicFun, BasicFun2, Fun } from "../../../fun/state"; import { Value } from "../../../value/state"; import { Errors } from "../errors/state"; import { unit, Unit, Updater, Option, Sum } from "../../../../main"; export type ValueOrErrors = ( | (Value & { kind: "value" }) | (Errors & { kind: "errors" }) ) & { Map: ( this: ValueOrErrors, f: BasicFun, ) => ValueOrErrors; MapErrors: ( this: ValueOrErrors, f: BasicFun, List>, ) => ValueOrErrors; Flatten: ( this: ValueOrErrors, e>, ) => ValueOrErrors; Then: ( this: ValueOrErrors, k: BasicFun>, ) => ValueOrErrors; }; const operations = { Map: function ( this: ValueOrErrors, f: BasicFun, ): ValueOrErrors { if (this.kind == "errors") { return this; } return ValueOrErrors.Default.return(f(this.value)); }, MapErrors: function ( this: ValueOrErrors, f: BasicFun, List>, ): ValueOrErrors { if (this.kind == "errors") { return ValueOrErrors.Default.throw(f(this.errors)); } return this; }, Flatten: function ( this: ValueOrErrors, e>, ): ValueOrErrors { if (this.kind == "errors") { return this; } else if (this.value.kind == "errors") { return ValueOrErrors.Default.throw(this.value.errors); } else { return this.value; } }, Then: function ( this: ValueOrErrors, k: BasicFun>, ): ValueOrErrors { return this.Map(k).Flatten(); }, }; export const ValueOrErrors = { Default: { return: (_: v): ValueOrErrors => ({ ...Value.Default(_), kind: "value", ...operations, }), throwOne: (_: e): ValueOrErrors => ({ errors: List([_]), kind: "errors", ...operations, }), throw: (_: List): ValueOrErrors => ({ errors: _, kind: "errors", ...operations, }), ofOption: ( v: Option, e: BasicFun, ): ValueOrErrors => v.kind == "l" ? ValueOrErrors.Default.throwOne(e(unit)) : ValueOrErrors.Default.return(v.value), }, Operations: { Return: (_: v): ValueOrErrors => ValueOrErrors.Default.return(_), Throw: (_: List): ValueOrErrors => ValueOrErrors.Default.throw(_), Map: ( f: BasicFun, ): Fun, ValueOrErrors> => Fun((_) => _.kind == "errors" ? _ : ValueOrErrors.Default.return(f(_.value)), ), MapErrors: ( f: BasicFun, List>, ): BasicFun, ValueOrErrors> => Fun((_) => _.kind == "errors" ? ValueOrErrors.Default.throw(f(_.errors)) : _, ), Flatten: (): Fun< ValueOrErrors, e>, ValueOrErrors > => Fun((_) => _.kind == "errors" ? _ : _.value.kind == "errors" ? ValueOrErrors.Default.throw(_.value.errors) : _.value, ), Then: ( k: BasicFun>, ): Fun, ValueOrErrors> => Fun((_: ValueOrErrors) => ValueOrErrors.Operations.Flatten()( ValueOrErrors.Operations.Map, e>(k)(_), ), ), Catch: (_: ValueOrErrors): ValueOrErrors>, e> => _.kind == "errors" ? ValueOrErrors.Default.return(Sum.Default.right(_.errors)) : ValueOrErrors.Default.return(Sum.Default.left(_.value)), Fold: ( l: BasicFun, r: BasicFun, c>, ): Fun, c> => Fun((_) => (_.kind == "value" ? l(_.value) : r(_.errors))), All: (_: List>): ValueOrErrors, e> => _.size == 0 ? ValueOrErrors.Default.return(List()) : ValueOrErrors.Operations.Catch(_.first()!).Then((res_p) => res_p.kind == "l" ? ValueOrErrors.Operations.All(_.slice(1).toList()).Then( (values) => ValueOrErrors.Default.return( List().push(res_p.value).concat(values), ), ) : ValueOrErrors.Default.throw(res_p.value), ), }, };