【问题标题】:In ZIO, is there a way to transform an IO[Nothing, T] to T, and if not, why not?在 ZIO 中,有没有办法将 IO[Nothing, T] 转换为 T,如果没有,为什么不呢?
【发布时间】:2019-07-31 20:40:10
【问题描述】:

在考虑错误并将IO[E, T] 转换为IO[Nothing, T] 之后,我们可以直接将值称为T 类型而不是IO[Nothing, T]。这允许我们返回 T 类型的值,而无需使用 varIO.map。有没有办法做到这一点,如果没有,为什么不呢?

在 ZIO 的当前 README 中没有找到解决方案。

【问题讨论】:

  • 至于“为什么不呢?”:这个想法是让函数成为该函数类型签名的“非纯”部分。所以任何与IO 交互的东西都必须是IO 本身。如果你在普通的 Scala 中使用了Future,那是一种相同的情况:如果函数所做的任何事情都涉及 Futures,它本身必须返回一个 Future。您可以通过在内部调用 Await.result 来“隐藏”它,但非常不鼓励这样做。如有必要,只有最终调用者应该这样做。与IO 相同。您可以调用 unsafeRun 来“提取”该值,但您确实不应该这样做。

标签: scala scalaz zio


【解决方案1】:

IO[E, T] 只是对可以返回错误E 或产生值T 的程序的描述。

要实际产生这个值,你需要运行这个程序。

ZIO 的设计鼓励将不纯的副作用推到程序的最边缘,即main 函数。事实上,您不需要在代码中的任何位置显式调用 unsafeRun,因为 ZIO 的 App 特性会为您处理这些问题。

话虽如此,如果你仍然需要这样做,比如你还没有准备好重构整个应用程序,你可以使用RTS trait(RTS 代表运行时系统)。

import scalaz.zio._

class SomeService extends RTS {

  val pureProgram: IO[Nothing, String] = ???

  // will throw if pureProgram returns error branch
  def impureMethod: String {
    println("Part of my program is pure, but not all of it")
    unsafeRun(pureProgram)
  }
}

请参阅 ZIO RTS Scaladoc 了解其他运行方法。

【讨论】:

    【解决方案2】:

    没有办法实现一个接受IO[Nothing, T]并返回T函数。

    之所以如此,是因为 ZIO 的 IO[_, _] 的第一个类型参数描述了在 IO 包装的计算中可能发生的错误IO[Nothing, T] 描述了一个不会失败的计算,但它仍然封装了一个副作用计算。这就是为什么你不能在 pure 函数中获得 T 类型的值。

    仅谈论物理可能性,由于 Scala 不是一种纯语言,您可以编写一个接受 IO[Nothing, T] 并返回 T 的函数,但 ZIO 的设计和意识形态真的不鼓励您这样做.

    【讨论】:

      【解决方案3】:

      对于所有在 2019 年寻找答案的人 - API 发生了微小的变化。

      import scalaz.zio._
      
      object RTS extends DefaultRuntime
      
      class Service {
        val program: UIO[String] = ???
      
        def mixPureImpure: String = {
          println("Calling service")
          RTS.unsafeRun(program)
        }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-11-09
        • 2021-09-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-13
        • 2011-09-19
        • 2010-10-06
        • 1970-01-01
        • 2011-06-01
        相关资源
        最近更新 更多