With `effectfulProgram: IO<E, A>` I could do...
# arrow
j
With
effectfulProgram: IO<E, A>
I could do
effectfulProgram.unsafeRunSync()
to run the program from a none suspended context. (For example an endpoint in a framework without coroutines.) Now I am trying out the new Arrow Fx Coroutines lib and transformed my program to
effectfulProgram: suspend () Either<E, A>
. How do I run it? 😅
a
IIRC there was a runBlocking function on kotlin coroutines with the same funcionality
s
Kotlin offers no such functionality, it’s exposed in a different library by Jetbrains called KotlinX Coroutines @AdrianRaFo.
I hope you liked working with it so far!
j
Yesterday eve I could only get the startCoroutine approach to work with a hacky Continuation implementation. That was basically the point where I was wondering if such an approach is the best approach. I was also starting to wonder if using the KotlinX Coroutines lib coroutine builders for the use case I described would be a valid approach. (I don’t like the idea of mixing Arrow Fx Coroutines and KotlinX Coroutines.) Or that I could potentially use IO to run the program. As last step wrap the suspend program in an IO and run the IO unsafe. (But I am not sure if mixing the two is a good idea (or even needed...).) I’ll give the startCoroutine approach another shot. The Environment prototype looks clean by the way! 😃 I do like the simplified API of Arrow Fx Coroutines. And the transition between IO and suspend is quite smooth because the API’s are similar. One thing that is less elegant is that I need to wrap the program in an Either.catch (because it might throw an exception), while before it would be implicitly be handled in the IO and I could make use of functions like redeemWith to handle all cases.
Had some time to try out
startCoroutine
once more.
Copy code
fun main(): Unit {
    val ctx: CoroutineContext = ComputationPool
    suspend { program() }.startCoroutine(Continuation(ctx) { r -> println(r) })
}
This does not run my program. What am I missing? (Or did I find a bug? 🤭)
s
It jumps async and immediately, and exits the JVM.
unsafeRunSync
still exists but it’s
internal
atm, the difference with
runBlocking
is that it doesn’t start an
EventLoop
on the current
Thread
, but uses a simple
Reantrant
lock. https://github.com/arrow-kt/arrow-fx/blob/master/arrow-fx-coroutines/src/main/kotlin/arrow/fx/coroutines/Platform.kt#L128
You can however just do
suspend main(): Unit = program()
One thing that is less elegant is that I need to wrap the program in an Either.catch (because it might throw an exception), while before it would be implicitly be handled in the IO and I could make use of functions like redeemWith to handle all cases
There is actually no difference between
IO
and
suspend
if you use Arrow Fx Coroutines. Since all it’s operators are lazy like
IO
, you can install
Either.catch
at any time in your program just like you can call
attempt
or
redeemWith
at any point in time. So
val io2 = io.redeemWith(recover, map)
becomes
val value = Either.catch { io() }.fold(recover, map)
.
Thanks for the feedback @Joram Visser! I’ll try to make time for the
Enviroment
PR next week and I’ll share it here in the channel 😉
j
I know that in this case I could make the main suspended. But the point of my example is that I want to be able to run a program from a none suspended context (because some (Java) frameworks do not support coroutines). I am looking forward to your PR. 😀
Thanks for pointing out the async nature of the startCoroutine functions. They do work for my use case. 😄
👍 1