如何将 `List[IO[Unit]]` 转换为 `Stream[IO,Unit]`

How to convert a `List[IO[Unit]]` into `Stream[IO,Unit]`

我有一个 List[IO[Unit]],它由 IO 编码的不同作品组成。我想把它转换成 Stream[IO,Unit]

目前我做的是这样的

val works: List[IO[Unit]]
works.map(work => Stream.eval(work)).reduceLeft((left, right) => left ++ right)

有没有更好的方法?

我能想到这三个备选方案:
(注意,我只是检查了它们的类型检查,但我没有 运行 它们)

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)
  }

顺便说一句,如果你在 map.

之后得到 List[IO[Unit]]

您可以 data.traverse(f) 而不是 works.map(f).sequence
并且 f(input).map { io => 而不是 work.map { io =>

我建议做其中之一:

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

与在 works.sequence 上执行 Stream.evals 的区别在于您失去了效果由不同部分组成的事实。如果您 运行 部分流式传输,这将自行浮出水面,例如通过做:

stream.take(3).compile.drain

如果您序列,它只会运行来自works的前3个元素。如果这样做,它将 运行 所有这些。

从 Luis Miguel 提出的其他选项中,只有 unfoldEval 保留了分隔,但这可能有点矫枉过正。