【发布时间】:2021-12-03 08:18:21
【问题描述】:
我在尝试使用 FP-TS 实现事物时经常遇到的一种模式是,当我的管道涉及将 TaskEither 的分支分支和合并在一起时。
合并似乎工作得很好,因为我可以使用 sequenceT 创建数组并将它们传递到函数中,然后使用所有这些值。
似乎不太好用的是更复杂的依赖图,其中一个函数需要较早的项目,然后需要该函数的输出以及第一个任务的原始结果。
基本上是这样的函数签名(这可能不是 100% 正确的类型,但大致了解一下):
function fetchDataA(): TaskEither<Error, TypeA> {
}
function fetchBBasedOnOutputOfA(a: TypeA): TaskEither<Error, TypeB> {
}
function fetchCBasedOnOutputOfAandB(a: TypeA, b: TypeB): TaskEither<Error, TypeC> {
}
因为在管道中,你可以很好地为前两个作曲
pipe(
fetchDataA(),
TE.map(fetchBBasedOnOutputOfA)
)
而且这个管道按预期返回 TaskEither
而要执行最后一个操作,我现在需要输入 TypeA 作为参数,但它不可用,因为它已传递给 B。
一种解决方案是让函数 B 同时输出 A 和 B,但这感觉不对,因为创建 B 的函数不应该知道某些其他函数也需要 A。
另一种方法是创建某种中间函数来存储 A 的值,但在我看来,这打破了使用 TaskEither 的全部意义,这是为了让我抽象出所有错误类型并自动处理。
我会有一些奇怪的功能:
async function buildC(a : TypeA): TaskEither<Error, TypeC> {
const b = await fetchBBasedOnOutputOfA(a);
// NOW DO MY OWN ERROR HANDLING HERE :(
if (isRight(b)) {
return fetchCBasedOnOutputOfAandB(a, b);
}
// etc.
那么有没有更惯用的方法来做到这一点,也许是创建树结构并遍历它们?虽然说实话,Traverse 的文档很少包含代码示例,而且我不知道如何使用它们。
【问题讨论】:
-
附带说明,当您有多个彼此独立的计算时,通常会使用
traverse或sequence等函数。在您的情况下,您的每个函数都将依赖于先前的结果,这就是chain和Do将派上用场的地方。 -
我刚才问了一个类似的问题,得到了同样的答案:stackoverflow.com/questions/58560310/…
标签: typescript fp-ts