Hi people have you ever encountered this error ``...
# arrow
i
Hi people have you ever encountered this error
Copy code
kotlin.NoWhenBranchMatchedException: null
	at arrow.core.computations.EitherEffect$DefaultImpls.bind(either.kt:20) ~[arrow-core-jvm-1.0.1.jar:?]
I am using the either monad comprehension block and the bind extension function but maybe I am missing something. I am using arrow version 1.0.1 Basically I have few interface with suspended methods, and one interface exposing a method not suspended (and using jooq in the implementation to handle transactions)
Copy code
interface Repository {
  suspend fun getBy(userId: UserId): Either<Error, List<DomainObject>>
  suspend fun update(obj: DomainObject) : Either<ErrorResult, Unit>
}
Copy code
class TransactionMgmt(private val dslContext: DSLContext) {

    fun <T> transaction(
        block: () -> Either<Error, T>
    ): Either<ErrorResult, T> ...
Copy code
interface Observer {

    suspend fun onExpired(obj: DomainObject): Either<ErrorResult, Unit>
}
Copy code
class ExpireUseCase(
    private val repository: Repository,
    private val transactionMgmt: TransactionMgmt,
    private val observer: Observer
) : UseCase<Request, Response> {
    override suspend fun execute(request: Request): Either<Error, Response> =
        repository.getBy(request.userId)
            .flatMap { obj ->
                updateAndNotify(obj)
            }

    private suspend fun updateAndNotify(objs: List<DomainObject>): Either<Error, Response> {
        return objs.fold(initial) { acc, obj ->
            transactionMgmt.transaction {
                runBlocking {
                    expire(obj, acc)
                }
            }
        }
    }

    private suspend fun expire(
        obj: DomainObject,
        acc: Either<Error, Response>
    ): Either<Error, Response> = either {
        val expiredObj = obj.copy(status = EXPIRED)
        repository.update(expiredObj).bind()
        observer.onExpired(expiredObj).bind()
        Response(acc.bind().count + 1)
    }

    private val initial: Either<Error, Response> = Response(0).right()
}
Basically I am getting that error in the method
Copy code
private suspend fun expire(
        obj: DomainObject,
        acc: Either<Error, Response>
    ): Either<Error, Response> = either {
        val expiredObj = obj.copy(status = EXPIRED)
        repository.update(expiredObj).bind()
        observer.onExpired(expiredObj).bind()
        Response(acc.bind().count + 1)
    }
Sorry for the very long post, and maybe I am missing something really stupid but I cannot see it. (this is a similar version of the actual code I am using, I cannot post the original one)
Sorry for this, it was indeed a test problem, I was mocking not in the right way the observer using mockito
what happened was that mockito was not stubbing the mock method because it didn’t got the argument equality, and in that case returned null
sorry for the silly question
r
Hi @itbhp, Looks by your exception that you are passing a
null
value where it would otherwise expect a typed value non nullable of
Left
or
Right
.
bind
is currently defined in the
Either.bind
effect as an exaustive match over the Either data structure.
Copy code
public suspend fun <B> Either<E, B>.bind(): B =
    when (this) {
      is Either.Right -> value
      is Left -> control().shift(this@bind)
    }
if in that case
this
is
null
and incorrectly typed it would not be able to match either of the two cases.
Can’t tell if there is anything causing that to be null but if you can come up with a small repro example on a gist or repo I’ll be happy to look at it.
i
Thanks for your answer, it was mockito returning null instead of Unit.right(), I made a mistake in the test arrangement
👏 1
647 Views