I'm migrating my pet project from an MTL-based imp...
# arrow
m
I'm migrating my pet project from an MTL-based implementation with Arrow 0.10 to new Arrow 0.11 fx. I had a function that was combining results of two computations:
Copy code
fun <F> Applicative<F>.combine(
    fn1: () -> Kind<F, Any>,
    fn2: () -> Kind<F, Any>
): Kind<F, Any> =
    fn1().map2(fn2) { (a, b) ->
        // do sth with a and b
    }
With Arrow 0.11 I'm trying to pass effectful computations as suspend functions. I'm able to combine them using the
either
companion:
Copy code
suspend fun combine(
    fn1: suspend () -> Either<Throwable, Any>,
    fn2: suspend () -> Either<Throwable, Any>
): Either<F, Any> =
    either {
        val a = !fn1()
        val b = !fn2()
        // do sth with a and b
    }
If I want to execute the effects concurrently with
parMapN
, I'm not able to unwrap
Either
values and work with them:
Copy code
parMapN(fn1, fn2) { a, b ->
        // Compile error: Suspension functions can be called only within coroutine body
        either {
            // same code as in the sequential example
        }
    }
Is there a way to combine
parMapN
with Either comprehensions?
r
Hi @Marcin Gryszko , the Coroutines lib provides parMapN for suspension https://arrow-kt.io/docs/fx/async/#parmapnpartupledn
Is that the one you are using or the one from the Applicative instances?
m
This is the one I'm trying to use. However, the 3rd parameter to
parMapN
is not a
suspend
function:
Copy code
parMapN(fa: suspend () -> A, fb: suspend () -> B, f: (A, B) -> C)
from the package
arrow.fx.coroutines
r
Can you surround all with either and apply the effects inside the suspended args. Sorry on my phone but something like...
either { parMap({ !eitherValue }, ... }
m
Same error:
Copy code
either { 
        parMapN(fn1, fn2) { a, b -> 
            val aUnwrapped = !a // Compile error: Suspension functions can be called only within coroutine body
        }
    }
Would it make sense to add a
parMap
variant accepting a
suspend
combining function:
Copy code
parMapN(fa: suspend () -> A, fb: suspend () -> B, suspend f: (A, B) -> C)
r
I ment applying either in the captured lambdas you pass to parMap before the final function, but yes maybe it makes sense to make the final function suspend in there
I can't think of a reason why that last function is not already suspend.