Add flatMap{Both,Either}
This commit is contained in:
parent
5d2c732ae7
commit
4e5cdeede7
@ -22,6 +22,151 @@ public inline infix fun <V, E, U> Result<V, E>.map(transform: (V) -> U): Result<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<Result<V, E>, E>][Result] to [Result<V, E>][Result].
|
||||||
|
*
|
||||||
|
* - Rust: [Result.flatten](https://doc.rust-lang.org/std/result/enum.Result.html#method.flatten)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E> Result<Result<V, E>, E>.flatten(): Result<V, E> {
|
||||||
|
return when (this) {
|
||||||
|
is Ok -> value
|
||||||
|
is Err -> this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by either applying the [transform]
|
||||||
|
* function if this [Result] is [Ok], or returning this [Err].
|
||||||
|
*
|
||||||
|
* This is functionally equivalent to [andThen].
|
||||||
|
*
|
||||||
|
* - Scala: [Either.flatMap](http://www.scala-lang.org/api/2.12.0/scala/util/Either.html#flatMap[AA>:A,Y](f:B=>scala.util.Either[AA,Y]):scala.util.Either[AA,Y])
|
||||||
|
*/
|
||||||
|
public inline infix fun <V, E, U> Result<V, E>.flatMap(transform: (V) -> Result<U, E>): Result<U, E> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return andThen(transform)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
||||||
|
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||||
|
*
|
||||||
|
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||||
|
*
|
||||||
|
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#mapBoth)
|
||||||
|
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E, U> Result<V, E>.mapBoth(
|
||||||
|
success: (V) -> U,
|
||||||
|
failure: (E) -> U,
|
||||||
|
): U {
|
||||||
|
contract {
|
||||||
|
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
||||||
|
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (this) {
|
||||||
|
is Ok -> success(value)
|
||||||
|
is Err -> failure(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
||||||
|
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||||
|
*
|
||||||
|
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||||
|
*
|
||||||
|
* This is functionally equivalent to [mapBoth].
|
||||||
|
*
|
||||||
|
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#mapBoth)
|
||||||
|
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E, U> Result<V, E>.fold(
|
||||||
|
success: (V) -> U,
|
||||||
|
failure: (E) -> U,
|
||||||
|
): U {
|
||||||
|
contract {
|
||||||
|
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
||||||
|
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapBoth(success, failure)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by applying either the [success]
|
||||||
|
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||||
|
*
|
||||||
|
* Unlike [mapEither], [success] and [failure] must both return [U].
|
||||||
|
*
|
||||||
|
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#mapBoth)
|
||||||
|
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E, U> Result<V, E>.flatMapBoth(
|
||||||
|
success: (V) -> Result<U, E>,
|
||||||
|
failure: (E) -> Result<U, E>,
|
||||||
|
): Result<U, E> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
||||||
|
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (this) {
|
||||||
|
is Ok -> success(value)
|
||||||
|
is Err -> failure(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success]
|
||||||
|
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||||
|
*
|
||||||
|
* Unlike [mapBoth], [success] and [failure] may either return [U] or [F] respectively.
|
||||||
|
*
|
||||||
|
* - Haskell: [Data.Bifunctor.Bimap](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:bimap)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E, U, F> Result<V, E>.mapEither(
|
||||||
|
success: (V) -> U,
|
||||||
|
failure: (E) -> F,
|
||||||
|
): Result<U, F> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
||||||
|
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (this) {
|
||||||
|
is Ok -> Ok(success(value))
|
||||||
|
is Err -> Err(failure(error))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps this [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success]
|
||||||
|
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
||||||
|
*
|
||||||
|
* Unlike [mapBoth], [success] and [failure] may either return [U] or [F] respectively.
|
||||||
|
*
|
||||||
|
* - Haskell: [Data.Bifunctor.Bimap](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:bimap)
|
||||||
|
*/
|
||||||
|
public inline fun <V, E, U, F> Result<V, E>.flatMapEither(
|
||||||
|
success: (V) -> Result<U, F>,
|
||||||
|
failure: (E) -> Result<U, F>,
|
||||||
|
): Result<U, F> {
|
||||||
|
contract {
|
||||||
|
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
||||||
|
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return when (this) {
|
||||||
|
is Ok -> success(value)
|
||||||
|
is Err -> failure(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps this [Result<V, E>][Result] to [Result<V, F>][Result] by either applying the [transform]
|
* Maps this [Result<V, E>][Result] to [Result<V, F>][Result] by either applying the [transform]
|
||||||
* function to the [error][Err.error] if this [Result] is [Err], or returning this [Ok].
|
* function to the [error][Err.error] if this [Result] is [Err], or returning this [Ok].
|
||||||
@ -94,88 +239,6 @@ public inline infix fun <V, E, U> Result<Iterable<V>, E>.mapAll(transform: (V) -
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
|
||||||
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err]. Both of these
|
|
||||||
* functions must return the same type ([U]).
|
|
||||||
*
|
|
||||||
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#mapBoth)
|
|
||||||
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
|
|
||||||
*/
|
|
||||||
public inline fun <V, E, U> Result<V, E>.mapBoth(success: (V) -> U, failure: (E) -> U): U {
|
|
||||||
contract {
|
|
||||||
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
|
|
||||||
return when (this) {
|
|
||||||
is Ok -> success(value)
|
|
||||||
is Err -> failure(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps this [Result<V, E>][Result] to [U] by applying either the [success] function if this
|
|
||||||
* [Result] is [Ok], or the [failure] function if this [Result] is an [Err]. Both of these
|
|
||||||
* functions must return the same type ([U]).
|
|
||||||
*
|
|
||||||
* This is functionally equivalent to [mapBoth].
|
|
||||||
*
|
|
||||||
* - Elm: [Result.Extra.mapBoth](http://package.elm-lang.org/packages/elm-community/result-extra/2.2.0/Result-Extra#mapBoth)
|
|
||||||
* - Haskell: [Data.Either.either](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Either.html#v:either)
|
|
||||||
*/
|
|
||||||
public inline fun <V, E, U> Result<V, E>.fold(success: (V) -> U, failure: (E) -> U): U {
|
|
||||||
contract {
|
|
||||||
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapBoth(success, failure)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps this [Result<V, E>][Result] to [Result<U, F>][Result] by applying either the [success]
|
|
||||||
* function if this [Result] is [Ok], or the [failure] function if this [Result] is an [Err].
|
|
||||||
*
|
|
||||||
* - Haskell: [Data.Bifunctor.Bimap](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-Bifunctor.html#v:bimap)
|
|
||||||
*/
|
|
||||||
public inline fun <V, E, U, F> Result<V, E>.mapEither(success: (V) -> U, failure: (E) -> F): Result<U, F> {
|
|
||||||
contract {
|
|
||||||
callsInPlace(success, InvocationKind.AT_MOST_ONCE)
|
|
||||||
callsInPlace(failure, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
|
|
||||||
return when (this) {
|
|
||||||
is Ok -> Ok(success(value))
|
|
||||||
is Err -> Err(failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps this [Result<V, E>][Result] to [Result<U, E>][Result] by either applying the [transform]
|
|
||||||
* function if this [Result] is [Ok], or returning this [Err].
|
|
||||||
*
|
|
||||||
* This is functionally equivalent to [andThen].
|
|
||||||
*
|
|
||||||
* - Scala: [Either.flatMap](http://www.scala-lang.org/api/2.12.0/scala/util/Either.html#flatMap[AA>:A,Y](f:B=>scala.util.Either[AA,Y]):scala.util.Either[AA,Y])
|
|
||||||
*/
|
|
||||||
public inline infix fun <V, E, U> Result<V, E>.flatMap(transform: (V) -> Result<U, E>): Result<U, E> {
|
|
||||||
contract {
|
|
||||||
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
|
|
||||||
}
|
|
||||||
|
|
||||||
return andThen(transform)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps this [Result<Result<V, E>, E>][Result] to [Result<V, E>][Result].
|
|
||||||
*
|
|
||||||
* - Rust: [Result.flatten](https://doc.rust-lang.org/std/result/enum.Result.html#method.flatten)
|
|
||||||
*/
|
|
||||||
public inline fun <V, E> Result<Result<V, E>, E>.flatten(): Result<V, E> {
|
|
||||||
return andThen { it }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the [transformation][transform] of the [value][Ok.value] if this [Result] is [Ok]
|
* Returns the [transformation][transform] of the [value][Ok.value] if this [Result] is [Ok]
|
||||||
* and satisfies the given [predicate], otherwise this [Result].
|
* and satisfies the given [predicate], otherwise this [Result].
|
||||||
@ -194,6 +257,7 @@ public inline fun <V, E> Result<V, E>.toErrorIf(predicate: (V) -> Boolean, trans
|
|||||||
} else {
|
} else {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
is Err -> this
|
is Err -> this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,11 +274,12 @@ public inline fun <V, E> Result<V?, E>.toErrorIfNull(error: () -> E): Result<V,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Ok -> if(value == null) {
|
is Ok -> if (value == null) {
|
||||||
Err(error())
|
Err(error())
|
||||||
} else {
|
} else {
|
||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
is Err -> this
|
is Err -> this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,6 +302,7 @@ public inline fun <V, E> Result<V, E>.toErrorUnless(predicate: (V) -> Boolean, t
|
|||||||
} else {
|
} else {
|
||||||
this
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
is Err -> this
|
is Err -> this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -258,6 +324,7 @@ public inline fun <V, E> Result<V, E>.toErrorUnlessNull(error: () -> E): Result<
|
|||||||
} else {
|
} else {
|
||||||
Err(error())
|
Err(error())
|
||||||
}
|
}
|
||||||
|
|
||||||
is Err -> Err(error())
|
is Err -> Err(error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,175 +3,41 @@ package com.github.michaelbull.result
|
|||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertNull
|
import kotlin.test.assertNull
|
||||||
import kotlin.test.assertSame
|
|
||||||
|
|
||||||
class MapTest {
|
class MapTest {
|
||||||
private sealed class MapErr(val reason: String) {
|
private sealed interface MapErr {
|
||||||
object HelloError : MapErr("hello")
|
val reason: String
|
||||||
object WorldError : MapErr("world")
|
|
||||||
class CustomError(reason: String) : MapErr(reason)
|
data object HelloError : MapErr {
|
||||||
|
override val reason = "hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
data object WorldError : MapErr {
|
||||||
|
override val reason = "world"
|
||||||
|
}
|
||||||
|
|
||||||
|
data class CustomError(override val reason: String) : MapErr
|
||||||
}
|
}
|
||||||
|
|
||||||
class Map {
|
class Map {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsTransformedValueIfOk() {
|
fun returnsTransformedValueIfOk() {
|
||||||
assertEquals(
|
val value: Result<Int, MapErr> = Ok(10)
|
||||||
expected = 30,
|
|
||||||
actual = Ok(10).map { it + 20 }.get()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Suppress("UNREACHABLE_CODE")
|
|
||||||
fun returnsErrorIfErr() {
|
|
||||||
val result = Err(MapErr.HelloError).map { "hello $it" }
|
|
||||||
|
|
||||||
result as Err
|
|
||||||
|
|
||||||
assertSame(
|
|
||||||
expected = MapErr.HelloError,
|
|
||||||
actual = result.error
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapError {
|
|
||||||
@Test
|
|
||||||
fun returnsValueIfOk() {
|
|
||||||
val value = Ok(55).map { it + 15 }.mapError { MapErr.WorldError }.get()
|
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = 70,
|
expected = Ok(30),
|
||||||
actual = value
|
actual = value.map { it + 20 }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun returnsErrorIfErr() {
|
fun returnsErrorIfErr() {
|
||||||
val result: Result<String, MapErr> = Ok("let")
|
val value: Result<Int, MapErr> = Err(MapErr.HelloError)
|
||||||
.map { "$it me" }
|
|
||||||
.andThen {
|
|
||||||
when (it) {
|
|
||||||
"let me" -> Err(MapErr.CustomError("$it $it"))
|
|
||||||
else -> Ok("$it get")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.mapError { MapErr.CustomError("${it.reason} get what i want") }
|
|
||||||
|
|
||||||
result as Err
|
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(
|
||||||
expected = "let me let me get what i want",
|
expected = Err(MapErr.HelloError),
|
||||||
actual = result.error.reason
|
actual = value.map { "hello $it" }
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapOr {
|
|
||||||
@Test
|
|
||||||
fun returnsTransformedValueIfOk() {
|
|
||||||
val value = Ok("foo").mapOr(42, String::length)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = 3,
|
|
||||||
actual = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun returnsDefaultValueIfErr() {
|
|
||||||
val value = Err("bar").mapOr(42, String::length)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = 42,
|
|
||||||
actual = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapOrElse {
|
|
||||||
private val k = 21
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun returnsTransformedValueIfOk() {
|
|
||||||
val value = Ok("foo").mapOrElse({ k * 2 }, String::length)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = 3,
|
|
||||||
actual = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun returnsDefaultValueIfErr() {
|
|
||||||
val value = Err("bar").mapOrElse({ k * 2 }, String::length)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = 42,
|
|
||||||
actual = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapBoth {
|
|
||||||
@Test
|
|
||||||
@Suppress("UNREACHABLE_CODE")
|
|
||||||
fun returnsTransformedValueIfOk() {
|
|
||||||
val value = Ok("there is").mapBoth(
|
|
||||||
success = { "$it a light" },
|
|
||||||
failure = { "$it that never" }
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = "there is a light",
|
|
||||||
actual = value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Suppress("UNREACHABLE_CODE")
|
|
||||||
fun returnsTransformedErrorIfErr() {
|
|
||||||
val error = Err(MapErr.CustomError("this")).mapBoth(
|
|
||||||
success = { "$it charming" },
|
|
||||||
failure = { "${it.reason} man" }
|
|
||||||
)
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = "this man",
|
|
||||||
actual = error
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MapEither {
|
|
||||||
@Test
|
|
||||||
@Suppress("UNREACHABLE_CODE")
|
|
||||||
fun returnsTransformedValueIfOk() {
|
|
||||||
val result = Ok(500).mapEither(
|
|
||||||
success = { it + 500 },
|
|
||||||
failure = { MapErr.CustomError("$it") }
|
|
||||||
)
|
|
||||||
|
|
||||||
result as Ok
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = 1000,
|
|
||||||
actual = result.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun returnsTransformedErrorIfErr() {
|
|
||||||
val result = Err("the reckless").mapEither(
|
|
||||||
success = { "the wild youth" },
|
|
||||||
failure = { MapErr.CustomError("the truth") }
|
|
||||||
)
|
|
||||||
|
|
||||||
result as Err
|
|
||||||
|
|
||||||
assertEquals(
|
|
||||||
expected = "the truth",
|
|
||||||
actual = result.error.reason
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,6 +90,208 @@ class MapTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MapError {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsValueIfOk() {
|
||||||
|
val value: Result<Int, MapErr> = Ok(70)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Ok(70),
|
||||||
|
actual = value.mapError { MapErr.WorldError }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsErrorIfErr() {
|
||||||
|
val value: Result<Int, MapErr> = Err(MapErr.HelloError)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Err(MapErr.WorldError),
|
||||||
|
actual = value.mapError { MapErr.WorldError }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapOr {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<String, String> = Ok("foo")
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = 3,
|
||||||
|
actual = value.mapOr(42, String::length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsDefaultValueIfErr() {
|
||||||
|
val value: Result<String, String> = Err("foo")
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = 42,
|
||||||
|
actual = value.mapOr(42, String::length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapOrElse {
|
||||||
|
private val k = 21
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<String, String> = Ok("foo")
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = 3,
|
||||||
|
actual = value.mapOrElse({ k * 2 }, String::length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsDefaultValueIfErr() {
|
||||||
|
val value: Result<String, String> = Err("foo")
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = 42,
|
||||||
|
actual = value.mapOrElse({ k * 2 }, String::length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapBoth {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<Int, Long> = Ok(50)
|
||||||
|
|
||||||
|
val result: String = value.mapBoth(
|
||||||
|
success = { "good $it" },
|
||||||
|
failure = { "bad $it" }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = "good 50",
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedErrorIfErr() {
|
||||||
|
val value: Result<Int, Long> = Err(20)
|
||||||
|
|
||||||
|
val result: String = value.mapBoth(
|
||||||
|
success = { "good $it" },
|
||||||
|
failure = { "bad $it" }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = "bad 20",
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FlatMapBoth {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<Int, Long> = Ok(50)
|
||||||
|
|
||||||
|
val result: Result<String, Long> = value.flatMapBoth(
|
||||||
|
success = { Ok("good $it") },
|
||||||
|
failure = { Err(100L) }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Ok("good 50"),
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedErrorIfErr() {
|
||||||
|
val result: Result<Int, Long> = Err(25L)
|
||||||
|
|
||||||
|
val value: Result<String, Long> = result.flatMapBoth(
|
||||||
|
success = { Ok("good $it") },
|
||||||
|
failure = { Err(100L) }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Err(100L),
|
||||||
|
actual = value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MapEither {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<Int, MapErr.HelloError> = Ok(500)
|
||||||
|
|
||||||
|
val result: Result<Long, MapErr.CustomError> = value.mapEither(
|
||||||
|
success = { it + 500L },
|
||||||
|
failure = { MapErr.CustomError("$it") }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Ok(1000L),
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedErrorIfErr() {
|
||||||
|
val value: Result<Int, MapErr.HelloError> = Err(MapErr.HelloError)
|
||||||
|
|
||||||
|
val result: Result<Long, MapErr.CustomError> = value.mapEither(
|
||||||
|
success = { it + 500L },
|
||||||
|
failure = { MapErr.CustomError("bad") }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Err(MapErr.CustomError("bad")),
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FlatMapEither {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedValueIfOk() {
|
||||||
|
val value: Result<Int, MapErr.HelloError> = Ok(500)
|
||||||
|
|
||||||
|
val result: Result<Long, MapErr.CustomError> = value.flatMapEither(
|
||||||
|
success = { Ok(it + 500L) },
|
||||||
|
failure = { Err(MapErr.CustomError("$it")) }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Ok(1000L),
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun returnsTransformedErrorIfErr() {
|
||||||
|
val value: Result<Int, MapErr.HelloError> = Err(MapErr.HelloError)
|
||||||
|
|
||||||
|
val result: Result<Long, MapErr.CustomError> = value.flatMapEither(
|
||||||
|
success = { Ok(it + 500L) },
|
||||||
|
failure = { Err(MapErr.CustomError("bad")) }
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
expected = Err(MapErr.CustomError("bad")),
|
||||||
|
actual = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ToErrorIfNull {
|
class ToErrorIfNull {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
Loading…
Reference in New Issue
Block a user