Intro to Eithers in Android
Tags: android, kotlin, either, fore
Published: 2022-06-09 09:06:19

It's not often you come across **Either**s in android code, which I think is a shame given how awesome they are. _(We've been using Eithers to chain networking results and handle errors in [fore](https://erdo.github.io/android-fore/) since late 2019)_.

The thing is, they are a little... weird.

I think we all instinctively understand what an Either is: it's a single type that represents either **thing A** or **thing B**; never both; never neither.

Nothing in that description talks about **errors** or **successes**, so, many implementations use the more generically applicable names: **Left** and **Right**. And by convention (if we are dealing with success / error data) Left is used for the error case, and Right is used for the success case (it's the "right" answer after all).

``` kotlin
Either.left(ERROR_NETWORK)
```

bit weird.

One of the most famous implementations of Either is from the [Arrow-Core library](https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/). For a while, they were using the names "a" and "b" (they use "value" now) to represent the data contained by the Left and Right either respectively, so we had this:

``` kotlin
when(either){
    is Either.Left -> either.a // bad stuff
    is Either.Right -> either.b // good stuff
}
```

still weird.

Don't get me wrong, if Eithers are your bread and butter, this is normal stuff that fades into the background. _Why would anyone put the success on the Left anyway???_

Despite that though, I've found that Either's very slight weirdness (and the requirement that you need to remember that Left holds the error case) is enough to put non-functional developers off using them.

Which is a shame.

---

## A less weird Either 

There is nothing special about the words Left and Right, those words are only generic terms if you happen to _not_ be developing a driving app for instance (where the words Left and Right would have a special significance). In fore (and probably in most cases) the Eithers are exclusively dealing with success / error data. And that's why fore changed its Either implementation to this instead (feel free to copy paste into your own project):

``` kotlin
sealed class Either<out F, out S> {

  data class Fail<out F> internal constructor(val value: F) : Either<F, Nothing>() {
    companion object {
      operator fun <F> invoke(f: F): Either<F, Nothing> = Fail(f)
    }
  }

  data class Success<out S> internal constructor(val value: S) : Either<Nothing, S>() {
    companion object {
      operator fun <S> invoke(s: S): Either<Nothing, S> = Success(s)
    }
  }
  
  companion object {
    fun <S> success(value: S): Either<Nothing, S> = Success(value)
    fun <F> fail(value: F): Either<F, Nothing> = Fail(value)
  }
}
```

So now we can make them like this

``` kotlin
success(serviceResponse)

/** or **/

fail(ERROR_NETWORK)
```
 and use them like this

``` kotlin
when(either){
    is Fail -> either.value // sad face
    is Success -> either.value // happy face
}
```
or with auto-complete

![coding autocomplete gif, pressing alt enter from a when will give you the option to automatically complete the Success and Fail branches](https://media2.giphy.com/media/zD4TPkguJsYoyBGg8g/giphy.gif?cid=790b76112aa9b76600d2092a68c9eea76275314c0bb37096&rid=giphy.gif&ct=g)
less weird.

## Fail or Error

Why did we use **Fail** instead of **Error**? Because every time you type **Error** in your IDE when writing kotlin, you will immediately be referencing:

``` kotlin
public actual typealias Error = java.lang.Error
```

Which is not what you want. **Fail** doesn't have this problem.


## Converting Eithers

Just in case you wanted some other kind of Either (like the one from Arrow) it's very easy to convert between eithers:

``` kotlin
fun <F, S> Either<F, S>.toArrow(): arrow.core.Either<F, S> {
    return when(this){
        is Fail ->  arrow.core.Either.left(this.value)
        is Success -> arrow.core.Either.right(this.value)
    }
}

/** which can be used like this **/

val arrowEither = foreEither.toArrow()

```

---

## So you said Eithers were good?

That's probably a whole article in itself. But as long as you set them up properly, they can help you handle error conditions in such a way that the compiler will notice if you don't do it. That's why fore uses them in the networking CallWrapper classes.

The reason I absolutely love them though, is that they are so easy to chain together. With this little extension function we get some pretty amazing wins:

``` kotlin
suspend fun <E, S, S2> Either<E, S>.carryOn(
        nextBlock: suspend (S) -> Either<E, S2>
): Either<E, S2> {
    return when (this) {
        is Either.Fail -> this
        is Either.Success -> nextBlock(value)
    }
}
```

What that does is to call the nextBlock() whenever the either is a Success (thus continuing the flow of code) or just return the either if it was a Fail. If you were pedantic enough, you might call that function **carryOnIfThatLastOperationWasASuccess()**. It lets us write things like this:

``` kotlin
val response = createUserUseCase()
  .carryOn { user ->
    createUserTicketUseCase(user.userId)
  }.carryOn { ticket ->
    ticketRef = ticket.ticketRef
    getEstimatedWaitingTimeUseCase(it.ticketRef)
  }.carryOn { minutesWait ->
    if (minutesWait > 10) {
        cancelTicketUseCase(ticketRef)
    } else {
        confirmTicketUseCase(ticketRef)
    }
  }.carryOn {
    claimFreeGiftUseCase(ticketRef)
  }

when (response) {
    is Fail -> handleFailure(response.value)
    is Success -> handleSuccess(response.value)
}
```

If all those useCases return Eithers, we basically have:
- no callback hell
- highly dense business logic
- complete confidence that errors are being handled

You can see this technique being used to create a weather report by calling separate wind speed, pollen level, and temperature services in this [clean modules sample app](https://github.com/erdo/clean-modules-sample/blob/810a688b32cd2e32f2e0c8680e7cdc8cbd693c63/app/domain/src/main/java/foo/bar/clean/domain/weather/WeatherModel.kt#L94-L115)

---

I'd highly encourage you to give Eithers a go if you haven't already, you might be pleasantly surprised! Check the Arrow link at the top if you want to dig deeper. Also check out [fore](https://github.com/erdo/android-fore) :) it's meant to make things like this very easy and concise. Thanks for reading!