You can asynchronously define the preceding computation as follows:
def taskLight(prefix: String): IO[Nothing] = Monad[IO].tailRecM(0) { i => for { _ <- IO { println(s"${Thread.currentThread.getName}; $prefix: $i") } _ <- IO.sleep(1 second) } yield Left(i + 1) }
Notice that this method is defined similarly to the previous task. However, we no longer block the thread. Instead, we are using a built-in IO primitive called sleep. sleep is a non-blocking primitive, meaning that it does not block the underlying thread. That is, it is a description of the sleep operation. Remember, all of the computations happening defined in terms of IO are descriptions of computations and not computations themselves. So, you can define a sleep ...