monads
monads copied to clipboard
Wrap async/sync result in the library
Its super common for async/sync operations to throw an error, but i don't see a constructor to conveniently wrap the operation in the Result
. I propose a new constructor:
async function AsyncResultOf<T>(val: Promise<T>): Promise<Result<T, Error>> {
try {
return Ok(await val);
} catch(err) {
return Err(err);
}
}
This allows us to go from the throw/catch error handling to the monadic error handling patterns const result = await AsyncResultOf(fetch(...))
I will go further to suggest an even more general constructor that translates both async and non-async fallible operations:
async function ResultOf<T>(val: () => Promise<T>): Promise<Result<T, Error>> {
try {
return Ok(await val());
} catch(err) {
return Err(err);
}
}
This can of course be overloaded with the signature of AsyncResultOf
.
(PS im trying to whip up a PR but the test keeps saying "Timed out while running tests" on my machine)
i changed
results.ts
interestingly.
I think your proposal is interesting. Have you considered using TaskEither
from the fp-ts
library? It could be more suitable for more complex scenarios. Additionally, if we're planning to support this constructor, we should also consider adding a wrapper for regular functions. Your syntax seems fitting for this purpose:
function resultOf<T, E = unknown>(val: () => T): Result<T, E> {
try {
return Ok(val());
} catch(err) {
return Err(err);
}
}
// usage:
const result = resultOf(() => 10 / 0);
Also, I have modified the error type, as we cannot be certain that the thrown value is an error.
upd: I hadn't seen your PR https://github.com/sniptt-official/monads/pull/112 , when I sent the comment.
My bad, I should have linked this issue with my PR.
fp-ts
's TaskEither
is a good analog. However, Either
is a more generalized form of Result
as in Result
makes it explicit that you will either get the result or the error.
And from non-async functions i meant regular functions, yes.
Would be cool to see this implemented :)