Lev*_*sov 15 functional-programming scala scala-cats fs2
在函数流的 Scala fs2 库中:
我想明白之间的差别flatMap,flatTap,evalMap和evalTap。它们似乎都执行相同的操作,即流值的转换。
有什么区别以及何时应该使用它们中的每一个?
Yuv*_*kov 11
传统上,taplike 函数允许您观察(或窥视)流中的元素,但丢弃观察效果的结果。例如,在 fs2 中,您可以看到的签名evalTap是:
def evalTap[F2[x] >: F[x]](f: (O) ? F2[_])(implicit arg0: Functor[F2]): Stream[F2, O]
Run Code Online (Sandbox Code Playgroud)
注意f函数 from 的方式O => F2[_],意思是“你取一个O值并返回一个F2存在 Functor的效果类型”,但它不会影响流的返回类型,它仍然是O.
例如,如果我们想将流的元素发送到控制台,我们可以这样做:
import cats.effect.{ExitCode, IO, IOApp}
import cats.implicits._
object Test extends IOApp {
override def run(args: List[String]): IO[ExitCode] = {
fs2
.Stream(1, 2, 3)
.covary[IO]
.evalTap(i => IO(println(i)))
.map(_ + 1)
.compile
.drain
.as(ExitCode.Success)
}
}
Run Code Online (Sandbox Code Playgroud)
这将产生1 2 3.
您可以看到我们使用 将流的每个元素发送到控制台evalTap,其中我们具有 type 的效果IO[Unit],但我们可以立即map在管道的下一步中每个这样的元素,因为它不会影响流的结果类型.
我找不到,flatTap但我认为它们在 fs2 中通常是相同的(https://github.com/functional-streams-for-scala/fs2/issues/1177)
另一方面,像flatMap这样的函数确实会导致流的返回类型发生变化。我们可以看到签名:
def flatMap[F2[x] >: F[x], O2](f: O => Stream[F2, O2]): Stream[F2, O2] =
Run Code Online (Sandbox Code Playgroud)
请注意,与 不同evalTap的f是O2,执行的结果是,它也在返回类型中进行了编码。如果我们采用与上面相同的示例:
fs2
.Stream(1, 2, 3)
.covary[IO]
.flatMap(i => fs2.Stream(IO(println(i))))
.map(_ + 1)
.compile
.drain
.as(ExitCode.Success)
Run Code Online (Sandbox Code Playgroud)
这将不再编译,因为flatMap返回 an Stream[IO, Unit],这意味着它的执行println和它返回的事实Unit直接影响下游组合器。
evalMap是 a 的别名,flatMap它允许您省略Stream类型的包装,通常按照以下方式实现flatMap:
def evalMap[F2[x] >: F[x], O2](f: O => F2[O2]): Stream[F2, O2] =
flatMap(o => Stream.eval(f(o)))
Run Code Online (Sandbox Code Playgroud)
哪个使用起来方便一些。
| 归档时间: |
|
| 查看次数: |
2477 次 |
| 最近记录: |