Facilitate mapping to arbitrary types in and/or functions

Closes #95
This commit is contained in:
Michael Bull 2024-03-02 16:36:56 +00:00
parent 6c155362dc
commit 05d50b7fec
3 changed files with 19 additions and 15 deletions

View File

@ -8,7 +8,7 @@ import kotlin.contracts.contract
*
* - Rust: [Result.and](https://doc.rust-lang.org/std/result/enum.Result.html#method.and)
*/
public infix fun <V, E> Result<V, E>.and(result: Result<V, E>): Result<V, E> {
public infix fun <V, E, U> Result<V, E>.and(result: Result<U, E>): Result<U, E> {
return when (this) {
is Ok -> result
is Err -> this
@ -16,7 +16,7 @@ public infix fun <V, E> Result<V, E>.and(result: Result<V, E>): Result<V, E> {
}
@Deprecated("Use andThen instead", ReplaceWith("andThen { result() }"))
public inline infix fun <V, E> Result<V, E>.and(result: () -> Result<V, E>): Result<V, E> {
public inline infix fun <V, E, U> Result<V, E>.and(result: () -> Result<U, E>): Result<U, E> {
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}

View File

@ -8,7 +8,7 @@ import kotlin.contracts.contract
*
* - Rust: [Result.or](https://doc.rust-lang.org/std/result/enum.Result.html#method.or)
*/
public infix fun <V, E> Result<V, E>.or(result: Result<V, E>): Result<V, E> {
public infix fun <V, E, F> Result<V, E>.or(result: Result<V, F>): Result<V, F> {
return when (this) {
is Ok -> this
is Err -> result
@ -16,7 +16,7 @@ public infix fun <V, E> Result<V, E>.or(result: Result<V, E>): Result<V, E> {
}
@Deprecated("Use orElse instead", ReplaceWith("orElse { result() }"))
public inline infix fun <V, E> Result<V, E>.or(result: () -> Result<V, E>): Result<V, E> {
public inline infix fun <V, E, F> Result<V, E>.or(result: () -> Result<V, F>): Result<V, F> {
contract {
callsInPlace(result, InvocationKind.AT_MOST_ONCE)
}
@ -30,7 +30,7 @@ public inline infix fun <V, E> Result<V, E>.or(result: () -> Result<V, E>): Resu
*
* - Rust: [Result.or_else](https://doc.rust-lang.org/std/result/enum.Result.html#method.or_else)
*/
public inline infix fun <V, E> Result<V, E>.orElse(transform: (E) -> Result<V, E>): Result<V, E> {
public inline infix fun <V, E, F> Result<V, E>.orElse(transform: (E) -> Result<V, F>): Result<V, F> {
contract {
callsInPlace(transform, InvocationKind.AT_MOST_ONCE)
}

View File

@ -3,6 +3,10 @@ package com.github.michaelbull.result
import kotlin.test.Test
import kotlin.test.assertEquals
private inline fun produce(number: Int, error: String): Result<Int, String> {
return Ok(number).and(Err(error))
}
class ZipTest {
data class ZipData3(val a: String, val b: Int, val c: Boolean)
@ -31,7 +35,7 @@ class ZipTest {
fun returnsErrIfOneOfTwoErr() {
val result = zip(
{ Ok(10) },
{ Ok(20).and(Err("hello")) },
{ produce(20, "hello") },
Int::plus
)
@ -46,8 +50,8 @@ class ZipTest {
@Test
fun returnsFirstErrIfBothErr() {
val result = zip(
{ Ok(10).and(Err("foo")) },
{ Ok(20).and(Err("bar")) },
{ produce(10, "foo") },
{ produce(20, "bar") },
Int::plus
)
@ -225,11 +229,11 @@ class ZipTest {
@Test
fun returnsAllErrsIfAllErr() {
val result = zipOrAccumulate(
{ Ok(10).and(Err("error one")) },
{ Ok(20).and(Err("error two")) },
{ Ok(30).and(Err("error three")) },
{ Ok(40).and(Err("error four")) },
{ Ok(50).and(Err("error five")) },
{ produce(10, "error one") },
{ produce(20, "error two") },
{ produce(30, "error three") },
{ produce(40, "error four") },
{ produce(50, "error five") },
) { a, b, c, d, e ->
a + b + c + d + e
}
@ -252,7 +256,7 @@ class ZipTest {
fun returnsOneErrsIfOneOfErr() {
val result = zipOrAccumulate(
{ Ok(10) },
{ Ok(20).and(Err("only error")) },
{ produce(20, "only error") },
{ Ok(30) },
{ Ok(40) },
{ Ok(50) },
@ -263,7 +267,7 @@ class ZipTest {
result as Err
assertEquals(
expected = listOf("only error",),
expected = listOf("only error"),
actual = result.error,
)
}