Youssef Shoaib [MOD]
12/10/2025, 4:57 AMfun foo(): Either<Nothing?, Int> = accumulate(::either) {
accumulate(null)
return@foo 42.right()
}
This results in Right(42), while the similar:
fun foo() = accumulate(::either) {
accumulate(null)
42
}
results in Left(null)
Should this be the behaviour? The same behaviour happens with raise as well:
fun foo() = either {
accumulate {
accumulate(null)
this@either.raise(42)
}
}Alejandro Serrano.Mena
12/10/2025, 8:14 AM42.right() (and not just 42 shows that even the types are differentYoussef Shoaib [MOD]
12/10/2025, 8:28 AM.right() isn't required either:
context(_: Raise<NonEmptyList<Unit>>)
fun foo(): Int {
accumulate {
accumulate(Unit)
return 42
}
}
// vs
context(_: Raise<NonEmptyList<Unit>>)
fun foo(): Int {
return accumulate {
accumulate(Unit)
42
}
}
It should probably be documented that non-local return from accumulate behaves differently from returning normally.
After some thought, this might not be as unintuitive as I initially thought. My intuition was viewing accumulate raising any accumulated errors as a finally action of sorts, but perhaps that's not what a user immediately thinks.
My (mostly mental) attempts at changing this behaviour have failed. We'd need to somehow differentiate between the Raise<NonEmptyList<Error>> that we're `accumulate`ing into, vs any outer Raise. It's likely possible using an intermediary withError or something like that.