转义效果 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。
这两个函数有什么不同吗?
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。