Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to lift content from IO to other container without run?

According to the cats official document: https://typelevel.org/cats-effect/typeclasses/liftio.html, if we want lift something from IO to other container, you should implement LiftIO trait, but the example explicitly run unsafeRunXXX method to fetch out the effect, I'm wondering is it the only way for the transformation?

like image 218
user3593261 Avatar asked Sep 12 '19 00:09

user3593261


1 Answers

IO is suspending side-effects, and its type tells you what value you'll get if you run all computations (both side-effectful and pure), if there will be no error to throw in the end (they can be handled along the way).

As such, it is impossible to obtain the value without running the calculation. So, basically any useful translation from IO[A] to F[A] would have to call some .unsafeXXX somewhere. The unsafe part doesn't mean, that you shouldn't use it - it means that you need to know what you are doing as the moment you run it, the result returned will be side-effecting, can fail and in general you give up on referential transparency.

That it why this it used in internally in IOApp (it uses it at the end of the world, where you want to have your results computed). You can also translate IO into another F without loosing referential transparency, if you know that this F:

  • is lazy, just like IO,
  • allows suspending side-effects, just like IO,
  • handled errors, just like IO.

So basically, it is another implementation of the same concept - see: 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)
}

You could also do things like IO[A] => Either[Throwable, A] or IO[A] => Option[A], or IO[A] => Future[A] but then you have to remember that each time you run such evaluation, you are starting side effects immediately.

Long story short: of you want to translate IO into something else, you have to use some .unsafeXXX somewhere and this is not bad, unsafe is just a reminder that you have to be careful, that's it.

like image 191
Mateusz Kubuszok Avatar answered Oct 21 '22 15:10

Mateusz Kubuszok