Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Shameless copied from Arrow Core. However this is ideal to introduce your team to Either without making a big fuzz about adding a new lib with new paradigms.
//https://arrow-kt.io/docs/apidocs/arrow-core-data/arrow.core/-either/
sealed class Either<out A, out B> {
internal abstract val isRight: Boolean
internal abstract val isLeft: Boolean
fun isLeft(): Boolean = isLeft
fun isRight(): Boolean = isRight
inline fun <C> fold(ifLeft: (A) -> C, ifRight: (B) -> C): C = when (this) {
is Right -> ifRight(b)
is Left -> ifLeft(a)
}
fun swap(): Either<B, A> =
fold({ Right(it) }, { Left(it) })
inline fun <C> map(f: (B) -> C): Either<A, C> =
flatMap { Right(f(it)) }
inline fun <C> mapLeft(f: (A) -> C): Either<C, B> =
fold({ Left(f(it)) }, { Right(it) })
inline fun <C, D> bimap(leftOperation: (A) -> C, rightOperation: (B) -> D): Either<C, D> =
fold({ Left(leftOperation(it)) }, { Right(rightOperation(it)) })
fun orNull(): B? = fold({ null }, { it })
data class Left<out A>(val a: A) : Either<A, Nothing>() {
override val isLeft = true
override val isRight = false
override fun toString(): String = "Either.Left($a)"
companion object {
operator fun <A> invoke(a: A): Either<A, Nothing> = Left(a)
}
}
data class Right<out B>(val b: B) : Either<Nothing, B>() {
override val isLeft = false
override val isRight = true
override fun toString(): String = "Either.Right($b)"
companion object {
operator fun <B> invoke(b: B): Either<Nothing, B> = Right(b)
}
}
companion object {
fun <L> left(left: L): Either<L, Nothing> = Left(left)
fun <R> right(right: R): Either<Nothing, R> = Right(right)
fun <A> fromNullable(a: A?): Either<Unit, A> = a?.right() ?: Unit.left()
inline fun <R> catch(f: () -> R): Either<Throwable, R> =
try {
f().right()
} catch (t: Throwable) {
t.left()
}
inline fun <L, R> catch(fe: (Throwable) -> L, f: () -> R): Either<L, R> =
try {
f().right()
} catch (t: Throwable) {
fe(t).left()
}
}
}
inline fun <A, B, C> Either<A, B>.flatMap(f: (B) -> Either<A, C>): Either<A, C> =
when (this) {
is Either.Right -> f(b)
is Either.Left -> this
}
fun <A> A.left(): Either<A, Nothing> = Either.Left(this)
fun <A> A.right(): Either<Nothing, A> = Either.Right(this)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment