简体   繁体   English

在 fp-ts 和函数式编程中管理单子数组

[英]Managing array of monads in fp-ts and Functional Programming

I'm very new to Functional Programming and I'm struggling a lot with running traverse on arrays.我对函数式编程非常陌生,并且在 arrays 上运行遍历时遇到了很多困难。

When I read 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 .当我阅读这本书时,似乎我应该能够简单地在 Monad 之间遍历,但我无法用fp-ts来理解这个概念。

Can someone explain the following using array.traverse/sequence or any other ways please?有人可以使用array.traverse/sequence或任何其他方式解释以下内容吗?

  1. How can I go from TaskEither<Error, string[]> to TaskEither<Error, Either<Error, string>[]> ;我怎样才能 go 从TaskEither<Error, string[]>TaskEither<Error, Either<Error, string>[]> ; or is there a better way to go from a single error to nested errors while keeping the typings simple?或者有没有更好的方法将 go 从单个错误变为嵌套错误,同时保持打字简单?
  2. How can I go from TaskEither<Error, Either<Error, string[]>> to something like TaskEither<Error, Option<string[]>> or something similar;我怎样才能从TaskEither<Error, Either<Error, string[]>> go 到TaskEither<Error, Option<string[]>>或类似的东西; or should we map the result of that function to turn back to Either ?还是我们应该将 map 的结果 function 转回Either

Consider the following simplified code to have a better idea what we are doing with these arrays:考虑以下简化代码,以便更好地了解我们正在使用这些 arrays 做什么:

// 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
)

Strictly spoken, Applicative is sufficient for traverse - you don't need a monad.严格来说, Applicative足以traverse - 你不需要 monad。

TaskEither<Error, string[]> to TaskEither<Error, Either<Error, string>[]> ? TaskEither<Error, string[]>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[]>> ? TaskEither<Error, Either<Error, string[]>>TaskEither<Error, Option<string[]>>

const program2 = (input: string) =>
  P.pipe(
    toItems(input),
    TE.map(items => A.array.traverse(O.option)(items, clean))
  );

The concrete chosen structure depends your environment and purpose.具体选择的结构取决于您的环境和目的。 Option : emphasis on absence/presence; Option :强调缺席/在场; Either : permits a more concrete error type in Left . Either是:允许在Left中使用更具体的错误类型。


Let's look at some programs and imagine, all use a web API with TaskEither .让我们看一些程序并想象一下,它们都使用带有 TaskEither 的 web TaskEither

Program 3: (input: string) => TE.TaskEither<Error, string[]> 程序 3:( (input: string) => TE.TaskEither<Error, string[]>

▶ will either fail completely with Error or succeed with string[] fetched data ▶ 将因Error完全失败或因string[]获取数据而成功

Program 4: (input: string) => TE.TaskEither<Error, E.Either<Error, string[]>> 程序 4:( (input: string) => TE.TaskEither<Error, E.Either<Error, string[]>>

fetch results in Error or succeeds. fetch Error或成功的结果。 If succeeded, process web data further - resulting in Error or string[]如果成功,则进一步处理 web 数据 - 导致Errorstring[]

Program 5: (input: string) => TE.TaskEither<Error, E.Either<Error, string>[]> 程序 5:( (input: string) => TE.TaskEither<Error, E.Either<Error, string>[]>

▶ same as Program 4, but post-processing of web data results in multiple Either results - each can fail or succeed individually ▶ 与程序 4 相同,但 web 数据的后处理会产生多个Either结果 - 每个都可以单独失败或成功


Here is implementation of program 4 as some kind of middle ground:这是作为某种中间立场的程序 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))) ) ) ) );

Codesandbox密码沙盒

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 fp-ts,如何获取TaskEithers数组,在每个项目中运行一个function,然后将选项分成两个arrays? - fp-ts, how to take an array of TaskEithers, run a function in each item then split the options into two arrays? 反转多维数组-函数式编程风格 - Reverse a mult dimensional array - functional programming style 使用函数式编程复制数组的元素 - Duplicating an array's elements using functional programming 使用功能编程对2D数组中的列求平均值 - Average a columns in a 2D array with functional programming 函数式编程和ES6数组子类化 - Functional programming and ES6 array subclassing 功能编程风格增长阵列循环 - Functional Programming style growing array loop Julia:函数式编程:根据另一个值数组验证数组条目 - Julia: Functional Programming :Validate array entries against another array of values Swit中的函数式编程可分配数组元素以更正“存储桶” - Functional Programming in Swit to distribute array elements to correct “buckets” 如何用纯函数编程对破坏所有条件的数组元素进行分组? - How to group array elements breaking every condition with pure functional programming? 函数式编程:Numpy向量化函数以创建期望值数组 - Functional Programming: Numpy Vectorizable Function to Create an Expected Values Array
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM