I can write something like the following and it works just as it should (it yields 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()
However, supposing that, instead of a predicate like _ < 10
which returns Boolean, I have a predicate that returns an IO[Boolean]. Is there an alternative form of dropWhile which could handle this situation? I don't want to have to do something like unsafeRunSync() inside the predicate just so that it can yield a Boolean.
Clearly, this is a toy case, not the actual problem that I'm working on.
CodePudding user response:
You can easily define that combinator yourself:
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)
CodePudding user response:
This answer is based on the accepted answer by @Luis Miguel Mejia Suárez. But there is a tiny typo in that answer and, essentially, I changed the question after posting the original. So here's the final (toy) code:
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()