stojan
05/09/2020, 8:55 AMval callWithTimeout: IO<Model> = IO.raceN(
IO.effect { service.getModel() },
IO.sleep(2.seconds)
)
right?Nico
05/09/2020, 6:58 PMHiosdra
05/09/2020, 10:28 PMstojan
05/10/2020, 8:47 AMfx
block I can use continueOn
with <http://dispatchers.io|dispatchers.io>()
but also <http://Dispatchers.IO|Dispatchers.IO>
or I can mix is there a preferred way? is there any difference between the two? (I am also using the coroutines integration to run the IO)
IO.fx {
effect { _viewState.postValue(ViewState.Loading) }.bind()
continueOn(dispatchers().io()) // dispatchers from IO
val repositoryDto: RepositoryDto = effect { service.getRepository() }.bind()
continueOn(Dispatchers.Default) // Dispatchers from Coroutines
ViewState.Content(repositoryDto)
}
stojan
05/10/2020, 8:54 AMval backgroundTask = IO.fx {
effect { Timber.d("starting sleep...") }.bind()
sleep(10.seconds).bind()
effect { Timber.d("sleep ended...") }.bind()
raiseError<Unit>(Throwable("Bang!!")).bind()
}
IO.fx {
effect { _viewState.postValue(ViewState.Loading) }.bind()
continueOn(Dispatchers.Default)
backgroundTask.fork().bind()
ViewState.Content(GithubService.model) // show static data
}
.handleError { ViewState.Error(it.errorMessage()) }
.flatMap { IO.effect { _viewState.postValue(it) } }
.unsafeRunScoped(viewModelScope) { }
if my ViewModel
gets destroyed here, the backgroundTask
continues executing (as expected). However after is done, the error is swallowed. Is that the expected behavior? 🤔stojan
05/10/2020, 7:26 PMDennis Tel
05/11/2020, 12:11 PMEgor Trutenko
05/12/2020, 11:31 AMkluck
05/13/2020, 8:01 AMfun <T, E> IO<T>.setState(handleError: (Throwable) -> E, onSuccess: (T) -> IO<Any>) = IO.fx {
val state = !this@setState.attempt()
state.fold(
{ handleError(it) },
{
// Other stuff happening…
!onSuccess(it)
}
)
}
@Test
fun test() {
val handleError = { t: Throwable -> println("Error: ${t.message}") }
val onSuccess = { bool: Boolean ->
IO.fx {
println("Starting")
!effect { delay(5000) } // --> SwitchMapping should happen around here
println("Finished with value $bool")
}
}
// Here, this is what I don't know how to "Observablify" to send multiple events
IO.just(true).setState(handleError, onSuccess).unsafeRunAsync {}
IO.just(false).setState(handleError, onSuccess).unsafeRunSync()
}
What I expect is:
Starting
Starting
Finished with value false // The other one should be "switchMapped"
I don't know how to have some kind of flow or observable with arrow, and I don't know how to switch map within it. Any guidance?than_
05/13/2020, 8:54 AMListK<MapK<String,ListK<String>>>
(don't ask 😄 ) and I need to populate it by folding some stream of data. To preserve my sanity I'd like to use optics. Basically what i need to do is to append elements to the inner lists. How would I go about doing that?kobby
05/13/2020, 8:59 AMCannot access Arrow.Kind which is a supertype of arrow.core.Either.Right
I'm using arrow-core 0.10.5, arrow-core-data 0.10.5, arrow-effects-data 0.9.0kobby
05/13/2020, 9:30 AMEither (found in arrow.core)
this way when people read the documentation and want to try out stuff they know what to import?renghen pajanilingum
05/14/2020, 6:38 PMrenghen pajanilingum
05/14/2020, 6:38 PMsuspend fun parse(str: String): Either<String, Int> =
Either.catch { str.toInt() }.mapLeft { "wrong string value" }
raulraja
05/15/2020, 7:55 PMSaša Šijak
05/16/2020, 4:45 AMIO.unsafeRunSync
has this in the comment above it
* **NOTE** this function is intended for testing, it should never appear in your mainline production code!
Why is that. How would you implement the case where in a typical web app I have the following:
api request -> http handler triggered -> it calls the service method -> service method calls DB service
And I want to wrap the call to the DB service in the equivalent of
Try {
//db call here
}.toEither {
//handle db errors
}
I want to use Either early and at the boundary of my core logic, so I can model my function returns and errors as I want and translate exceptions to my errors. Also I am not running in the coroutine context. For example, stack is http4k, jooqgeorg
05/17/2020, 5:06 PMKind<F, A>
and I want a function that turns it into Kind<G, A>
. Or even to Kind<G, B>
Maciek
05/18/2020, 6:04 AMRestricted suspending functions can only invoke member or extension suspending functions on their restricted coroutine scope
when trying to run suspending function inside Option.fx {}
lambda. Option itself is also in suspending function. Can't really wrap my head around why compiler doesn't allow me to run my suspending function in Option.fx {}
suspending lambdaraulraja
05/18/2020, 2:54 PMjulian
05/18/2020, 8:05 PM<ERROR CLASS>
in the docs mean? Is it a glitch in the docs generation? For example:
tailrec fun <L, A, B> tailRecM(a: A, f: (A) -> Kind<<ERROR CLASS><L>, Either<A, B>>): Either<L, B>
simon.vergauwen
05/19/2020, 8:48 AMUnion
. You can compose 2 errors together, without having to create a new ADT that wraps the errors.Satyam Agarwal
05/20/2020, 10:37 AMfun NonFatal(t: Throwable): Boolean =
when (t) {
is VirtualMachineError, is ThreadDeath, is InterruptedException, is LinkageError -> false
else -> true
}
pakoito
05/22/2020, 2:07 PMSatyam Agarwal
05/23/2020, 5:53 PMtim
05/24/2020, 1:18 PMstojan
05/25/2020, 6:19 PMUserServiceAlgerbra
for working with users.... If I use suspend
for my methods (instead of IO
), what would be the equivalent of raiseError
in case of duplicate users for suspend fun createUser(user: User): Unit
?CLOVIS
05/25/2020, 6:36 PMComparator
and similar behavior interfaces (which are called ‘Type classes'? Please correct me if I'm wrong).
It would also allow to implement a behavior in different ways, and choose which behavior is used when calling a function (with an explicit with
parameter), which makes dependency injection trivial (possibility to implement patterns such as DAO with some nice syntax sugar).carbaj0
05/26/2020, 9:49 AMej : data class PersonalDataModel(
val firstName: Option<String>
)
firstName.modify(state){ //here i have a String instead of Option<String> }
tim
05/26/2020, 8:57 PMfun doWorkWithIO() {
val time = measureTime {
IO.fx {
val effects = mutableListOf<Kind<ForIO, Int>>()
for (i in 0..1_000_000) {
val thing = effect { i }
effects.add(thing)
}
effects.forEach { it.bind() }
}.unsafeRunSync()
}
println("Default IO took $time")
}
fun doWorkWithFork() {
val time = measureTime {
IO.fx {
val effects = mutableListOf<Fiber<ForIO, Int>>()
for (i in 0..1_000_000) {
val thing = effect { i }.fork().bind()
effects.add(thing)
}
effects.forEach { it.join() }
}.unsafeRunSync()
}
println("Fibers took $time")
}
doWorkWithIO
completes in about 1 second and doWorkWithFork
runs in about 3 seconds. Are fibers using coroutines under the hood or threads? If so, whats the difference between them and effect? I assume they're for different things otherwise the wouldn't exist 🤷♂️ Is my code completely wrong!?Bob Glamm
05/26/2020, 9:28 PMdoWorkWithFork
takes longer purely due to the overhead of launching suspend functions into coroutines. If your effect body does something computationally intensive or takes time - a simple example is to delay 5 seconds - then you should see doWorkWithIO
take more total time than doWorkWithFork
. (Change the upper limit to 10 or 20 instead of 1,000,000 if using a five-second delay.)Bob Glamm
05/26/2020, 9:28 PMdoWorkWithFork
takes longer purely due to the overhead of launching suspend functions into coroutines. If your effect body does something computationally intensive or takes time - a simple example is to delay 5 seconds - then you should see doWorkWithIO
take more total time than doWorkWithFork
. (Change the upper limit to 10 or 20 instead of 1,000,000 if using a five-second delay.)tim
05/26/2020, 9:38 PM