Reputation: 1459
I have a List[IO[Unit]]
which consists of distinct works encoded in IO
. I would like to convert it into Stream[IO,Unit]
Currently, what I have done is this
val works: List[IO[Unit]]
works.map(work => Stream.eval(work)).reduceLeft((left, right) => left ++ right)
Is there a better way?
Upvotes: 2
Views: 920
Reputation: 7353
I suggest doing one of those:
Stream.emits(works).flatMap(Stream.eval) // or
Stream.emits(works).evalMap(x => x) // which is the same, or
Stream(works: _*).evalMap(x => x) // which is also the same
There's a difference vs. doing Stream.evals
on a works.sequence
in that you lose the fact that your effect is made of different parts. That will surface itself if you run stream partially, e.g. by doing:
stream.take(3).compile.drain
If you do not sequence, it will only run first 3 elements from works
. If you do, it will run all of them.
From other options proposed by Luis Miguel, only the unfoldEval
one preserves the separation, but it's probably an overkill.
Upvotes: 3
Reputation: 22895
I can think of these three alternatives:
(Note, I just checked they typecheck but I didn't run them)
def stream1: Stream[IO, Unit] =
Stream.evalSeq(works.sequence)
def stream2: Stream[IO, Unit] =
Stream.evals(works.sequence)
def stream3: Stream[IO, Unit] =
Stream.unfoldEval(works) {
case work :: tail =>
work.map { io =>
Some(io -> tail)
}
case Nil =>
IO.pure(None)
}
BTW, if you got that List[IO[Unit]] after a map
.
You can data.traverse(f)
instead of works.map(f).sequence
And f(input).map { io =>
instead of work.map { io =>
Upvotes: 3