有没有办法在不运行的情况下将内容从 IO 提升到其他容器?

use*_*261 6 scala monad-transformers io-monad scala-cats cats-effect

根据cats官方文档:https : //typelevel.org/cats-effect/typeclasses/liftio.html ,如果我们想把东西从IO提升到其他容器,你应该实现LiftIO trait,但示例明确运行unsafeRunXXX方法来获取出了效果,我想知道这是转型的唯一途径吗?

Mat*_*zok 5

IO 正在暂停副作用,它的类型告诉您如果运行所有计算(包括副作用和纯计算),如果最终没有错误抛出(它们可以沿途处理),您将获得什么值)。

因此,在不运行计算的情况下无法获得该值。所以,基本上任何有用的翻译IO[A],以F[A] 将不得不调用一些.unsafeXXX地方。这unsafe部分并不意味着你不应该使用它 - 这意味着你需要知道你在做什么,因为你运行它的那一刻,返回的结果会产生副作用,可能会失败,通常你会放弃关于参考透明度。

这就是为什么它在内部IOApp使用(它在世界末日使用它,在那里你想要计算你的结果)。如果您知道这一点,您还可以IOF不失去参考透明度的情况下转换为另一个F

  • 很懒,就像IO一样,
  • 允许暂停副作用,就像 IO 一样,
  • 处理错误,就像IO一样。

所以基本上,它是相同概念的另一种实现 - 请参阅:SyncIO, Coeval, Task, ZIO ...

// example: Async can be used to translate IO into F
def IO2F[F[_]: Async]: IO ~> F = new (IO ~> F) {
  def apply[A](ioa: IO[A]): F[A] = Async[F].async(ioa.unsafeRunAsync)
}
Run Code Online (Sandbox Code Playgroud)

您也可以执行类似IO[A] => Either[Throwable, A]or 之类的操作IO[A] => Option[A]IO[A] => Future[A]但是您必须记住,每次运行此类评估时,都会立即产生副作用。

长话短说:如果你想翻译IO成别的东西,你必须在.unsafeXXX某个地方使用一些,这还不错,unsafe只是提醒你必须小心,就是这样。