Skip to content

Instantly share code, notes, and snippets.

@timrijckaert
Created February 18, 2021 17:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timrijckaert/084da897db333b4224a1a2ae07b4011f to your computer and use it in GitHub Desktop.
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.
//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