Untitled.kt
# arrow
s
Untitled.kt
🔝 2
😍 3
arrow 2
@carbaj0 I’ll continue here.
This also includes how you can compose different algebras like
MainScreen
,
UserRepo
and
AndroidDispatchers
together to have a testable architecture.
But let’s zoom in on the
fx
part, and specifically into the cancelation.
Copy code
fun mainUseCase(screen: MainScreen,
                repo: UserRepo,
                dispatchers: AndroidDispatchers): IO<Unit> = IO.fx {
  continueOn(dispatchers.main())
  !screen.renderEmpty()
  continueOn(dispatchers.default())
  val user = !repo.getUser()
  continueOn(dispatchers.main())
  !screen.renderUser(user)
}
Each line in this
fx
introduces a cancelation point, and this is because we “bind” to each operation. Binding is simply semantically extracting the value, because even if you call this function and get the resulting
IO
nothing happens until you call
unsafeRunXXX
.
So to recap every binding introduces a cancelation boundary: -
val user = repo.getUser().bind()
-
val user = !repo.getUser()
-
val (user) = repo.getUser()
So whenever we run the program with
unsafeRunAsyncCancellable
we get back a
Disposable
which is
typealias Disposable = () -> Unit
. So when we trigger it after 500ms, we call the network request. So upon
!
it will get cancelled.
Copy code
fun mainUseCase(screen: MainScreen,
                repo: UserRepo,
                dispatchers: AndroidDispatchers): IO<Unit> = IO.fx {
  continueOn(dispatchers.main())
  !screen.renderEmpty()
  continueOn(dispatchers.default())
  val user = !repo.getUser()
          <-- Never reached this point due to cancelation
  continueOn(dispatchers.main())
  !screen.renderUser(user)
}
So in Android this means binding
typealias Disposable = () -> Unit
to the lifecycle
Alternatively you can also integrate with kotlinx.coroutines and use the kotlinx lifecycle support.
Copy code
suspend fun <A> IOOf<A>.suspendCancellable(): A = suspendCancellableCoroutine { cont ->
  val disposable = fix().unsafeRunAsyncCancellable { result -> 
    result.fold(cont::tryResumeWithException, cont::tryResume)
  }
  cont.invokeOnCancellation { disposable.invoke() }
}
c
thank you very much, great explanation
As soon as possible, I try to apply it to my problem
👍 1
k
HOLY COW @simon.vergauwen Thanks a lot, this is a code snippet i’ve been looking for ages 😍
🔝 1
👍 1
(not yet at the point i can write it from scratch, but have smth to iterate from)
s
Feel free to ask any questions or share any code you have questions about :)
I'd like to work on Android side of things for Arrow but am currently occupied with other work on Arrow working toward 1.0 by the end of the year.
If anyone is up for working on Android integrations I'm always available for guidance 2.