【问题标题】:Chain fp-ts TaskEither with Either in right将 fp-ts TaskEither 与右侧的 Either 连接起来
【发布时间】:2020-08-16 23:10:29
【问题描述】:

我有 2 个嵌套请求流,其中可能是 3 个不同的结果:

  1. 其中一个请求返回错误
  2. 用户不是匿名的,返回个人资料
  3. 用户是匿名的,返回 false

两个请求都可能引发错误,因此实现了TaskEither

const isAuth = ():TE.TaskEither<Error, E.Either<true, false>>  
   => TE.tryCatch(() => Promise(...), E.toError)
const getProfile = ():TE.TaskEither<Error, Profile>  
   => TE.tryCatch(() => Promise(...), E.toError)

第一个请求返回用户授权的布尔状态。第二个请求加载用户配置文件如果用户被授权

作为回报,我想获得下一个签名,Error 或 Either with Anonymous/Profile:

E.Either<Error, E.Either<false, Profile>>

我试着这样做:

pipe(
    isAuth()
    TE.chain(item => pipe(
      TE.fromEither(item),
      TE.mapLeft(() => Error('Anonimous')),
      TE.chain(getProfile)
    ))
  )

但作为回报,我得到了E.Either&lt;Error, Profile&gt;,这不方便,因为我必须手动从Error 中提取Anonymous 状态。

如何解决这个问题?

【问题讨论】:

  • E.Either&lt;true, false&gt; 没有多大意义,因为类型是Either&lt;boolean, boolean&gt;,所以无论如何您都无法获得Either&lt;boolean, TypeOfProfile&gt;。您丢失Either 层的原因是您作为合成的第一步执行的从EitherTask 的自然转换TE.fromEither(item)
  • 糟糕,刚刚注意到您的初始 Either 具有文字作为类型参数,因此是 Either&lt;true, false&gt;。不过问题还是一样。
  • @bob 是的,我使用自然转换使其工作,因为我找不到编写正确管道的方法,这将返回 E.Either&lt;false, Profile&gt;Option&lt;Profile&gt;,这不是重点,在右侧部分,并将第二个请求中的错误放在左侧部分 - 这是我的问题。

标签: javascript typescript functional-programming fp-ts


【解决方案1】:

不知道你是否过度简化了实际代码,但 E.Either&lt;true, false&gt;boolean 同构,所以让我们坚持更简单的事情。

declare const isAuth: () => TE.TaskEither<Error, boolean>;
declare const getProfile: () => TE.TaskEither<Error, Profile>;

然后你根据它是否被授权添加条件分支并包装getProfile的结果:

pipe(
  isAuth(),
  TE.chain(authed => authed 
    ? pipe(getProfile(), TE.map(E.right)) // wrap the returned value of `getProfile` in `Either` inside the `TaskEither`
    : TE.right(E.left(false))
  )
)

此表达式的类型为TaskEither&lt;Error, Either&lt;false, Profile&gt;&gt;。您可能需要添加一些类型注释才能正确地进行类型检查,我自己没有运行代码。

编辑:

您可能需要将 lambda 提取为命名函数以获得正确的类型,如下所示:

const tryGetProfile: (authed: boolean) => TE.TaskEither<Error, E.Either<false, Profile>> = authed
  ? pipe(getProfile(), TE.map(E.right))
  : TE.right(E.left(false));

const result: TE.TaskEither<Error, E.Either<false, Profile>> = pipe(
  isAuth(),
  TE.chain(tryGetProfile)
);

【讨论】:

  • 它有效,谢谢!但是如何获得正确的类型呢?我试过这个A.sequenceT(TE.taskEitherSeq)(result),但作为回报,我得到了数组类型TE.TaskEither&lt;Error, [E.Either&lt;false, Profile&gt;]&gt;,这不是我要找的:(你知道怎么解决吗?
  • @IvanTarasov 不太确定,可能有错误或拼写错误。我用一些打字建议更新了答案,你可以从那里开始工作,它应该会给你一些合理的编译器错误。
猜你喜欢
  • 2021-07-17
  • 1970-01-01
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 2022-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多