```class Failure<A>(val exception: A) transp...
# language-evolution
y
Copy code
class Failure<A>(val exception: A)
transparent value class Either<out A, out B> private constructor(val underlying: Any?) {
    companion object {
        fun <B> Right(value: B) = Either<Nothing, B>(value)
        fun <A> Left(exception: A) = Either<A, Nothing>(Failure<A>(exception))
    }
    val isRight: Boolean get() {
        contract {
            returns(true) implies (underlying is B)
            returns(false) implies (underlying is Failure<A>)
        }
        return underlying !is Failure<*>
    }
    val isLeft: Boolean get() {
        contract {
            returns(false) implies (underlying is B)
            returns(true) implies (underlying is Failure<A>)
        }
        return underlying is Failure<*>
    }
    // map, flatMap, etc.
}
// User code
class NetworkFailure(val causeOfError: String)
class Information(val information: String)
fun networkCall(shouldBeSuccessful: Boolean): Either<NetworkFailure, Information> = if(shouldBeSuccessful) Either.Right(Information("super secret user data")) else Either.Left(NetworkFailure("No internet"))

fun main() {
    val result = networkCall(true)
    // Smart casting go brrrrr...
    if(result.isRight) {
        println(result.information)
    } else {
        println(result.exception.causeOfError)
    }
}
Now, the Arrow folks already kind of tried to do with, but with computational blocks. The only issue with them is that they're kind of friction-y to use since you have to call
.bind()
on the returned result to get the value. However, this feature so far doesn't actually solve their use case because it has a missing piece: verification. What if, with an operator
verify
, a value class can prove that its underlying value is of a specific type. To continue with the arrow use-case, consider this:
Copy code
transparent value class Either<out A, out B> private constructor(val underlying: Any?) {
    // Same code from before
    ...
    context(EitherEffect<A>) // Can't quite remember the Arrow implementation but it is something like that
    operator fun verify() { // This would be auto-magically called everytime the value class is used as its underlying type
        contract {
            returns() implies (this@Either is B)
        }
        if(isLeft) throw ShortCircuitException(underlying)
    }
}
// User code
class NetworkFailure(val causeOfError: String)
class Information(val information: String)
fun networkCall(shouldBeSuccessful: Boolean): Either<NetworkFailure, Information> = if(shouldBeSuccessful) Either.Right(Information("super secret user data")) else Either.Left(NetworkFailure("No internet"))

fun main() {
    val result = networkCall(true)
    // Arrow computational block
    either {
        println(result.information)
        println(networkCall(false).information)
        // This never actually executes because the top one throws
        println(networkCall(true).information)
    }
}
or let's go even crazier. What if there's an
operator fun transparentlyCoerce
(long name to avoid clashes) that can be used for any class (not only value classes) and can have different implementations depending on context parameters. Then, that can be defined for Either like this:
Copy code
operator fun transparentlyCoerce(): B = if(isLeft) throw ShortCircuitException(underlying) else underlying
and in fact, have you noticed that
Failure
is kind of ugly? You need to call its
exception
property every time, what if you don't have to...:
Copy code
operator fun <A> Failure<A>.transparentlyCoerce(): A = exception