I'm trying to understand asynchronous computation by cats.effect.IO
examples and got some misunderstanding. The unsafe
method unsafeRunAsync
seems like running the underlying effect asynchronously (I expected that some ContextShift
to be provided). But the method looks simply like this:
final def unsafeRunAsync(cb: Either[Throwable, A] => Unit): Unit =
IORunLoop.start(this, cb)
Neither ContextShift
nor ExecutionContext
is provided. Here is the very simple example:
object TestIo extends App {
println(s"Main thread = ${Thread.currentThread().getName}")
val io = IO {
println(s"Effect thread = ${Thread.currentThread().getName}")
Thread.sleep(1000)
}
io.unsafeRunAsync(_ => println(s"Callback thread = ${Thread.currentThread().getName}"))
println(s"Finished")
}
The output is
Main thread = main
Effect thread = main
Callback thread = main
Finished
As you can see everything here is run in the main thread synchronously. Can you please explain unsafeRunAsync
? To me it seems the same as unsafeRunSync
.
The I/O monad contains primitives which build composite actions, a process similar to joining statements in sequential order using `;' in other languages. Thus the monad serves as the glue which binds together the actions in a program.
A monad is an algebraic structure in category theory, and in Haskell it is used to describe computations as sequences of steps, and to handle side effects such as state and IO. Monads are abstract, and they have many useful concrete instances. Monads provide a way to structure a program.
The IO monad provides a straightforward way of embedding imperative programming with I/O effects in a pure program while preserving referential transparency. It clearly separates effectful code—code that needs to have some effect on the outside world—from the rest of our program.
IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.
About
Neither ContextShift nor ExecutionContext is provided.
There is a context switch in cats.effect.IO
See this blog: https://www.jaspervanzandbeek.com/scala/cats-io-monad/
Here an example from there:
def blockingOperation(): String = {
// Read from file
...
}
val result: IO[String] = for {
_ <- IO.shift(executionContextForBlockingOperations)
result <- IO { blockingOperation() }
_ <- IO.shift(mainExecutionContext)
} yield result
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With