Effect 里 map 和 flatMap 怎么选?

在 map 里返回一个 Effect,你会得到 Effect<Effect<...>>,里面那层永远不会被运行。

函数返回普通值就用 map,返回另一个 Effect 就用 flatMap。 用错了不会静默通过,因为类型会变成「Effect 里套着 Effect」,一眼就能看出来。

这里的 Effect 指 Effect<A, E, R>,一段对计算的描述而不是已经发生的结果,细节见 为什么我用 Effect。map、flatMap、tap、andThen 都是用 pipe 串起来的小变换,下面按它们的分工逐个讲。

pipe 是什么,怎么写?

pipe 在 v4 里是 Effect 值上的方法,写成 value.pipe(f, g, h),就是依次把 value 交给 f、g、h。它也可以用于任何其他值。

const piped = Effect.succeed(2).pipe(
  Effect.map((n) => n * 2),
  Effect.flatMap((n) => Effect.succeed(String(n))),
  Effect.tap((s) => Effect.log(s)),
  Effect.andThen((s) => Effect.succeed(s.length))
)

map、flatMap、tap、andThen 各管什么?

  • map:变换成功值,函数返回普通值
  • flatMap:变换成功值,函数返回另一个 Effect(需要再运行一步)
  • tap:做一个副作用(日志、指标),但保留原来的成功值
  • andThen:对「接下来做什么」的宽松写法,既接受返回值的函数,也接受返回 Effect 的函数

map 里返回了 Effect 会怎样?

结果是 Effect<Effect<...>>,里面那层永远不会被运行。这是个典型的错用,好在类型会暴露它。把 map 换成 flatMap 就行。

步骤多了,还该用 pipe 吗?

多步、有中间变量、有条件分支时,Effect.gen 更顺手;pipe 更适合在单个 Effect 上叠加一连串小变换或横切行为。两者怎么分工,见 怎么用 Effect.gen 写出第一段 Effect 程序。

本文的 API 与行为描述全部取自教程原章节,代码没有在写作时重新运行。原章节只提到 Effect v4,没有给出具体版本号,写法以你安装的版本为准。