是否有任何内建的方法在fp-ts减少函数的数组每一个作为参数的结果另一个返回一个任务?



假设我们有一个函数数组,每个函数取一个数字并返回一个TaskEither<string, number>

let tasks: (n: number) => TE.TaskEither<string, number>[] = [];

目标是提供一个初始值,然后按顺序执行每个函数和另一个函数的结果。

reducer是一个选项:

const taskEitherReducer = <E, S>(acc: TE.TaskEither<E, S>, cur: (x: S) => TE.TaskEither<E, S>) =>  
pipe(TE.map(cur)(acc), TE.flatten);

然后可以定义一个接受初始值和任务数组的函数:

const runTasks =   
(initialValue: number) =>  
A.reduce(  
TE.of(initialValue),  
(  
acc: TE.TaskEither<string, number>,  
cur: (ord: number) => TE.TaskEither<string, number>  
) => taskEitherReducer(acc, cur));  

最后:

runTasks(1)(tasks);

问题:

  • 所有这些过程看起来像一个组合,TaskEither.chain()允许组合函数,但强制知道我们想要组合哪些函数。在这种情况下,我们不知道有多少个这样的函数,只知道它的类型。

那么,fp-ts中有没有什么内置的方法来实现这种动态构图呢?

不确定这将回答您的问题,但是有一个reduceM组合子,它概括了返回一元值的函数的通常减少。你需要为函数返回的类型提供一个Monad实例,为你要折叠的类型提供一个Foldable实例。

import * as TE from "fp-ts/TaskEither";
import * as F from "fp-ts/Foldable";
import * as A from "fp-ts/Array";
import { pipe } from "fp-ts/lib/function";
const tasks: ((n: number) => TE.TaskEither<string, number>)[] = [];
const reduceTaskEither = F.reduceM(TE.Monad, A.Foldable);
const runTasks = (initialValue: number) =>
pipe(
tasks,
reduceTaskEither(initialValue, (n, f) => f(n))
);