我对函数式编程非常陌生,尤其是fp-ts
。
我最近在挣扎的是使用数组并将它们链接到不同的Monad中,同时保留与每个步骤有关的一些细节。
假设我们有一个程序,
ITitle
数组;类型可以为Option<ITitle[]>
ITitle
数组中;类型可以为TaskEither<IError, ITitle>
// 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?
)
答案 0 :(得分:2)
TE.map(parseTitles)
给我们一个TaskEither<IError, Option<ITitle[]>>
,问题出在chain
回调中,其中titles
仍然包裹在Option中,这不起作用
您可以使用fromOption
添加另一个将chain
展开为Option
的{{1}}:
TaskEither
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))
),
)