Created
February 18, 2021 17:27
-
-
Save timrijckaert/084da897db333b4224a1a2ae07b4011f to your computer and use it in GitHub Desktop.
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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