
commonMain.arrow.core.raise.RaiseAccumulate.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arrow-core Show documentation
Show all versions of arrow-core Show documentation
Functional companion to Kotlin's Standard Library
@file:OptIn(ExperimentalTypeInference::class, ExperimentalContracts::class)
@file:JvmMultifileClass
@file:JvmName("RaiseKt")
package arrow.core.raise
import arrow.core.Either
import arrow.core.EitherNel
import arrow.core.NonEmptyList
import arrow.core.NonEmptySet
import arrow.core.collectionSizeOrDefault
import arrow.core.toNonEmptyListOrNull
import arrow.core.toNonEmptySetOrNull
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind.AT_LEAST_ONCE
import kotlin.contracts.InvocationKind.AT_MOST_ONCE
import kotlin.contracts.InvocationKind.EXACTLY_ONCE
import kotlin.contracts.contract
import kotlin.experimental.ExperimentalTypeInference
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KProperty
/**
* Accumulate the errors from running both [action1] and [action2] using the given [combine] function.
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
block: (A, B) -> C
): C {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
{ }) { a, b, _ ->
block(a, b)
}
}
/**
* Accumulate the errors from running [action1], [action2], and [action3] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
block: (A, B, C) -> D
): D {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
{ }) { a, b, c, _ ->
block(a, b, c)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], and [action4] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
block: (A, B, C, D) -> E
): E {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
action4,
{ }) { a, b, c, d, _ ->
block(a, b, c, d)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
block: (A, B, C, D, E) -> F
): F {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
action4,
action5,
{ }) { a, b, c, d, e, _ ->
block(a, b, c, d, e)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
block: (A, B, C, D, E, F) -> G
): G {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
action4,
action5,
action6,
{ }) { a, b, c, d, e, f, _ ->
block(a, b, c, d, e, f)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
block: (A, B, C, D, E, F, G) -> H
): H {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
action4,
action5,
action6,
action7,
{ }) { a, b, c, d, e, f, g, _ ->
block(a, b, c, d, e, f, g)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
@BuilderInference action8: RaiseAccumulate.() -> H,
block: (A, B, C, D, E, F, G, H) -> I
): I {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(action8, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
combine,
action1,
action2,
action3,
action4,
action5,
action6,
action7,
action8,
{ }) { a, b, c, d, e, f, g, h, _ ->
block(a, b, c, d, e, f, g, h)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9] using the given [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.zipOrAccumulate(
combine: (Error, Error) -> Error,
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
@BuilderInference action8: RaiseAccumulate.() -> H,
@BuilderInference action9: RaiseAccumulate.() -> I,
block: (A, B, C, D, E, F, G, H, I) -> J
): J {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(action8, EXACTLY_ONCE)
callsInPlace(action9, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return withError({ it.reduce(combine) }) {
zipOrAccumulate(action1, action2, action3, action4, action5, action6, action7, action8, action9, block)
}
}
/**
* Accumulate the errors from running both [action1] and [action2].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
block: (A, B) -> C
): C {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
{}) { a, b, _ ->
block(a, b)
}
}
/**
* Accumulate the errors from running [action1], [action2], and [action3].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
block: (A, B, C) -> D
): D {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
{}) { a, b, c, _ ->
block(a, b, c)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], and [action4].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
block: (A, B, C, D) -> E
): E {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
action4,
{}) { a, b, c, d, _ ->
block(a, b, c, d)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
block: (A, B, C, D, E) -> F
): F {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
action4,
action5,
{}) { a, b, c, d, e, _ ->
block(a, b, c, d, e)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
block: (A, B, C, D, E, F) -> G
): G {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
action4,
action5,
action6,
{}) { a, b, c, d, e, f, _ ->
block(a, b, c, d, e, f)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
block: (A, B, C, D, E, F, G) -> H
): H {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
action4,
action5,
action6,
action7,
{}) { a, b, c, d, e, f, g, _ ->
block(a, b, c, d, e, f, g)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
@BuilderInference action8: RaiseAccumulate.() -> H,
block: (A, B, C, D, E, F, G, H) -> I
): I {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(action8, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return zipOrAccumulate(
action1,
action2,
action3,
action4,
action5,
action6,
action7,
action8,
{}) { a, b, c, d, e, f, g, h, _ ->
block(a, b, c, d, e, f, g, h)
}
}
/**
* Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL @OptIn(ExperimentalRaiseAccumulateApi::class)
@Suppress("WRONG_INVOCATION_KIND")
public inline fun Raise>.zipOrAccumulate(
@BuilderInference action1: RaiseAccumulate.() -> A,
@BuilderInference action2: RaiseAccumulate.() -> B,
@BuilderInference action3: RaiseAccumulate.() -> C,
@BuilderInference action4: RaiseAccumulate.() -> D,
@BuilderInference action5: RaiseAccumulate.() -> E,
@BuilderInference action6: RaiseAccumulate.() -> F,
@BuilderInference action7: RaiseAccumulate.() -> G,
@BuilderInference action8: RaiseAccumulate.() -> H,
@BuilderInference action9: RaiseAccumulate.() -> I,
block: (A, B, C, D, E, F, G, H, I) -> J
): J {
contract {
callsInPlace(action1, EXACTLY_ONCE)
callsInPlace(action2, EXACTLY_ONCE)
callsInPlace(action3, EXACTLY_ONCE)
callsInPlace(action4, EXACTLY_ONCE)
callsInPlace(action5, EXACTLY_ONCE)
callsInPlace(action6, EXACTLY_ONCE)
callsInPlace(action7, EXACTLY_ONCE)
callsInPlace(action8, EXACTLY_ONCE)
callsInPlace(action9, EXACTLY_ONCE)
callsInPlace(block, EXACTLY_ONCE)
}
return accumulate {
val a = accumulating { action1() }
val b = accumulating { action2() }
val c = accumulating { action3() }
val d = accumulating { action4() }
val e = accumulating { action5() }
val f = accumulating { action6() }
val g = accumulating { action7() }
val h = accumulating { action8() }
val i = accumulating { action9() }
block(a.value, b.value, c.value, d.value, e.value, f.value, g.value, h.value, i.value)
}
}
@RaiseDSL
public inline fun Raise.forEachAccumulating(
iterable: Iterable,
combine: (Error, Error) -> Error,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulating(iterable.iterator(), combine, block)
@RaiseDSL
public inline fun Raise.forEachAccumulating(
sequence: Sequence,
combine: (Error, Error) -> Error,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulating(sequence.iterator(), combine, block)
@RaiseDSL
public inline fun Raise.forEachAccumulating(
iterator: Iterator,
combine: (Error, Error) -> Error,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulatingImpl(iterator, combine) { item, _ -> block(item) }
@PublishedApi @JvmSynthetic
internal inline fun Raise.forEachAccumulatingImpl(
iterator: Iterator,
combine: (Error, Error) -> Error,
@BuilderInference block: RaiseAccumulate.(item: A, hasErrors: Boolean) -> Unit
): Unit = withError({ it.reduce(combine) }) {
forEachAccumulatingImpl(iterator, block)
}
@RaiseDSL
public inline fun Raise>.forEachAccumulating(
iterable: Iterable,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulating(iterable.iterator(), block)
@RaiseDSL
public inline fun Raise>.forEachAccumulating(
sequence: Sequence,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulating(sequence.iterator(), block)
@RaiseDSL
public inline fun Raise>.forEachAccumulating(
iterator: Iterator,
@BuilderInference block: RaiseAccumulate.(A) -> Unit
): Unit = forEachAccumulatingImpl(iterator) { item, _ -> block(item) }
/**
* Allows to change what to do once the first error is raised.
* Used to provide more performant [mapOrAccumulate].
*/
@PublishedApi @JvmSynthetic @OptIn(ExperimentalRaiseAccumulateApi::class)
internal inline fun Raise>.forEachAccumulatingImpl(
iterator: Iterator,
@BuilderInference block: RaiseAccumulate.(item: A, hasErrors: Boolean) -> Unit
): Unit = accumulate {
iterator.forEach {
accumulating { block(it, hasErrors()) }
}
}
/**
* Transform every element of [iterable] using the given [transform], or accumulate all the occurred errors using [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.mapOrAccumulate(
iterable: Iterable,
combine: (Error, Error) -> Error,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): List = buildList(iterable.collectionSizeOrDefault(10)) {
forEachAccumulatingImpl(iterable.iterator(), combine) { item, hasErrors ->
transform(item).also { if (!hasErrors) add(it) }
}
}
/**
* Accumulate the errors obtained by executing the [transform] over every element of [iterable].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.mapOrAccumulate(
iterable: Iterable,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): List = buildList(iterable.collectionSizeOrDefault(10)) {
forEachAccumulatingImpl(iterable.iterator()) { item, hasErrors ->
transform(item).also { if (!hasErrors) add(it) }
}
}
/**
* Transform every element of [sequence] using the given [transform], or accumulate all the occurred errors using [combine].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise.mapOrAccumulate(
sequence: Sequence,
combine: (Error, Error) -> Error,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): List = buildList {
forEachAccumulatingImpl(sequence.iterator(), combine) { item, hasErrors ->
transform(item).also { if (!hasErrors) add(it) }
}
}
/**
* Accumulate the errors obtained by executing the [transform] over every element of [sequence].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
public inline fun Raise>.mapOrAccumulate(
sequence: Sequence,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): List = buildList {
forEachAccumulatingImpl(sequence.iterator()) { item, hasErrors ->
transform(item).also { if (!hasErrors) add(it) }
}
}
/**
* Accumulate the errors obtained by executing the [transform] over every element of [NonEmptyList].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
@Suppress("WRONG_INVOCATION_KIND")
public inline fun Raise>.mapOrAccumulate(
nonEmptyList: NonEmptyList,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): NonEmptyList {
// For a NonEmptyList to be returned, there must be a B, which can only be produced by transform
// thus transform must be called at least once (or alternatively an error is raised or an exception is thrown etc)
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return requireNotNull(mapOrAccumulate(nonEmptyList.all) { transform(it) }.toNonEmptyListOrNull())
}
/**
* Accumulate the errors obtained by executing the [transform] over every element of [NonEmptySet].
*
* See the Arrow docs for more information over
* [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors)
* and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/).
*/
@RaiseDSL
@Suppress("WRONG_INVOCATION_KIND")
public inline fun Raise>.mapOrAccumulate(
nonEmptySet: NonEmptySet,
@BuilderInference transform: RaiseAccumulate.(A) -> B
): NonEmptySet {
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return buildSet(nonEmptySet.size) {
forEachAccumulatingImpl(nonEmptySet.iterator()) { item, hasErrors ->
transform(item).also { if (!hasErrors) add(it) }
}
}.toNonEmptySetOrNull()!!
}
@RaiseDSL
@Deprecated(
message = "Deprecated to allow for future alignment with stdlib Map#map returning List",
replaceWith = ReplaceWith("mapValuesOrAccumulate(map, combine, transform)"),
)
public inline fun Raise.mapOrAccumulate(
map: Map,
combine: (Error, Error) -> Error,
@BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B
): Map = mapValuesOrAccumulate(map, combine, transform)
@RaiseDSL
@Deprecated(
message = "Deprecated to allow for future alignment with stdlib Map#map returning List",
replaceWith = ReplaceWith("mapValuesOrAccumulate(map, transform)")
)
public inline fun Raise>.mapOrAccumulate(
map: Map,
@BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B
): Map = mapValuesOrAccumulate(map, transform)
@RaiseDSL
public inline fun Raise.mapValuesOrAccumulate(
map: Map,
combine: (Error, Error) -> Error,
@BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B
): Map = buildMap(map.size) {
forEachAccumulatingImpl(map.entries.iterator(), combine) { item, hasErrors ->
transform(item).also { if (!hasErrors) put(item.key, it) }
}
}
@RaiseDSL
public inline fun Raise>.mapValuesOrAccumulate(
map: Map,
@BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B
): Map = buildMap(map.size) {
forEachAccumulatingImpl(map.entries.iterator()) { item, hasErrors ->
transform(item).also { if (!hasErrors) put(item.key, it) }
}
}
@RequiresOptIn(level = RequiresOptIn.Level.WARNING, message = "This API is work-in-progress and is subject to change.")
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
public annotation class ExperimentalRaiseAccumulateApi
@ExperimentalRaiseAccumulateApi
public inline fun Raise>.accumulate(
block: RaiseAccumulate.() -> A
): A {
contract { callsInPlace(block, EXACTLY_ONCE) }
val nel = RaiseAccumulate(this)
val result = block(nel)
if (nel.hasErrors()) nel.raiseErrors()
return result
}
@ExperimentalRaiseAccumulateApi
public inline fun accumulate(
raise: (Raise>.() -> A) -> R,
crossinline block: RaiseAccumulate.() -> A
): R {
contract {
callsInPlace(raise, EXACTLY_ONCE)
}
return raise { accumulate(block) }
}
/**
* Receiver type belonging to [mapOrAccumulate].
* Allows binding both [Either] and [EitherNel] values for [Either.Left] types of [Error].
* It extends [Raise] of [Error], and allows working over [Raise] of [NonEmptyList] of [Error] as well.
*/
public open class RaiseAccumulate(
public val raise: Raise>
) : Raise {
internal val errors: MutableList = mutableListOf()
@RaiseDSL
public override fun raise(r: Error): Nothing =
raise.raise((errors + r).toNonEmptyListOrNull()!!)
public override fun Map>.bindAll(): Map =
raise.mapValuesOrAccumulate(this) { it.value.bind() }
@RaiseDSL
public inline fun Iterable.mapOrAccumulate(
transform: RaiseAccumulate.(A) -> B
): List = raise.mapOrAccumulate(this, transform)
@RaiseDSL
public inline fun NonEmptyList.mapOrAccumulate(
transform: RaiseAccumulate.(A) -> B
): NonEmptyList {
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return raise.mapOrAccumulate(this, transform)
}
@RaiseDSL
public inline fun NonEmptySet.mapOrAccumulate(
transform: RaiseAccumulate.(A) -> B
): NonEmptySet {
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return raise.mapOrAccumulate(this, transform)
}
@RaiseDSL
public inline fun Map.mapOrAccumulate(
transform: RaiseAccumulate.(Map.Entry) -> B
): List = raise.mapOrAccumulate(entries, transform)
@RaiseDSL
public inline fun Map.mapValuesOrAccumulate(
transform: RaiseAccumulate.(Map.Entry) -> B
): Map = raise.mapValuesOrAccumulate(this, transform)
@RaiseDSL
@JvmName("_mapOrAccumulate")
public inline fun mapOrAccumulate(
iterable: Iterable,
transform: RaiseAccumulate.(A) -> B
): List = raise.mapOrAccumulate(iterable, transform)
@RaiseDSL
@JvmName("_mapOrAccumulate")
public inline fun mapOrAccumulate(
list: NonEmptyList,
transform: RaiseAccumulate.(A) -> B
): NonEmptyList {
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return raise.mapOrAccumulate(list, transform)
}
@RaiseDSL
@JvmName("_mapOrAccumulate")
public inline fun mapOrAccumulate(
set: NonEmptySet,
transform: RaiseAccumulate.(A) -> B
): NonEmptySet {
contract { callsInPlace(transform, AT_LEAST_ONCE) }
return raise.mapOrAccumulate(set, transform)
}
@RaiseDSL
override fun Iterable>.bindAll(): List =
mapOrAccumulate { it.bind() }
override fun NonEmptyList