## TLDR

```
Either is either Left or Right with values inside.
Either is a union type.
It's a concept that is language agnostic.
It's right biased.
Left is used to transport/represent errors.
Right is used to transport/represent the successful data.
=flatMap= and =map= are used to chain them together.
bind is sugar over =flatMap= and =map= to make the code more sequential and easier to read.
It short circuits if it gets a Left.
Vavr for Java (no bind here).
Arrow for Kotlin (here you have bind).
```

## Introduction

Errors and exceptions in applications can be hard to handle and be aware of. Java tries to solve this with checked exceptions. Kotlin doesn't have checked exceptions so the compiler won't help or guide you.

One way of solving this is to represent errors and exceptions in a union type.
There are a couple of different data types, one is Kotlin's built in Result.
`Result`

is a union type that can be of type A or Throwable. `Either`

is a bit
more general than `Result`

and have `Left<A>`

and `Right<B>`

. `Left`

and
`Right`

can contain any data type. By convention is `Left`

used for error.

When a function returns a union type like `Either`

. The compiler will make you
aware of it and can guide you to handle both of the cases, `Left`

and `Right`

.

## Exceptions

Here is a small application that does 4 calculations. Each calculation is simulated to be executed on a different server, so the request could fail and throw an error.

This is pretty standard approach and often seen. In this case it's a small example so we can easily handle the exception. But if you forget the try/catch here you could end up in problem. Exceptions bring with them non-local jumps, which can make it hard to understand the flow of our code if you don't catch them locally.

```
import java.io.IOException
// Simulates an external call to server
fun <A> runOnServer(f: () -> A): A =
if (Math.random() > 0.2) f()
else throw IOException("boom!")
fun addition(a: Int, b: Int): Int = runOnServer { a + b }
fun subtraction(a: Int, b: Int): Int = runOnServer { a - b }
fun multiplication(a: Int, b: Int): Int = runOnServer { a * b }
fun division(a: Int, b: Int): Int = runOnServer { a / b }
fun main(){
try {
val additionResult = addition(10, 10)
val subtractionResult = subtraction(additionResult, 10)
val multiplicationResult = multiplication(subtractionResult, 10)
val divisionResult = division(multiplicationResult, 10)
println(divisionResult)
} catch (e: Exception) {
println("Error: ${e.message}")
}
}
```

`Error: boom!`

A function name could imply that it could throw an exception. For example
`getPlayer(playerId)`

hints that it will make I/O. But to be sure you need to
look inside. This could be a disturbance and harms the purpose of an
abstraction.

By only looking at the function names in this example it's easy to reason that
only `division`

could throw an `ArithmeticException`

. But you need to look in
the definitions to be sure.

If the functions in this example instead returned `Either<Error, Int>`

it
would be very clear that an error could occur.

## Railway programming

For this union types there are very general patterns and we can create simple functions that chain the functions together and short circuits if an error occurs. This is sometimes refereed to as railway programming.

In this railroad track you have 3 steps that needs to be executed in sequence. Each one of them can fail and if so it will short circuits and exit. So if Validate fails, UpdateDB and SendEmail won't be executed. But if Validate succeeds, it will go on to UpdateDb.

We arrive at Validate. If we get an `Either.Right`

we continue to UpdateDB. If
we get an `Either.Left`

we short circuit and exit.

## flatMap, map and fold

There are 3 essential functions when working with railway programming and
`Either`

; `flatMap`

, `map`

and `fold`

. Let's look at the implementations, they
are super simple and you will see them or slight variations in different
implementations of `Either`

.

### flatMap

If we get an `Either.Right`

we unpack the value and apply function `f`

to it.
If we get an `Either.Left`

we should just pass it on. This is the short
circuit mechanism. Just like in the railroad diagrams.

```
public inline fun <A, B, C> Either<A, B>.flatMap(f: (B) -> Either<A, C>): Either<A, C> =
when (this) {
is Right -> f(this.value)
is Left -> this
}
```

### map

Is defined in terms of `flatMap`

and only wraps the return from `flatMap`

in
an `Either.Right`

.

```
public inline fun <C> map(f: (B) -> C): Either<A, C> =
flatMap { Right(f(it)) }
```

### fold

If we get a `Either.Right`

, run `ifRight`

on its value, if we get an
`Either.Left`

, run `ifLeft`

on its value. You don't need to end a chain with
`fold`

, there are a lot of other operators depending on the use case.

```
public inline fun <C> fold(ifLeft: (A) -> C, ifRight: (B) -> C): C =
when (this) {
is Right -> ifRight(value)
is Left -> ifLeft(value)
}
```

## Either in Vavr

Let's put it all together.

We have the same 4 calculations, but we also have a `trap`

function and an
`Error`

data class. Each calculation is surrounded in `trap`

, so if
`runOnServer`

throws an exception the exception will be captured in the
`Error`

object together with a string and contained in a `Either.Left`

. If
everything is successful we get the calculated value in a `Either.Right`

.

```
import io.vavr.control.Either
import java.io.IOException
// A data class that holds data about the error
data class Error(val errorString: String, val exception: Exception)
// Simulates an operation that can go wrong
fun <A> runOnServer(f: () -> A): A =
if (Math.random() > 0.2) f()
else throw IOException("boom!")
// Wrap in Either.Left if exception, else in Either.Right
fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
try { Either.right(f()) }
catch (e: Exception) { Either.left(Error(errorString, e)) }
fun addition(a: Int, b: Int): Either<Error, Int> =
trap("Addition failed") { runOnServer { a + b } }
fun subtraction(a: Int, b: Int): Either<Error, Int> =
trap("Subtraction failed") { runOnServer { a - b } }
fun multiplication(a: Int, b: Int): Either<Error, Int> =
trap("Multiplication failed") { runOnServer { a * b } }
fun division(a: Int, b: Int): Either<Error, Int> =
trap("Division failed") { runOnServer { a / b } }
fun main() {
addition(10, 10)
.flatMap { additionResult ->
subtraction(additionResult, 10)
.flatMap { subtractionResult ->
multiplication(subtractionResult, 10)
.flatMap { multiplicationResult ->
division(multiplicationResult, 10)
.map { divisionResult ->
divisionResult
}
}
}
}
.fold(
{
// This is what we do if we get an Either.Left / Error
println(it)
},
{
// This is what we do if we get an Either.Right
println(it)
}
)
}
```

`Error(errorString=Division failed, exception=java.io.IOException: boom!)`

The code could be represented in a railway diagram. If `addition`

returns a
`Right<Int>`

we continue to `subtraction`

with the value inside `Right<Int>`

,
if `addition`

fails it circuit breaks and returns a `Left<Error>`

containing
the error. It follow the same pattern all the way down. And returns a
`Right<Int>`

or a `Left<Error>`

.

## Either in Arrow

Vavr is aimed for Java and there is another implementation of Either aim for Kotlin in a lib called Arrow.

Here we replace the `Either`

implementation from Vavr to Arrow. The code looks
more or less the same. It's the same pattern with `flatMap`

, `map`

and `fold`

.

```
import arrow.core.Either
import arrow.core.flatMap
import java.io.IOException
// A data class that holds data about the error
data class Error(val errorString: String, val exception: Exception)
// Simulates an operation that can go wrong
fun <A> runOnServer(f: () -> A): A =
if (Math.random() > 0.2) f()
else throw IOException("boom!")
// Wrap in Either.Left if exception, else in Either.Right
fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
try { Either.Right(f()) } catch (e: Exception) { Either.Left(Error(errorString, e)) }
fun addition(a: Int, b: Int): Either<Error, Int> =
trap("Addition failed") { runOnServer { a + b } }
fun subtraction(a: Int, b: Int): Either<Error, Int> =
trap("Subtraction failed") { runOnServer { a - b } }
fun multiplication(a: Int, b: Int): Either<Error, Int> =
trap("Multiplication failed") { runOnServer { a * b } }
fun division(a: Int, b: Int): Either<Error, Int> =
trap("Division failed") { runOnServer { a / b } }
fun main() {
addition(10, 10)
.flatMap { additionResult ->
subtraction(additionResult, 10)
.flatMap { subtractionResult ->
multiplication(subtractionResult, 10)
.flatMap { multiplicationResult ->
division(multiplicationResult, 10)
.map { divisionResult ->
divisionResult
}
}
}
}
.fold(
{
// This is what we should do if we get an Either.Left / Error
println(it)
},
{
// This is what we do if everything when well
println(it)
}
)
}
```

`Error(errorString=Addition failed, exception=java.io.IOException: boom!)`

We still have the `flatMap`

, `map`

pyramid. Let's see if we can do something
about it.

## Bind in Arrow

So let's look at how Arrow can fix this for us with something called `bind`

.
This gives us the exact same pattern as in the examples above, but it looks
much more sequential and is much easier to read. The `either<Error,Int>`

returns an `Either`

and we fold over the result to take action on both the
`Either.Left`

and `Either.Right`

.

```
import arrow.core.Either
import arrow.core.continuations.either
import kotlinx.coroutines.runBlocking
import java.io.IOException
// A data class that holds data about the error
data class Error(val errorString: String, val exception: Exception)
// Simulates an operation that can go wrong
fun <A> runOnServer(f: () -> A): A =
if (Math.random() > 0.2) f()
else throw IOException("boom!")
// Wrap in Either.Left if exception, else in Either.Right
fun <A> trap(errorString: String, f: () -> A): Either<Error, A> =
try { Either.Right(f()) } catch (e: Exception) { Either.Left(Error(errorString, e)) }
fun addition(a: Int, b: Int): Either<Error, Int> =
trap("Addition failed") { runOnServer { a + b } }
fun subtraction(a: Int, b: Int): Either<Error, Int> =
trap("Subtraction failed") { runOnServer { a - b } }
fun multiplication(a: Int, b: Int): Either<Error, Int> =
trap("Multiplication failed") { runOnServer { a * b } }
fun division(a: Int, b: Int): Either<Error, Int> =
trap("Division failed") { runOnServer { a / b } }
fun main() {
runBlocking {
either<Error,Int> {
val additionResult = addition(10, 10).bind()
val subtractionResult = subtraction(additionResult, 10).bind()
val multiplicationResult = multiplication(subtractionResult, 10).bind()
val divisionResult = division(multiplicationResult, 10).bind()
divisionResult
}
}.fold(
{
// This is what we should do if we get an Either.Left / Error
println(it)
},
{
// This is what we do if everything when well
println(it)
}
)
}
```

`10`

The railway diagram for this code is the same as the one above.

## Resources

- https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.md
- https://fsharpforfunandprofit.com/rop/
- https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/
- https://arrow-kt.io/docs/patterns/monad_comprehensions/
- https://www.vavr.io/
- https://www.javadoc.io/doc/io.vavr/vavr/0.10.0/io/vavr/control/Either.html