0

我有这样的管道

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);

我想在asyncFn. 问题是当我有Right输入时,我可以再分叉它。

当我登录时,pipeResult我看到:

Right (tryP(() => Promise.resolve(x + ' str2')))

我怎样才能做到这一点?

4

1 回答 1

5

Either a b并且Future a b都能够表达失败/成功。在处理异步计算时,通常使用Future a b而不是Future a (Either b c). 更简单、更扁平的类型需要更少的映射:S.map (f)而不是S.map (S.map (f)). 另一个优点是错误值总是在同一个地方,而Future a (Either b c)两者都a代表b失败的计算。

但是,我们可能已经有一个返回 any 的验证函数。例如:

//    validateEmail :: String -> Either String String
const validateEmail = s =>
  s.includes ('@') ? S.Right (S.trim (s)) : S.Left ('Invalid email address');

如果我们有一个futtype 的值,Future String String我们如何验证电子邮件地址fut可能包含的内容?首先要尝试的是S.map

S.map (validateEmail) (fut) :: Future String (Either String String)

避免这种嵌套会很好。为此,我们首先需要定义一个函数 from Either a bto Future a b

//    eitherToFuture :: Either a b -> Future a b
const eitherToFuture = S.either (Future.reject) (Future.resolve);

我们现在可以将一个返回要么返回的函数转换为返回返回的函数:

S.compose (eitherToFuture) (validateEmail) :: String -> Future String String

让我们重新审视一下我们的用法S.map

S.map (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String (Future String String)

我们仍然有嵌套,但现在内部和外部类型都是Future String _. 这意味着我们可以替换S.mapS.chain以避免引入嵌套:

S.chain (S.compose (eitherToFuture) (validateEmail)) (fut) :: Future String String
于 2019-11-05T10:33:18.130 回答