在 fp-ts 和函数式编程中管理 monad 数组
Managing array of monads in fp-ts and Functional Programming
我是函数式编程的新手,我在 运行 遍历数组方面遇到了很多困难。
当我阅读this book it seems that I should be able to simply traverse between Monads but I can't wrap my head around this concept with fp-ts.
有人可以使用 array.traverse/sequence
或任何其他方式解释以下内容吗?
- 如何从
TaskEither<Error, string[]>
到 TaskEither<Error, Either<Error, string>[]>
;还是有更好的方法从单个错误到嵌套错误,同时保持输入简单?
- 我怎样才能从
TaskEither<Error, Either<Error, string[]>>
变成 TaskEither<Error, Option<string[]>>
或类似的东西?或者我们应该映射该函数的结果以返回 Either
?
考虑以下简化代码,以更好地了解我们对这些数组的处理方式:
// helper functions
declare function toItems(input: string): TaskEither<Error, string[]);
declare function toTitle(item: string): Either<Error, string>;
declare function clean(item: string): Option<string>;
// This is what I tried so far
const program = (input: string) => pipe(
toItems(input), // we have TaskEither<Error, string[]>
TE.map(items => array.traverse(either)(items, toTitle)), // now we have TaskEither<Error, Either<Error, string[]>>
TE.map(items => array.traverse(option)(items, clean)), // nothing works with clean() from here
)
严格来说,Applicative 足以满足 traverse
- 您不需要 monad。
TaskEither<Error, string[]>
to TaskEither<Error, Either<Error, string>[]>
?
const program1 = (input: string) =>
P.pipe(
toItems(input),
TE.map(A.map(toTitle))
);
TaskEither<Error, Either<Error, string[]>>
to TaskEither<Error, Option<string[]>>
?
const program2 = (input: string) =>
P.pipe(
toItems(input),
TE.map(items => A.array.traverse(O.option)(items, clean))
);
具体选择的结构取决于您的环境和目的。 ▶ Option
:强调absence/presence; ▶ Either
:允许在 Left
.
中使用更具体的错误类型
让我们看一些程序并想象一下,所有程序都使用 API 和 TaskEither
。
计划 3:(input: string) => TE.TaskEither<Error, string[]>
▶ 将 完全失败 Error
或 string[]
成功获取数据
计划 4:(input: string) => TE.TaskEither<Error, E.Either<Error, string[]>>
▶ fetch
结果 Error
或成功。如果成功,进一步处理网络数据 - 导致 Error
或 string[]
方案 5:(input: string) => TE.TaskEither<Error, E.Either<Error, string>[]>
▶ 与计划 4 相同,但 post- 处理 Web 数据会产生 多个 Either
个结果 - 每个都可能失败或成功 个别
这里是作为某种中间立场的程序 4 的实现:
const program4 = (
input: string
): TE.TaskEither<Error, E.Either<Error, string[]>> =>
P.pipe(
toItems(input), // TE.TaskEither<Error, string[]>
TE.map(items => // TE.TaskEither<E, E.Either<Error, string[]>>
A.array.traverse(E.either)( // E.Either<Error, string[]>
items,
F.flow( // E.Either<Error, string>
toTitle,
E.chain(s => E.fromOption(() => Error())(clean(s)))
)
)
)
);
我是函数式编程的新手,我在 运行 遍历数组方面遇到了很多困难。
当我阅读this book it seems that I should be able to simply traverse between Monads but I can't wrap my head around this concept with fp-ts.
有人可以使用 array.traverse/sequence
或任何其他方式解释以下内容吗?
- 如何从
TaskEither<Error, string[]>
到TaskEither<Error, Either<Error, string>[]>
;还是有更好的方法从单个错误到嵌套错误,同时保持输入简单? - 我怎样才能从
TaskEither<Error, Either<Error, string[]>>
变成TaskEither<Error, Option<string[]>>
或类似的东西?或者我们应该映射该函数的结果以返回Either
?
考虑以下简化代码,以更好地了解我们对这些数组的处理方式:
// helper functions
declare function toItems(input: string): TaskEither<Error, string[]);
declare function toTitle(item: string): Either<Error, string>;
declare function clean(item: string): Option<string>;
// This is what I tried so far
const program = (input: string) => pipe(
toItems(input), // we have TaskEither<Error, string[]>
TE.map(items => array.traverse(either)(items, toTitle)), // now we have TaskEither<Error, Either<Error, string[]>>
TE.map(items => array.traverse(option)(items, clean)), // nothing works with clean() from here
)
严格来说,Applicative 足以满足 traverse
- 您不需要 monad。
TaskEither<Error, string[]>
toTaskEither<Error, Either<Error, string>[]>
?
const program1 = (input: string) =>
P.pipe(
toItems(input),
TE.map(A.map(toTitle))
);
TaskEither<Error, Either<Error, string[]>>
toTaskEither<Error, Option<string[]>>
?
const program2 = (input: string) =>
P.pipe(
toItems(input),
TE.map(items => A.array.traverse(O.option)(items, clean))
);
具体选择的结构取决于您的环境和目的。 ▶ Option
:强调absence/presence; ▶ Either
:允许在 Left
.
让我们看一些程序并想象一下,所有程序都使用 API 和 TaskEither
。
(input: string) => TE.TaskEither<Error, string[]>
▶ 将 完全失败 Error
或 string[]
成功获取数据
(input: string) => TE.TaskEither<Error, E.Either<Error, string[]>>
▶ fetch
结果 Error
或成功。如果成功,进一步处理网络数据 - 导致 Error
或 string[]
(input: string) => TE.TaskEither<Error, E.Either<Error, string>[]>
▶ 与计划 4 相同,但 post- 处理 Web 数据会产生 多个 Either
个结果 - 每个都可能失败或成功 个别
这里是作为某种中间立场的程序 4 的实现:
const program4 = (
input: string
): TE.TaskEither<Error, E.Either<Error, string[]>> =>
P.pipe(
toItems(input), // TE.TaskEither<Error, string[]>
TE.map(items => // TE.TaskEither<E, E.Either<Error, string[]>>
A.array.traverse(E.either)( // E.Either<Error, string[]>
items,
F.flow( // E.Either<Error, string>
toTitle,
E.chain(s => E.fromOption(() => Error())(clean(s)))
)
)
)
);