转义效果 Monad 与不转义

escaping effect Monad vs. not escaping

这两个函数有什么不同吗?

case class DFStorage(private var cache: Map[String, DataFrame] = Map()) {

  def tryLoad(job: Job): Kleisli[IO, MakeContext, \/[List[String], Unit]] = {
    if(!cache.contains(job.id)) {
      job.tryLoad.map(_.map(df => add(job, df)))
    } else {
      IO(().right[List[String]]).liftKleisli
    }
  }


  def tryLoad(job: Job): Kleisli[IO, MakeContext, \/[List[String], Unit]] = {
    Kleisli({makeContext: MakeContext =>
      if(!cache.contains(job.id)) {
        IO {
          job.tryLoad.run(makeContext).unsafePerformIO().map(df => add(job, df))
        }
      } else {
        IO(().right[List[String]])
      }
    })
  }
}

我认为你应该调用 unsafePerformIO 作为程序中的 final 副作用(例如在你的主函数中),但在这种情况下它可能会导致同样,假设您是 "unwrapping" IO monad 中的值,然后包装该值的转换。如您所见,值的展开和转换可能与 IO.map 执行的过程相同。

unsafePerformIO用于强制执行IO值所代表的副作用。在 Haskell 中,您的程序必须是 IO 类型的东西并且 Haskell 运行它(main 必须是 IO 类型)。但是在 Scala 中,main 函数可以做任何事情,所以你必须在那个时候执行 IO。