<@U72C3TBDH> Raul is looking into that! I don’t kn...
# arrow
p
@streetsofboston Raul is looking into that! I don’t know if he has a repro yet 😕
s
It is relatively easy to reproduce. Just add
delay(...)
call between two bind()-calls and it will happen.
p
👍🏼
cc @raulraja
s
I’ll add a little reproduction sample to this bug on your github repo
r
I see what is going on here
effect
is not a valid combinator on Either
In fact that BlockingContinuation and effect decalration on MonadSyntax which is causing this issue will go away
The reason why it's failing anyway it's because Either can;t suspend effects
you can;t use the
fx
from Either for this program
You need a data type that is suspend capable, that is, it provides an instance for
MonadDefer
.
The following program should work and
effect
will never be available for the Either
fx
block, only for monad defer.
The same program works if you use the IO fx which is able to suspend as shown below.
Copy code
package arrow.effects.zio

import arrow.core.Either
import arrow.core.extensions.either.applicative.just
import arrow.core.extensions.either.applicative.map
import <http://arrow.effects.IO|arrow.effects.IO>
import arrow.effects.extensions.io.fx.fx
import arrow.effects.extensions.io.unsafeRun.runBlocking
import arrow.unsafe
import kotlinx.coroutines.delay

suspend fun getValue1(): Either<Throwable, Int> {
  delay(100) // <-- Either can't suspend anything because it's an eager data type, so you can't use the `either fx`
  return 5.just()
}

suspend fun getValue2(): Either<Throwable, Int> {
  return 10.just()
}

val program: IO<Either<Throwable, Int>> =
  fx {
    val v1 = !effect { getValue1() }
    val v2 = !effect { getValue2() }
    val result = map(v1, v2) { it.a + it.b }
    !effect { println(result) }
    result
  }

fun main() {
  unsafe { runBlocking { program } } //Right(b=15)
}
s
Thanks @raulraja! I guess the current snapshot allows effects on Eithers and such confused me 🙂 But it is going away, so that can no longer happen 🙂
Question to @pakoito and @raulraja Is there a way for non MonadDefers to use a similar syntax, so that
val result = map(v1, v2) { it.a + it.b }
is not necessary and
val result = !v1 + !v2
is possible, for example?
You could use the EitherT fx but transformers have a heavier allocation cost. Not worth it when you can easily destructure like that.
s
Thank you!
k
It appears not as easy to remove
effect
from MonadSyntax, since BindSyntax defines it and FunctorSyntax derives from BindSyntax. Or am I missing something? 🙁 Would've loved to help out but that's a bit too complex for me 😢
r
No worries, it's part of my own mess and I realized it was more complex than anticipated
But it's fixed now in a PR
Feel free to review if interested