Как преобразовать `List [IO [Unit]]` в `Stream [IO, Unit]` - PullRequest
1 голос
/ 10 апреля 2020

У меня есть List[IO[Unit]], который состоит из отдельных работ, закодированных в IO. Я хотел бы преобразовать его в Stream[IO,Unit]

В настоящее время я сделал следующее:

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

Есть ли лучший способ?

Ответы [ 2 ]

3 голосов
/ 10 апреля 2020

Я могу подумать об этих трех альтернативах:
(Обратите внимание, я только что проверил проверку типов, но я их не запускал)

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

Кстати, если вы получили Список [IO [Unit]] после map.

Вы можете data.traverse(f) вместо works.map(f).sequence
И f(input).map { io => вместо work.map { io =>

2 голосов
/ 10 апреля 2020

Я предлагаю сделать одно из них:

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

Есть разница с выполнением Stream.evals на works.sequence в том, что вы теряете тот факт, что ваш эффект состоит из разных частей. Это всплывет, если вы запустите поток частично, например, выполнив:

stream.take(3).compile.drain

Если вы не последовательность, он будет запускать только первые 3 элемента из works. Если вы это сделаете, он запустит их все.

Из других вариантов, предложенных Луисом Мигелем, только unfoldEval сохраняет разделение, но, вероятно, это излишнее.

...