【问题标题】:How do I avoid nested Monads in fp-ts or deal with them elegantly?如何避免 fp-ts 中的嵌套 Monad 或优雅地处理它们?
【发布时间】:2019-07-06 02:16:58
【问题描述】:

我有一系列代码需要经过以下步骤(伪代码):

  jobsRepository.findById // <-- this returns a TaskEither
  jobs.openJob // <-- jobs.openJob returns an Either
  jobsRepository.update // <-- this returns another TaskEither
  createJobOpenedEvent // simple function that returns an IJobOpenedEvent
                       // given an IOpenJob

如果我将这些步骤映射/链接在一起,我最终会得到像 TaskEither&lt;IError, Either&lt;IError, TaskEither&lt;IError, IOpenJob&gt;&gt;&gt; 这样的类型,这显然有点尴尬。

我目前的解决方案是将所有这些扁平化为一个简单的TaskEither&lt;IError, IJobOpenedEvent&gt; 类型,如下所示(实际代码):

import { flatten } from "fp-ts/lib/Chain";
import { Either, either, left, right } from "fp-ts/lib/Either";
import {
  fromEither,
  TaskEither,
  taskEither,
  tryCatch,
} from "fp-ts/lib/TaskEither";

const createJobOpenedEvent = (openJob: jobs.IOpenJob): IJobOpenedEvent => ({
  name: "jobOpened",
  payload: openJob,
});

export const openJobHandler = (
  command: IOpenJobCommand
): TaskEither<IError, IJobOpenedEvent> =>
  flatten(taskEither)(
    flatten(taskEither)(
      jobsRepository
        .findById(command.jobId) // <-- this returns a TaskEither<IError, IJob>
        .map(jobs.openJob) // <-- jobs.openJob returns an Either<IError, IOpenJob>
        .map(fromEither)
        .map(jobsRepository.update) // <-- this returns a TaskEither<IError,IOpenJob>
    )
  ).map(createJobOpenedEvent);


我的问题是 - 有没有更好的方法来处理这种嵌套?我觉得我做错了,因为我是函数式编程的新手并且不理解所有的理论。拥有所有嵌套的flatten(taskEither) 调用并将Either 转换为TaskEitherfromEither 对我来说似乎很糟糕。

非常感谢任何帮助!

【问题讨论】:

  • 使用flatMap/chain而不是在很多flattens中嵌套很多maps
  • fromEither 很好(除非在TaskEither 上有一个特定的辅助方法,如mapEither
  • 啊,你说得对,使用chain 效果很好!

标签: typescript functional-programming monads fp-ts


【解决方案1】:

感谢 Bergi 的评论,我能够使用 chain 而不是 map 找到以下解决方案:

export const openJobHandler = (
  command: IOpenJobCommand
): TaskEither<IError, IJobOpenedEvent> =>
  jobsRepository
    .findById(command.jobId)
    .map(jobs.openJob)
    .chain(fromEither)
    .chain(jobsRepository.update)
    .map(createJobOpenedEvent)

【讨论】:

  • 您好,chainflatmap 有什么区别?
  • 嗨,克里斯蒂安,它们是同一事物的两个名称 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 2022-08-14
  • 2012-05-08
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
相关资源
最近更新 更多