fp-ts
库进行函数式编程。
这是我的代码和我的问题:
import * as TE from 'fp-ts/TaskEither';
import { pipe } from 'fp-ts/lib/function';
function getName(): TE.TaskEither<Error, String> {
return TE.right('John Doe');
}
function getAge(): TE.TaskEither<Error, number> {
return TE.right(40);
}
export function seqArrayTest(): TE.TaskEither<Error, string> {
return pipe(
TE.sequenceArray([
getName(),
getAge(),
]),
TE.chain(([name, age]) => {
return TE.right(`Name: ${name}, Age: ${age}`);
}),
);
}
这里:
getName
和getAge
返回具有不同值类型的TaskEither
。TE.sequenceArray
称它们为并行。TaskEither
。在编译过程中,在
TE.sequenceArray([getName(), getAge()])
上,它显示以下getAge()
错误:
类型“TaskEither
”不可分配给类型“TaskEither ”。 类型“number”不可分配给类型“String”.ts(2322)
但我的理解是:
TE.sequenceArray
应该采用一组具有不同返回类型的函数,这些函数用TaskEither
包装,并且它将按顺序返回一组响应。
查看 文档,
TE.sequenceArray
期望有一组具有相同正确类型的 TaskEithers。
export declare const sequenceArray: <A, E>(arr: readonly TaskEither<E, A>[]) =>
TaskEither<E, readonly A[]>
您可以明确指定数组的类型为
Array<TE.TaskEither<Error, String | number>>
,并且它应该按预期工作。
pipe(
[getName(), getAge()] as Array<TE.TaskEither<Error, String | number>>,
TE.sequenceArray,
// ...
);
然而,在调用
TE.chain
时解压这些值理论上可能是危险的。在 chain
调用中不能保证数组将有两个元素。正如所写的,它会,但类型检查器无法推断出这一点。 Do
符号可能更适合这些场景。
@Souperman 的答案在这种情况下是正确的。
TE.sequenceArray
期望具有相同 TaskEithers
类型的 Right
数组。
如果我们要处理
TaskEither
的数组并且返回类型不同,那么我们可以使用sequenceT
。
这是修改后的代码:
import * as TE from "fp-ts/TaskEither";
import { pipe } from "fp-ts/lib/function";
import { sequenceT } from "fp-ts/Apply";
function getName(): TE.TaskEither<Error, String> {
return TE.right("John Doe");
}
function getAge(): TE.TaskEither<Error, number> {
return TE.right(30);
}
export function seqArrayTest(): TE.TaskEither<Error, string> {
return pipe(
sequenceT(TE.ApplyPar)(getName(), getAge()),
TE.chain(([name, age]) => {
return TE.right(`Name: ${name}, Age: ${age}`);
}),
TE.mapLeft((e) => e)
);
}
这里,
TE.chain(([name, age])
参数中name
是string
类型,age
是number
类型。响应顺序将基于调用顺序。