fs2 dropWhile with X => IO[布尔值]



我可以写如下代码,它就像它应该的那样工作(它产生10):

import cats.effect.IO
import cats.effect.unsafe.implicits.global
val zz: fs2.Stream[IO, Int] = fs2.Stream.iterate[IO, Int](1)(_+1).map(_*2)
val qq: IO[Int] = zz.dropWhile(_ < 10).take(1).compile.toList.map(_.head)
qq.unsafeRunSync()

然而,假设不是像_ < 10这样返回布尔值的谓词,我有一个谓词返回一个IO[Boolean]。是否有另一种形式的dropWhile可以处理这种情况?我不想在谓词中做一些像unsafeRunSync()这样的事情,这样它就可以产生一个布尔值.

显然,这是一个玩具案例,而不是我正在解决的实际问题。

您可以轻松地自己定义组合符:

def dropWhileEval[A](sa: Stream[IO, A])(p: A = IO[Boolean]): Stream[IO, A] =
sa.evalMap(a => p(a).map(b => (b, a))).dropWhile(_._1).map(_._2)

这个答案是基于@Luis Miguel Mejia Suárez的公认答案。但是在这个答案中有一个小错字,基本上,我在发布原始问题后更改了问题。这是最终的(玩具)代码:

import cats.effect.IO
import fs2.{Pure, Stream}
import cats.effect.unsafe.implicits.global
val fLessThan10: Int => Boolean = _ < 10
val fLessThan10_lifted: IO[Int] => IO[Boolean] = _ map fLessThan10
def dropWhileEval[A](sa: Stream[IO, IO[A]])(p: IO[A] => IO[Boolean]): fStream[IO, IO[A]] =
sa.evalMap(a => p(a).map(b => (b, a))).dropWhile(_._1).map(_._2)
val zz: Stream[IO, IO[Int]] = Stream.iterate[IO, Int](1)(_+1).map(x => IO(x*2))
val yy: Stream[IO, IO[Int]] = dropWhileEval[Int](zz)(fLessThan10_lifted).take(1)
val result: IO[List[Int]] = yy.evalMap(identity).compile.toList
@result.unsafeRunSync()

最新更新