sealed class Result() { /** Contains the success value */ data class Ok(val ok: T): Result() /** Contains the error value */ data class Err(val err: E): Result() fun map(op: (T) -> U): Result = when (this) { is Result.Ok -> Result.Ok(op(this.ok)) is Result.Err -> Result.Err(this.err) } fun andThen(op: (T) -> Result): Result = when (this) { is Result.Ok -> op(this.ok) is Result.Err -> Result.Err(this.err) } fun unwrap(): T = when (this) { is Result.Ok -> this.ok is Result.Err -> when (this.err) { is Throwable -> throw this.err else -> throw RuntimeException(this.err.toString()) } } } fun wrapResult(op: () -> T): Result = try { Result.Ok(op()) } catch (e: Exception) { Result.Err(e) } fun div(x: Int, y: Int): Result = if (y == 0) { Result.Err("Division by zero") } else { Result.Ok(x / y) } fun main1(args: Array) { (0..5) .map { div(5, it) } .forEach { println(it) } } fun main2(args: Array) { (0..5) .map { div(5, it) .map { it * 2 } } .forEach { println(it) } } fun main3(args: Array) { (0..5) .map { div(5, it) .map { it - 2 } .andThen { div(2, it) } } .forEach { println(it) } } fun main4(args: Array) { (0..5) .map { wrapResult { 5 / it } .map { it - 2 } .andThen { wrapResult { 2 / it } } } .forEach { println(it) } } fun main5(args: Array) { (0..5) .reversed() .map { div(5, it) .map { it - 2 } .andThen { div(2, it) } } .forEach { println(it.unwrap()) } }