Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

132
Views
How to use Either monad and avoid nested flatMap

I'm in a situation where I'm trying to setup some data and then call a service. Each step can fail, so I'm trying to use Arrow's Either to manage this.

But I'm ending up with a lot of nested flatMaps.

The following code snippet illustrates what I'm trying to do:

import arrow.core.Either
import arrow.core.flatMap

typealias ErrorResponse = String
typealias SuccessResponse = String

data class Foo(val userId: Int, val orderId: Int, val otherField: String)
data class User(val userId: Int, val username: String)
data class Order(val orderId: Int, val otherField: String)

interface MyService {
    fun doSomething(foo: Foo, user: User, order: Order): Either<ErrorResponse, SuccessResponse> {
        return Either.Right("ok")
    }
}

fun parseJson(raw: String): Either<ErrorResponse, Foo> = TODO()
fun lookupUser(userId: Int): Either<ErrorResponse, User> = TODO()
fun lookupOrder(orderId: Int): Either<ErrorResponse, Order> = TODO()

fun start(rawData: String, myService: MyService): Either<ErrorResponse, SuccessResponse> {
    val foo = parseJson(rawData)
    val user = foo.flatMap {
        lookupUser(it.userId)
    }
    //I want to lookupOrder only when foo and lookupUser are successful
    val order = user.flatMap {
        foo.flatMap { lookupOrder(it.orderId) }
    }
    //Only when all 3 are successful, call the service
    return foo.flatMap { f ->
        user.flatMap { u ->
            order.flatMap { o ->
                myService.doSomething(f, u, o)
            }
        }
    }
}

I'm sure there is a better way to do this. Can someone help me with an idiomatic approach?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

You can use the either { } DSL, this is available in a suspend manner or in a non-suspend manner through the either.eager { } builder.

That way you can use suspend fun <E, A> Either<E, A>.bind(): A.

Rewriting your code example:

fun start(rawData: String, myService: MyService): Either<ErrorResponse, SuccessResponse> =
  either.eager {
    val foo = parseJson(rawData).bind()
    val user =  lookupUser(foo.userId).bind()
    val order = lookupOrder(foo.orderId).bind()
    myService.doSomething(foo, user, order).bind()
  }

If you run into an Either.Left, then bind() will short-circuit the either.eager block and return with the encountered Either.Left value.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!