I have a pipe like this
const asyncFn = (x) => {
return Future.tryP(() => Promise.resolve(x + ' str2'))
};
const pipeResult = S.pipe([
x => S.Right(x + " str1"), // some validation function
S.map(asyncFn),
])("X");
pipeResult.fork(console.error, console.log);
I want to do some async operation in asyncFn
.
The problem is when I have Right
as input I can fork it anymore.
When I log the pipeResult
I see this:
Right (tryP(() => Promise.resolve(x + ' str2')))
How can I do this?
Either a b
and Future a b
are both capable of expressing failure/success. When working with asynchronous computations it is usually better to use Future a b
rather than Future a (Either b c)
. The simpler, flatter type requires less mapping: S.map (f)
rather than S.map (S.map (f))
. Another advantage is that the error value is always in the same place, whereas with Future a (Either b c)
both a
and b
represent failed computations.
We may, though, already have a validation function that returns an either. For example:
// validateEmail :: String -> Either String String
const validateEmail = s =>
s.includes ('@') ? S.Right (S.trim (s)) : S.Left ('Invalid email address');
If we have a value fut
of type Future String String
, how do we validate the email address fut
may contain? The first thing to try is always S.map
:
S.map (validateEmail) (fut) :: Future String (Either String String)
It would be nice to avoid this nesting. In order to do so, we first need to define a function from Either a b
to Future a b
:
// eitherToFuture :: Either a b -> Future a b
const eitherToFuture = S.either (Future.reject) (Future.resolve);
We can now transform an either-returning function into a future-returning function:
S.compose (eitherToFuture) (validateEmail) :: String -> Future String String
Let's revisit our use of S.map
:
S.map (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String (Future String String)
We still have nesting, but now the inner and outer types are both Future String _
. This means we can replace S.map
with S.chain
to avoid introducing nesting:
S.chain (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String String