在考虑错误并将IO[E, T]
转换为IO[Nothing, T]
后,我们可以直接将该值称为T
类型而不是IO[Nothing, T]
。这允许我们返回T
类型的值,而不需要使用var
和IO.map
。有没有办法做到这一点,如果没有,为什么不呢?
目前在ZIO的README中找不到解决方案。
IO[E, T]
只是一个程序的描述,可以返回错误E
或产生值T
。
要实际生成此值,您需要运行此程序。
ZIO设计鼓励将不纯的副作用推到程序的最边缘,即main
函数。事实上,你不需要在你的代码中的任何地方显式调用unsafeRun
,因为ZIO的App
特性可以为你解决这个问题。
话虽这么说,如果你仍然需要这样做,比如因为你还没准备好重构你的整个应用程序,你可以使用RTS
特性(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。
没有办法实现一个接受IO[Nothing, T]
并返回T
的纯函数。
之所以如此,是因为ZIO的IO[_, _]
的第一个类型参数描述了在IO
包装计算中可能发生的错误。 IO[Nothing, T]
描述了一个不会失败的计算,但它仍然封装了一个有效的计算。这就是为什么你不能在纯函数中得到T
之类的值。
刚谈到物理可能性,因为Scala不是纯语言,你有可能编写一个接受IO[Nothing, T]
并返回T
的函数,但你真的不鼓励通过ZIO的设计和意识形态来做到这一点。
对于所有在2019年寻找答案的人来说 - API的变化很小。
import scalaz.zio._
object RTS extends DefaultRuntime
class Service {
val program: UIO[String] = ???
def mixPureImpure: String = {
println("Calling service")
RTS.unsafeRun(program)
}
}