Implementing Kotlin Either


#1

I am reading about implementing Either (disjoint union) in Kotlin.

Code I am reading on the internet suggests:

sealed class Either<out A, out B> {
    class Left<A>(val value: A): Either<A, Nothing>()
    class Right<B>(val value: B): Either<Nothing, B>()
}

my intuition suggests:

sealed class Either<A, B> {
    class Left<A>(val value: A): Either<A, B>()
    class Right<B>(val value: B): Either<A, B>()
}

What is the advantage of out/Nothing over my approach?


#2

Nothing is a bit more explicit and robust. The right side of Left is obviously “nothing” and shouldn’t be accessed. Actually it is not of the type B since this would mean something like “null of type B”, but there is nothing to be typed. As a subtype of all types Nothing can easily be used here.

The advantage of out is that the compiler doesn’t restrict some corner cases in striving for sound typing. You can read more about variance in the docs.


#3

(referring to first definition)

But the classes defined inside the “sealed class” are supposed to return objects of type Outer class right?

If the inner is returning Either<Left, Nothing> … how is that an object of type either<Left, Right> ?


#4

That is because Nothing is a subtype of everything, hence called “bottom type”.

You can for example write

fun foo(): String = TODO()

because the TODO function is of the type Nothing that is a subtype of String.


#5

This is going o sound stupid, but I want to make sure I understand this.
Consider the first example, with A = Int and B = String. Then.

1. Left<Int>(42) has type Either<Int, Nothing>
2. Because "Nothing is a subtype of String" therefore Either<Int, Nothing> is a subtype of Either<Int, String>
3. Therefore Left<Int>(42) can be used as an Either<Int, String>

Are all three assertions above correct?

If so, I can move on to understand how “when” still works given this weirdness.


#6

Yes, this is correct.


#7

Why don’t you use arrow ?

Implementation is There

It’s really good, with many transformation such as fold or map.


#8

I see few problem with the implementation you propose (the main issue is conceptually considering right to be the success & left to be the error in some places, it would be another type … like Result or Try)

But still an Either type would be nice (so does a Try type…)

on the other hand… I’m afraid people abusing Either (fear the Either<A, Ether<B, Either<C,D>>>)… but bad developpers should not be an excuse not to do things…


#9

In reality you should never have that kind of issue: you should use Map Either or fold to transform your source Either to a new Either.

Arrow, is the kotlin functional library. I used it in a project, and I never had such construct.