All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.arrow.core.raise.RaiseAccumulate.kt Maven / Gradle / Ivy

There is a newer version: 2.0.1
Show newest version
@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>.bindAll(): NonEmptyList =
    mapOrAccumulate { it.bind() }

  override fun  NonEmptySet>.bindAll(): NonEmptySet =
    mapOrAccumulate { it.bind() }

  @RaiseDSL
  public fun  EitherNel.bindNel(): A = when (this) {
    is Either.Left -> raise.raise(value)
    is Either.Right -> value
  }

  @RaiseDSL
  public inline fun  withNel(block: Raise>.() -> A): A {
    contract {
      callsInPlace(block, EXACTLY_ONCE)
    }
    return block(raise)
  }

  @PublishedApi internal fun addErrors(newErrors: Iterable) { errors.addAll(newErrors) }
  @PublishedApi internal fun hasErrors(): Boolean = errors.isNotEmpty()
  @PublishedApi internal fun raiseErrors(): Nothing = raise.raise(errors.toNonEmptyListOrNull()!!)

  @ExperimentalRaiseAccumulateApi
  public fun  Either.bindOrAccumulate(): Value =
    accumulating { [email protected]() }

  @ExperimentalRaiseAccumulateApi
  public fun  Iterable>.bindAllOrAccumulate(): Value> =
    accumulating { [email protected]() }

  @ExperimentalRaiseAccumulateApi
  public fun  EitherNel.bindNelOrAccumulate(): Value =
    accumulating { [email protected]() }

  @ExperimentalRaiseAccumulateApi
  public inline fun ensureOrAccumulate(condition: Boolean, raise: () -> Error) {
    contract { callsInPlace(raise, AT_MOST_ONCE) }
    accumulating { ensure(condition, raise) }
  }

  @ExperimentalRaiseAccumulateApi
  public inline fun  ensureNotNullOrAccumulate(value: B?, raise: () -> Error) {
    contract { callsInPlace(raise, AT_MOST_ONCE) }
    ensureOrAccumulate(value != null, raise)
  }

  @ExperimentalRaiseAccumulateApi
  public inline fun  accumulating(block: RaiseAccumulate.() -> A): Value {
    contract { callsInPlace(block, AT_MOST_ONCE) }
    return recover(inner@{
      Ok(block(RaiseAccumulate(this@inner)))
    }) {
      addErrors(it)
      Error()
    }
  }

  public inline operator fun  Value.getValue(thisRef: Nothing?, property: KProperty<*>): A = value

  public sealed interface Value {
    public val value: A
  }

  @PublishedApi internal inner class Error: Value {
    // WARNING: do not turn this into a property with initializer!!
    //          'raiseErrors' is then executed eagerly, and leads to wrong behavior!!
    override val value get(): Nothing = raiseErrors()
  }

  @PublishedApi internal class Ok(override val value: A): Value
}