Why does the type of the result of the `left()` fu...
# getting-started
l
Why does the type of the result of the
left()
function here must have
R?
, although
R
is already by definition nullable?
Copy code
class Either<L, R> private constructor(
    private val left: L,
    private val right: R,
) {

    companion object {

        fun <L, R> left(left: L): Either<L, R?> {
            return Either(left, null)
        }
    }
}
j
What makes you say that
R
is by definition nullable?
R
is only nullable if the caller of this function specifies it as such. This signature forces
Either.left<Int, String>(42)
to return an
Either<Int, String?>
. Were it not for the so called "definitely nullable"
R?
, it would be expected to return
Either<Int, String>
which is not possible given the body of the function (so defining the function without
?
would not compile)
l
You're right, I was thinking, because
R : Any?
that it's guaranteed to be nullable. But indeed it depends on the concrete instantiation of the class. It can be nullable, but doesn't have to.
👌 1
Thanks!
j
You're welcome 🙂
m
Why are you defining such an algebra for Either? you could just do something like:
Copy code
sealed interface Either<out L, out R> {

    data class Left<L>(val value: L) : Either<L, Nothing>
    data class Right<R>(val value: R) : Either<Nothing, R>

    companion object {

        fun <L, R> left(left: L): Either<L, R> {
            return Left(left)
        }

        fun <L, R> right(right: R): Either<L, R> {
            return Right(right)
        }
    }
}
And then type each of them in isolation so you don’t need to pass null for non used branches
if you make it
Either<L, R?>
you could not make it work with other non nullable
R
perhaps
l
It's not me, it's legacy code. I agree that your approach is better.