根据cats官方文档:https://typelevel.org/cats-effect/typeclasses/liftio.html,如果我们想将某物从IO提升到其他容器,则应实现LiftIO特性,但是该示例显式运行unsafeRunXXX
方法来获取效果,我想知道这是转换的唯一方法吗?
答案 0 :(得分:3)
IO
正在挂起副作用,并且其类型告诉您如果运行所有计算(包括副作用和纯计算)将获得什么值,如果最终没有错误的话(它们可以一路处理)。
这样,如果不运行计算就无法获得该值。因此,从IO[A]
到F[A]
的任何有用翻译基本上都必须在某个地方调用一些.unsafeXXX
。 unsafe
部分并不意味着您不应该使用它-这意味着您需要知道自己在做什么,在您运行它的那一刻,返回的结果将是副作用,可能会失败,并且通常您会放弃参照透明性。
这就是为什么它在IOApp
内部使用的原因(它在世界的尽头使用,您想在其中计算结果)。如果您知道IO
,也可以将F
转换为另一个F
,而不会失去参照的透明度:
因此,基本上,这是同一概念的另一种实现-参见: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)
}
您还可以执行诸如IO[A] => Either[Throwable, A]
或IO[A] => Option[A]
或IO[A] => Future[A]
之类的操作,但是您必须记住,每次进行此类评估时,都会立即开始产生副作用。
长话短说:要想将IO
转换为其他内容,必须在某个地方使用.unsafeXXX
,这还不错,unsafe
只是在提醒您要小心,就是这样。