export type Success<V> = {
value: V;
kind: "success";
};
export type Failure<E> = {
error: E;
kind: "failure";
};
export type Result<V, E> = Success<V> | Failure<E>;
export function succeed<V>(value: V): Success<V> {
return {
value,
kind: "success",
};
}
export function fail<E>(error: E): Failure<E> {
return {
error,
kind: "failure",
};
}
export function invertResults<V, E>(
...results: (Success<V> | Failure<E>)[]
): Promise<Success<V[]> | Failure<E>> {
return fold(async (acc: Result<V[], E>, result: Result<V, E>) =>
await chainResult(async (arr: V[]) =>
await mapResult(appendTo(arr))(result)
)(
acc,
)
)(succeed([]))(results);
}
export function chainResult<V, E, N>(
f: (value: V) => Result<N, E> | Promise<Result<N, E>>,
) {
return async <F>(
$result: Result<V, F>,
): Promise<Result<N, E>> => {
const result = await $result;
switch (result.kind) {
case "success":
return await f(result.value) as any;
case "failure":
return result as any;
default:
throwUnsupportedKind(result);
}
};
}
const success = succeed("first");
const failure = fail(new Error("Oops"));
const result = await invertResults(success, failure);
console.log(result);
let r = await chainResult((values: string[]) => {
const newValues = [...values, "fourth"];
return newValues.length > 2 ? succeed(newValues) : succeed(newValues);
})(result);
console.log(r);
r = {};