Skip to content

Instantly share code, notes, and snippets.

@indrih17
Created July 5, 2022 17:32
Show Gist options
  • Save indrih17/38eec1b4f59a31fc9c33933f93e25a3d to your computer and use it in GitHub Desktop.
Save indrih17/38eec1b4f59a31fc9c33933f93e25a3d to your computer and use it in GitHub Desktop.
/**
* Монада [Either] создан, чтобы передать состояние, которое может находиться в одном из двух вариантов:
* [Either.Left] и [Either.Right]. Если Вы передаёте ошибку и результат, то ошибка должна быть [Either.Left],
* а результат [Either.Right]. Пример: `Either<NetworkError, LoadedUser>`.
*/
sealed class Either<out A, out B> {
/** Левая ветвь. */
data class Left<T>(val value: T) : Either<T, Nothing>()
/** Правая ветвь. */
data class Right<T>(val value: T) : Either<Nothing, T>()
companion object
}
/** Трансформация правой части. */
inline infix fun <A, B, C> Either<A, B>.map(f: (B) -> C): Either<A, C> = when (this) {
is Either.Left -> this
is Either.Right -> Either.Right(f(value))
}
/** Трансформация левой части. */
inline infix fun <A, B, C> Either<A, C>.mapLeft(f: (A) -> B): Either<B, C> = when (this) {
is Either.Left -> Either.Left(f(value))
is Either.Right -> this
}
/** Трансформация левой и правой частей. */
inline fun <A, B, C, D> Either<A, B>.bimap(leftOperation: (A) -> C, rightOperation: (B) -> D): Either<C, D> =
when (this) {
is Either.Left -> Either.Left(leftOperation(value))
is Either.Right -> Either.Right(rightOperation(value))
}
/** Сведение обеих ветвей к единому результату [C]. */
inline fun <A, B, C> Either<A, B>.fold(ifLeft: (A) -> C, ifRight: (B) -> C): C = when (this) {
is Either.Left -> ifLeft(value)
is Either.Right -> ifRight(value)
}
/** При совпадающих типах можно просто взять результат. */
fun <A> Either<A, A>.take(): A =
when (this) {
is Either.Left -> value
is Either.Right -> value
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment