Составление нескольких фьючерсов и опций в Scala с ZIO - PullRequest
1 голос
/ 05 апреля 2020

Я только начал оценивать ZIO, чтобы улучшить модель программирования и производительность моего асинхронного Scala кода. В моей кодовой базе я часто имею дело с Future[Option[T]], и до этого момента я имел дело с этим, используя OptionT монадный преобразователь Scalaz. Теперь я хочу попробовать это с ZIO.

Рассмотрим две функции:

def foo: String => Future[Option[T]] и def bar: T => Future[U]

Я пробовал что-то вроде этого:

val t = for {
       o: Option[Int] <- ZIO.fromFuture { implicit ec =>
            foo("test")
       }
       i: Int <- ZIO.fromOption(o)
       s: String <- ZIO.fromFuture { implicit ec =>
            bar(i)
       }
} yield s

Согласно моей IDE, t имеет тип ZIO[Any, Any, String] в этом сценарии. Я не знаю, что с этим делать.

Я хочу рассмотреть три варианта:

  • Случай "успеха", когда foo производит Some, который может быть составлено с другими функциями по значению
  • Случай, когда foo выдает None
  • Случай, когда любая функция выдает ошибку

Я не являюсь уверен, как проанализировать эти возможности в этом сценарии с ZIO. Любая помощь приветствуется.

Ответы [ 2 ]

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

Тип ZIO.fromOption(o) равен IO[Unit, A], что составляет ZIO[Any, Unit, A], в то время как тип ZIO.fromFuture равен Task[A], что составляет ZIO[Any, Throwable, A], как указано в Псевдонимы типа . Таким образом, типы не выравнивают

ZIO[Any, Unit, A]
ZIO[Any, Throwable, A]

Попробуйте mapError выровнять типы ошибок по Throwable, например, так:

for {
  o <- ZIO.fromFuture { implicit ec => foo("test") }
  i <- ZIO.fromOption(o).mapError(_ => new RuntimeException("boom"))
  s <- ZIO.fromFuture { implicit ec => bar(i)}
} yield s
1 голос
/ 06 апреля 2020

Есть пара операторов, которые могут помочь вам в этом случае, в основном, вместо того, чтобы явно развернуть Option с fromOption, я бы рекомендовал использовать комбинацию some и asSomeError

val t: Task[Option[String]] = (for {

  // This moves the `None` into the error channel
  i: Int <- ZIO.fromFuture(implicit ec => foo("test")).some

  // This wraps the error in a Some() so that the signature matches
  s: String <- ZIO.fromFuture(implicit ec => bar(i)).asSomeError

} yield s).optional // Unwraps the None back into the value channel
...