sealed class Result { data class Ok(val v: T): Result() data class Error(val e: E): Result() inline val value: T get() = when(this) { is Ok -> this.v is Error -> throw RuntimeException("attempt to get value of ${this}") } inline val error: E get() = when(this) { is Ok -> throw RuntimeException("attempt to get error of ${this}") is Error -> this.e } inline val isOk: Boolean inline get() = when(this) { is Ok -> true is Error -> false } inline val isError: Boolean inline get() = !this.isOk // FUNCTOR @Suppress("UNCHECKED_CAST") inline infix fun map(f: (T) -> (U)): Result = when (this) { is Ok -> Ok(f(this.v)) is Error -> this as Error } @Suppress("UNCHECKED_CAST") inline infix fun mapErr(f: (E) -> (U)): Result = when (this) { is Ok -> this as Ok is Error -> Error(f(this.e)) } // MONAD @Suppress("UNCHECKED_CAST") inline infix fun flatMap(f: (T) -> (Result)): Result = when (this) { is Ok -> f(this.v) is Error -> this as Error } @Suppress("UNCHECKED_CAST") inline infix fun flatMapErr(f: (E) -> (Result)): Result = when (this) { is Ok -> this as Ok is Error -> f(this.e) } inline val seq: Sequence get() = when(this){ is Ok -> generateSequence(this.v, { _:T -> null }) is Error -> generateSequence { null } } }