In Cats-effect, when is xxx inside IO.pure(xxx) executed?

It’s said IO.pure() means eager evaluation. But it doesn’t seem to so in this example:

object TryPure1 extends App {

  def printTwice(): IO[Unit] =
    IO.apply(println("print in lazy")).flatMap(_ => IO.pure(println("print in pure")))

   val io = printTwice() //no output
   io.unsafeRunSync() //output:
                                      //print in lazy
                                     //print in pure                               
}

Here println("print in pure") is executed just like as if it’s IO.apply()

Another example, however, discloses the truth

object TryPure2 extends App{

  def printTwice(): IO[Unit] =
    IO.apply(println("print in lazy")) *> IO.pure(println("print in pure"))

  printTwice()  //output: print in pure
}

Here is it how it works:

  • When printTwice() is called, every expression inside it is evaluated
  • IO.apply(println("print in lazy")) is evaluated as an IO, without the println() executed because this IO is an lazy IO
    • The laziness is implemented by “using a by-name parameter as a property of a case class”
  • IO.pure(println("print in pure")) is also evaluated as an IO, and the println() inside it is executed right away, because this IO is an eager IO
  • If you then run unsafeRunSync() on this combined IO, then you will see "print in lazy" because now expressions in lazy IOs are evaluated
    • There won’t be another "print in pure" because of memory – the value has been evaluated when calling printTwice()

So when is xxx inside IO.pure(xxx) executed? It’s executed when IO is constructed using IO.pure() , and it’s before this IO really runs

Now go back to the first code example. Why is the println inside IO.pure() not executed ?

The answer is IO.flatMap() is also lazy (“using a by-name parameter as a property of a case class”, if you read cats-effect code) . So,

  • Calling printTwice() will not lead to the running of IO.pure(), let alone println inside IO.pure()
  • io.unsafeRunSync() will print "lazy" first then "pure", because f in flatMap() has to wait until the first IO has an evaluated value. (You need to read cats-effect code for the details)

Leave a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.