获取 TaskEithers 数组中的第一个成功值
Getting the first successful value in an array of TaskEithers
我是函数式编程的新手,也是 fp-ts 的新手,所以我很难理解所提供的 util 函数。我目前正在尝试弄清楚如何处理 TaskEither
s 作为数组中的后备。
我有一个函数可以为某些 id
获取数据,即 returns Error
或 Success
:
declare function getData(id: number): TaskEither<Error, Success>
我想要的是一个函数,它将遍历一些 id
数组(例如 [1, 2, 3, 4]
),为每个数组请求数据。它应该在第一个成功的 TaskEither
和 return Right<Success>
处停止。如果所有 TaskEither
都失败了,它应该将它们的错误收集到 Left<Error[]>
.
中
import { map } from 'fp-ts/lib/Array';
const program: TaskEither<Error[], Success>
= pipe(
[1, 2, 3, 4],
map(getData),
/*
* Now I have a TaskEither<Error, Success>[]
* What comes next?
*/
);
我试过类似的东西,但有一些明显的问题(如下所述):
import { map, sequence } from 'fp-ts/lib/Array';
import { map as mapTaskEither } from 'fp-ts/lib/TaskEither'
const program: TaskEither<Error, Success>
= pipe(
[1, 2, 3, 4],
map(getData),
sequence(taskEither), // Now this gets to a TaskEither<Error, Success[]>
mapTaskEither(successes => successes[0])
);
这种方法的问题
- 它在所有 ID 上运行
getData
,第一次成功时不会短路
- 如果 任何 个
getData
错误,它就会出错。所以如果getData(4)
出错,即使getData(1)
成功 ,整体program
也会出错
- 它不会将错误收集到
Error[]
的数组中
感谢,我想出了一个解决方案。
给这个 util 函数起一个名字有助于提高可读性:
import { TaskEither, taskEither, swap } from 'fp-ts/lib/TaskEither';
import { sequence, map } from 'fp-ts/lib/Array';
import { pipe } from 'fp-ts/lib/function';
const firstRightOrLefts: <A, B>(taskEithers: TaskEither<A, B>[]) => TaskEither<A[], B>
= taskEithers => pipe(
taskEithers,
map(swap),
sequence(taskEither),
swap,
);
然后可以这样使用:
import { map } from 'fp-ts/lib/Array';
const program: TaskEither<Error, Success>
= pipe(
[1, 2, 3, 4],
map(getData),
getFirstRightOrLefts, // <-- Woohoo!
);
我是函数式编程的新手,也是 fp-ts 的新手,所以我很难理解所提供的 util 函数。我目前正在尝试弄清楚如何处理 TaskEither
s 作为数组中的后备。
我有一个函数可以为某些 id
获取数据,即 returns Error
或 Success
:
declare function getData(id: number): TaskEither<Error, Success>
我想要的是一个函数,它将遍历一些 id
数组(例如 [1, 2, 3, 4]
),为每个数组请求数据。它应该在第一个成功的 TaskEither
和 return Right<Success>
处停止。如果所有 TaskEither
都失败了,它应该将它们的错误收集到 Left<Error[]>
.
import { map } from 'fp-ts/lib/Array';
const program: TaskEither<Error[], Success>
= pipe(
[1, 2, 3, 4],
map(getData),
/*
* Now I have a TaskEither<Error, Success>[]
* What comes next?
*/
);
我试过类似的东西,但有一些明显的问题(如下所述):
import { map, sequence } from 'fp-ts/lib/Array';
import { map as mapTaskEither } from 'fp-ts/lib/TaskEither'
const program: TaskEither<Error, Success>
= pipe(
[1, 2, 3, 4],
map(getData),
sequence(taskEither), // Now this gets to a TaskEither<Error, Success[]>
mapTaskEither(successes => successes[0])
);
这种方法的问题
- 它在所有 ID 上运行
getData
,第一次成功时不会短路 - 如果 任何 个
getData
错误,它就会出错。所以如果getData(4)
出错,即使getData(1)
成功 ,整体 - 它不会将错误收集到
Error[]
的数组中
program
也会出错
感谢
给这个 util 函数起一个名字有助于提高可读性:
import { TaskEither, taskEither, swap } from 'fp-ts/lib/TaskEither';
import { sequence, map } from 'fp-ts/lib/Array';
import { pipe } from 'fp-ts/lib/function';
const firstRightOrLefts: <A, B>(taskEithers: TaskEither<A, B>[]) => TaskEither<A[], B>
= taskEithers => pipe(
taskEithers,
map(swap),
sequence(taskEither),
swap,
);
然后可以这样使用:
import { map } from 'fp-ts/lib/Array';
const program: TaskEither<Error, Success>
= pipe(
[1, 2, 3, 4],
map(getData),
getFirstRightOrLefts, // <-- Woohoo!
);