![JAR search and dependency download from the Maven repository](/logo.png)
commonMain.com.harmony.kotlin.common.either.Either.kt Maven / Gradle / Ivy
package com.harmony.kotlin.common.either
import com.harmony.kotlin.common.either.Either.Left
import com.harmony.kotlin.common.either.Either.Right
/**
* Either implementation mainly based on arrow's implementation:
* https://github.com/arrow-kt/arrow/blob/main/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt
*
* Highly recommendable to read its documentation:
* https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/
*/
sealed class Either {
/**
* The left side of the disjoint union, as opposed to the [Right] side.
*/
data class Left(val value: T) : Either() {
override fun isRight() = false
override fun isLeft() = true
override fun get(): Nothing = throw NoSuchElementException("Either.Right.value on Left")
}
/**
* The right side of the disjoint union, as opposed to the [Left] side.
*/
data class Right(val value: T) : Either() {
override fun isRight() = true
override fun isLeft() = false
override fun get(): T = value
}
/**
* Returns `true` if this is a [Left], `false` otherwise.
*/
abstract fun isLeft(): Boolean
/**
* Returns `true` if this is a [Right], `false` otherwise.
*/
abstract fun isRight(): Boolean
/**
* The contained value if the instance is [Right], will throw NoSuchElementException when it is [Left]
*/
abstract fun get(): RIGHT
/**
* Applies `ifLeft` if this is a [Left] or `ifRight` if this is a [Right].
*/
inline fun fold(ifLeft: (LEFT) -> C, ifRight: (RIGHT) -> C): C = when (this) {
is Left -> ifLeft(value)
is Right -> ifRight(value)
}
/**
* Returns the value from this [Right] or null if this is a [Left].
*/
fun getOrNull(): RIGHT? = fold({ null }, { it })
/**
* Returns the value from this [Left] or null if this is a [Right].
*/
fun getLeftOrNull(): LEFT? = fold({ it }, { null })
/**
* If this is a [Left], then return the left value in [Right] or vice versa.
*/
fun swap() = fold(
{ Right(it) },
{ Left(it) }
)
/**
* The given function is applied if this is a [Right] but original [RIGHT] is returned.
*/
inline fun tap(f: (RIGHT) -> Unit): Either = fold(
{ Left(it) },
{
f(it)
Right(it)
}
)
/**
* The given function is applied if this is a [Right].
*/
inline fun map(f: (RIGHT) -> C): Either = fold(
{ Left(it) },
{ Right(f(it)) }
)
/**
* The given function is applied if this is a [Left].
*/
inline fun mapLeft(f: (LEFT) -> C): Either = fold(
{ Left(f(it)) },
{ Right(it) }
)
/**
* Map over Left and Right of this Either
* if the instance is [Left] will map with [leftMapper]
* if the instance is [Right] will map with [rightMapper]
*/
inline fun bimap(leftMapper: (LEFT) -> C, rightMapper: (RIGHT) -> P): Either = fold(
{ Left(leftMapper(it)) },
{ Right(rightMapper(it)) }
)
}
/**
* Binds the given function across [Right].
*
* @param f The function to bind across [Right].
*/
inline fun Either.flatMap(f: (B) -> Either): Either =
when (this) {
is Either.Left -> this
is Either.Right -> f(this.value)
}
/**
* Returns the value from this [Right] or the given argument if this is a [Left].
*/
fun Either<*, B>.getOrElse(default: () -> B): B = fold({ default() }, { it })
/**
* Returns the value from this [Right] or null if this is a [Left].
*/
fun Either<*, B>.getOrNull(): B? = getOrElse { null }
/**
* Returns the value from this [Right] or allows clients to transform [Left] to [Right] while providing access to the value of [Left].
*/
inline fun Either.getOrHandle(default: (A) -> B): B = fold({ default(it) }, { it })
© 2015 - 2025 Weber Informatics LLC | Privacy Policy