0

我对函数式编程非常陌生,特别是fp-ts.

我最近苦苦挣扎的是使用数组并将它们链接到不同的 Monad 中,同时保留与每个步骤相关的一些细节。

假设我们有一个程序

  1. 获取一些数据作为字符串
  2. ITitle如果可能,将字符串解析为数组;类型可以是Option<ITitle[]>
  3. ITitle将它们映射到可能执行一些异步更新的数组中;类型可以是TaskEither<IError, ITitle>
  4. 打印结果(如果可用),包括失败及其特定错误
// error definition
enum ErrorType {
    NotFound = 'NOT_FOUND',
    Timeout = 'TIMEOUT',
    ParseFailure = 'PARSE_FAILURE',
    UpdateFailure = 'UPDATE_FAILURE',
    Unknown = 'UNKNOWN',
}
// our types
interface ITitle {
    title: string;
    meta: unknown;
}
interface IError {
    msg: string;
    type: ErrorType;
}

// helper functions
declare function findTitles(): TaskEither<IError, string>;
declare function parseTitles(items: string): Option<ITitle[]>; // or Either<IError, ITitle[]> whatever fits best
declare function updateTitle(title: ITitle): TaskEither<IError, ITitle>;

更新:
我正在用更具体的问题更新问题:

const program = pipe(
  findTitles(),
  TE.map(parseTitles), // Now we get TaskEither<IError, Option<ITitle[]>>;
  TE.chain(titles =>
    // Problem is var titles is still wrapped in Option and this won't work
    // What if the titles is Either<IError, ITitle[]>?
    // How do we preserve the error if titles is an Either?
    array.traverse(taskEither)(titles, title => updateTitle(title))
  ),
  // How to log the result including the errors?
  // Or in another word how do we run traverse and fold the Eithers?
)
4

1 回答 1

2

TE.map(parseTitles)给我们一个TaskEither<IError, Option<ITitle[]>>,问题出在chain回调中,titles仍然包裹在 Option 中,这不起作用

您可以使用以下方法添加另一个chain将其解包Option到 aTaskEitherfromOption

const program = pipe(
  findTitles(),
  TE.map(parseTitles), // Now we have TaskEither<IError, Option<ITitle[]>>;
  TE.chain(TE.fromOption(() => ErrorType.NotFound)) // Now we have TaskEither<IError, ITitle[]>
  TE.chain(titles =>
    array.traverse(taskEither)(titles, title => updateTitle(title))
  ),
)

fromEither

const program = pipe(
  findTitles(),
  TE.map(parseTitles), // Now we have TaskEither<IError, Either<IError, ITitle[]>>;
  TE.chain(TE.fromEither) // Now we have TaskEither<IError, ITitle[]>
  TE.chain(titles =>
    array.traverse(taskEither)(titles, title => updateTitle(title))
  ),
)
于 2020-04-05T21:53:37.980 回答