From 88edce8894ae8c7daa7e7c0d6c2525713a8dd488 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 19:05:23 +0200 Subject: [PATCH 001/108] Initial commit --- .github/renovate.json | 6 +++ .github/workflows/build.yaml | 71 ++++++++++++++++++++++++++++ src/commonMain/kotlin/example.kt | 37 +++++++++++++++ src/commonTest/kotlin/ExampleSpec.kt | 12 +++++ 4 files changed, 126 insertions(+) create mode 100644 .github/renovate.json create mode 100644 .github/workflows/build.yaml create mode 100644 src/commonMain/kotlin/example.kt create mode 100644 src/commonTest/kotlin/ExampleSpec.kt diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000000..72240caadae --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,6 @@ +{ + "lockFileMaintenance": { + "enabled": true, + "automerge": true + } +} diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 00000000000..51db0bb91b7 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,71 @@ +name: "Build" + +on: pull_request + +env: + JAVA_OPTS: -Xms1g -Xmx3g + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + +jobs: + + linux_jvm_and_js: + runs-on: ubuntu-latest + timeout-minutes: 25 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Restore Gradle cache + id: cache + uses: actions/cache@v2.1.6 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.konan + key: linux-step-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + linux-step-gradle- + - name: Build + + run: ./gradlew linuxX64Test jvmTest jsTest + + - name: "Prepare test reports" + if: ${{ always() }} + run: | + mkdir test-reports + for report in `ls -d build/reports/tests`; do + module=$(echo $report | cut -d/ -f3) + cp -r $report test-reports/$module + done + - name: "Make test reports available to download" + if: ${{ always() }} + uses: actions/upload-artifact@v2 + with: + name: test-reports + path: test-reports + + windows: + runs-on: windows-latest + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Restore Gradle cache + id: cache + uses: actions/cache@v2.1.6 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.konan + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Build + run: ./gradlew mingwX64Test diff --git a/src/commonMain/kotlin/example.kt b/src/commonMain/kotlin/example.kt new file mode 100644 index 00000000000..0d6358e3201 --- /dev/null +++ b/src/commonMain/kotlin/example.kt @@ -0,0 +1,37 @@ +@file:Suppress("RedundantSuspendModifier") + +import arrow.core.Either +import arrow.core.Either.Left +import arrow.core.Either.Right +import arrow.core.computations.either + +object Lettuce +object Knife +object Salad + +sealed class CookingException { + object LettuceIsRotten : CookingException() + object KnifeNeedsSharpening : CookingException() + data class InsufficientAmount(val quantityInGrams: Int) : CookingException() +} + +typealias NastyLettuce = CookingException.LettuceIsRotten +typealias KnifeIsDull = CookingException.KnifeNeedsSharpening +typealias InsufficientAmountOfLettuce = CookingException.InsufficientAmount + +fun takeFoodFromRefrigerator(): Either = + Right(Lettuce) + +suspend fun getKnife(): Either = + Right(Knife) + +fun prepare(tool: Knife, ingredient: Lettuce): Either = + Left(InsufficientAmountOfLettuce(5)) + +suspend fun prepareLunch(): Either = + either { + val lettuce = takeFoodFromRefrigerator().bind() + val knife = getKnife().bind() + val lunch = prepare(knife, lettuce).bind() + lunch + } diff --git a/src/commonTest/kotlin/ExampleSpec.kt b/src/commonTest/kotlin/ExampleSpec.kt new file mode 100644 index 00000000000..c657e86b586 --- /dev/null +++ b/src/commonTest/kotlin/ExampleSpec.kt @@ -0,0 +1,12 @@ +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe + +class ExampleSpec : StringSpec({ + "true shouldBe true" { + true shouldBe true + } + + "exception should fail" { +// throw RuntimeException("Boom2!") + } +}) From 825f5e6f28f1e8971181806d517e70b1ac547598 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 19:22:57 +0200 Subject: [PATCH 002/108] Initial impl --- src/commonMain/kotlin/Cont.kt | 96 +++++++++++++ src/commonMain/kotlin/either.kt | 4 + src/commonMain/kotlin/example.kt | 37 ----- src/commonMain/kotlin/option.kt | 26 ++++ src/commonTest/kotlin/ContSpec.kt | 193 +++++++++++++++++++++++++++ src/commonTest/kotlin/ExampleSpec.kt | 12 -- 6 files changed, 319 insertions(+), 49 deletions(-) create mode 100644 src/commonMain/kotlin/Cont.kt create mode 100644 src/commonMain/kotlin/either.kt delete mode 100644 src/commonMain/kotlin/example.kt create mode 100644 src/commonMain/kotlin/option.kt create mode 100644 src/commonTest/kotlin/ContSpec.kt delete mode 100644 src/commonTest/kotlin/ExampleSpec.kt diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt new file mode 100644 index 00000000000..e57613c6f75 --- /dev/null +++ b/src/commonMain/kotlin/Cont.kt @@ -0,0 +1,96 @@ +import arrow.core.Either +import arrow.core.Validated +import arrow.core.identity +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract +import kotlin.coroutines.Continuation +import kotlin.coroutines.cancellation.CancellationException +import kotlin.coroutines.resume +import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn +import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn +import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED +import kotlin.coroutines.resumeWithException + +public fun cont(f: suspend ContEffect.() -> A): Cont = + Continuation(f) + +/** + * A Continuation of type [R] and [A] will + * - "Successfully" complete with a value of [A]. + * - Short-circuit with a value of [R]. + */ +public interface Cont { + suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B +} + +interface ContEffect { + public suspend fun shift(r: R): B + + public suspend fun Cont.bind(): B = + fold(this@ContEffect::shift, ::identity) + + public suspend fun Either.bind(): B = + when (this) { + is Either.Left -> shift(value) + is Either.Right -> value + } + + public suspend fun Validated.bind(): B = + when (this) { + is Validated.Valid -> value + is Validated.Invalid -> shift(value) + } + + public suspend fun Result.bind(transform: (Throwable) -> R): B = + fold(::identity) { throwable -> + shift(transform(throwable)) + } + + public suspend fun ensure(value: Boolean, shift: () -> R): Unit = + if (value) Unit else shift(shift()) +} + +@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. +public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { + contract { returns() implies (value != null) } + return value ?: shift(shift()) +} + +// We create a `Token` for every scope, so we can properly differentiate between nested scopes +private class ShiftCancellationException(val token: Token) : CancellationException("Shifted Continuation") + +private class Token { + override fun toString(): String = "Token(${hashCode().toUInt().toString(16)})" +} + +private class Continuation(private val f: suspend ContEffect.() -> A) : Cont { + override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = + suspendCoroutineUninterceptedOrReturn { cont -> + var token: Token? = null + var shifted: B? = null + val effect = object : ContEffect { + // Shift away from this Continuation by intercepting it, and completing it. + // The Continuation we grab here, is the same one from line 25 which is constructed on line 40 + // So this is a single continuation, completing it with it's final value means the remainder of the + // continuation program is short-circuited + override suspend fun shift(r: R): B { + shifted = f(r) + token = Token() + return suspendCoroutineUninterceptedOrReturn { contB -> + contB.resumeWithException(ShiftCancellationException(token!!)) + COROUTINE_SUSPENDED + } + } + } + + suspend { + val a = f(effect) + g(a) + }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> + res.fold(cont::resume) { throwable -> + if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted!!) + else cont.resumeWith(res) + } + }) + } +} diff --git a/src/commonMain/kotlin/either.kt b/src/commonMain/kotlin/either.kt new file mode 100644 index 00000000000..da21b744ccd --- /dev/null +++ b/src/commonMain/kotlin/either.kt @@ -0,0 +1,4 @@ +import arrow.core.Either + +suspend fun either(f: suspend ContEffect.() -> A): Either = + cont(f).fold({ Either.Left(it) }) { Either.Right(it) } diff --git a/src/commonMain/kotlin/example.kt b/src/commonMain/kotlin/example.kt deleted file mode 100644 index 0d6358e3201..00000000000 --- a/src/commonMain/kotlin/example.kt +++ /dev/null @@ -1,37 +0,0 @@ -@file:Suppress("RedundantSuspendModifier") - -import arrow.core.Either -import arrow.core.Either.Left -import arrow.core.Either.Right -import arrow.core.computations.either - -object Lettuce -object Knife -object Salad - -sealed class CookingException { - object LettuceIsRotten : CookingException() - object KnifeNeedsSharpening : CookingException() - data class InsufficientAmount(val quantityInGrams: Int) : CookingException() -} - -typealias NastyLettuce = CookingException.LettuceIsRotten -typealias KnifeIsDull = CookingException.KnifeNeedsSharpening -typealias InsufficientAmountOfLettuce = CookingException.InsufficientAmount - -fun takeFoodFromRefrigerator(): Either = - Right(Lettuce) - -suspend fun getKnife(): Either = - Right(Knife) - -fun prepare(tool: Knife, ingredient: Lettuce): Either = - Left(InsufficientAmountOfLettuce(5)) - -suspend fun prepareLunch(): Either = - either { - val lettuce = takeFoodFromRefrigerator().bind() - val knife = getKnife().bind() - val lunch = prepare(knife, lettuce).bind() - lunch - } diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt new file mode 100644 index 00000000000..e6bdeb7e042 --- /dev/null +++ b/src/commonMain/kotlin/option.kt @@ -0,0 +1,26 @@ +import arrow.core.None +import arrow.core.Option +import arrow.core.Some +import arrow.core.identity +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +suspend fun option(f: ContEffect.() -> A): Option = + cont { f(OptionEffect(this)) }.fold(::identity) { Some(it) } + +class OptionEffect(private val cont: ContEffect) : ContEffect by cont { + suspend fun Option.bind(): A = + when (this) { + None -> shift(None) + is Some -> value + } + + public suspend fun ensure(value: Boolean): Unit = + if (value) Unit else shift(None) +} + +@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. +public suspend fun ContEffect.ensureNotNull(value: B?): B { + contract { returns() implies (value != null) } + return value ?: shift(None) +} diff --git a/src/commonTest/kotlin/ContSpec.kt b/src/commonTest/kotlin/ContSpec.kt new file mode 100644 index 00000000000..9ed96c6a678 --- /dev/null +++ b/src/commonTest/kotlin/ContSpec.kt @@ -0,0 +1,193 @@ +import arrow.core.Either +import arrow.core.identity +import arrow.core.left +import arrow.core.right +import io.kotest.assertions.fail +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.boolean +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.orNull +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll +import kotlin.coroutines.Continuation +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED +import kotlin.coroutines.intrinsics.intercepted +import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn +import kotlin.coroutines.startCoroutine +import kotlin.time.Duration +import kotlin.time.ExperimentalTime +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withTimeout + +@OptIn(ExperimentalTime::class) +class ContSpec : StringSpec({ + + suspend fun Cont.value(): A = + fold(::identity, ::identity) + + "immediate values" { + cont { + 1 + }.value() shouldBe 1 + } + + "suspended value" { + cont { + 1.suspend() + }.value() shouldBe 1 + } + + "immediate short-circuit" { + cont { + shift("hello") + }.fold(::identity, ::identity) shouldBe "hello" + } + + "suspended short-circuit" { + cont { + shift("hello".suspend()) + }.fold(::identity, ::identity) shouldBe "hello" + } + + "Rethrows immediate exceptions" { + val e = RuntimeException("test") + Either.catch { + cont { + throw e + }.value() + } shouldBe Either.Left(e) + } + + "Rethrows suspended exceptions" { + val e = RuntimeException("test") + Either.catch { + cont { + e.suspend() + }.value() + } shouldBe Either.Left(e) + } + + "Can short-circuit immediately from nested blocks" { + cont { + cont { shift("test") }.value() + fail("Should never reach this point") + }.fold(::identity, ::identity) shouldBe "test" + } + + "Can short-circuit suspended from nested blocks" { + cont { + cont { shift("test".suspend()) }.value() + fail("Should never reach this point") + }.fold(::identity, ::identity) shouldBe "test" + } + + "Can short-circuit immediately after suspending from nested blocks" { + cont { + cont { + 1L.suspend() + shift("test".suspend()) + }.value() + fail("Should never reach this point") + }.fold(::identity, ::identity) shouldBe "test" + } + + // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 + "ensure null in either computation" { + checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> + either { + ensure(predicate) { shift } + success + } shouldBe if (predicate) success.right() else shift.left() + } + } + + // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 + "ensureNotNull in either computation" { + fun square(i: Int): Int = i * i + + checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, shift: String -> + val res = either { + val ii = i + ensureNotNull(ii) { shift } + square(ii) // Smart-cast by contract + } + val expected = i?.let(::square)?.right() ?: shift.left() + res shouldBe expected + } + } + + "Short-circuiting co-operates with KotlinX Structured Concurrency" { + val latch = CompletableDeferred() + val cancelled = CompletableDeferred() + + cont { + coroutineScope { + val never = async(Dispatchers.Default) { completeOnCancellation(latch, cancelled) } + val fail = async(Dispatchers.Default) { + latch.await() + shift("hello") + } + fail.await() // When this fails, it should also close never + never.await() + } + }.fold(::identity, ::identity) shouldBe "hello" + + withTimeout(Duration.Companion.seconds(2)) { + cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" + } + } + + "Computation blocks run on parent context" { + val parentCtx = currentContext() + cont { + currentContext() shouldBe parentCtx + }.value() + } +}) + +suspend fun currentContext(): CoroutineContext = + kotlin.coroutines.coroutineContext + +internal suspend fun Throwable.suspend(): Nothing = + suspendCoroutineUninterceptedOrReturn { cont -> + suspend { throw this }.startCoroutine( + Continuation(Dispatchers.Default) { + cont.intercepted().resumeWith(it) + } + ) + + COROUTINE_SUSPENDED + } + +internal suspend fun A.suspend(): A = + suspendCoroutineUninterceptedOrReturn { cont -> + suspend { this }.startCoroutine( + Continuation(Dispatchers.Default) { + cont.intercepted().resumeWith(it) + } + ) + + COROUTINE_SUSPENDED + } + +suspend fun completeOnCancellation( + latch: CompletableDeferred, + cancelled: CompletableDeferred +): A = + suspendCancellableCoroutine { cont -> + cont.invokeOnCancellation { cause -> + if (!cancelled.complete(cause)) throw AssertionError("cancelled latch was completed twice") + else Unit + } + + if (!latch.complete(Unit)) throw AssertionError("latch was completed twice") + else Unit + } diff --git a/src/commonTest/kotlin/ExampleSpec.kt b/src/commonTest/kotlin/ExampleSpec.kt deleted file mode 100644 index c657e86b586..00000000000 --- a/src/commonTest/kotlin/ExampleSpec.kt +++ /dev/null @@ -1,12 +0,0 @@ -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe - -class ExampleSpec : StringSpec({ - "true shouldBe true" { - true shouldBe true - } - - "exception should fail" { -// throw RuntimeException("Boom2!") - } -}) From 17bc59f19c17373b57e017cbb3292589cdce2080 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 19:59:43 +0200 Subject: [PATCH 003/108] Clean up, and add ior block --- src/commonMain/kotlin/Cont.kt | 10 ++++----- src/commonMain/kotlin/either.kt | 2 +- src/commonMain/kotlin/ior.kt | 35 ++++++++++++++++++++++++++++++++ src/commonMain/kotlin/option.kt | 8 ++++---- src/commonMain/kotlin/predef.kt | 7 +++++++ src/commonTest/kotlin/IorSpec.kt | 23 +++++++++++++++++++++ 6 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 src/commonMain/kotlin/ior.kt create mode 100644 src/commonMain/kotlin/predef.kt create mode 100644 src/commonTest/kotlin/IorSpec.kt diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index e57613c6f75..8e38e3c2b68 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -11,7 +11,7 @@ import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.resumeWithException -public fun cont(f: suspend ContEffect.() -> A): Cont = +public fun cont(f: suspend ContEffect.() -> A): Cont = Continuation(f) /** @@ -23,7 +23,7 @@ public interface Cont { suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B } -interface ContEffect { +interface ContEffect { public suspend fun shift(r: R): B public suspend fun Cont.bind(): B = @@ -51,7 +51,7 @@ interface ContEffect { } @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. -public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { +public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { contract { returns() implies (value != null) } return value ?: shift(shift()) } @@ -63,12 +63,12 @@ private class Token { override fun toString(): String = "Token(${hashCode().toUInt().toString(16)})" } -private class Continuation(private val f: suspend ContEffect.() -> A) : Cont { +private class Continuation(private val f: suspend ContEffect.() -> A) : Cont { override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> var token: Token? = null var shifted: B? = null - val effect = object : ContEffect { + val effect = object : ContEffect { // Shift away from this Continuation by intercepting it, and completing it. // The Continuation we grab here, is the same one from line 25 which is constructed on line 40 // So this is a single continuation, completing it with it's final value means the remainder of the diff --git a/src/commonMain/kotlin/either.kt b/src/commonMain/kotlin/either.kt index da21b744ccd..9bd5ebfd72f 100644 --- a/src/commonMain/kotlin/either.kt +++ b/src/commonMain/kotlin/either.kt @@ -1,4 +1,4 @@ import arrow.core.Either -suspend fun either(f: suspend ContEffect.() -> A): Either = +suspend fun either(f: suspend ContEffect.() -> A): Either = cont(f).fold({ Either.Left(it) }) { Either.Right(it) } diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt new file mode 100644 index 00000000000..b643b05acfb --- /dev/null +++ b/src/commonMain/kotlin/ior.kt @@ -0,0 +1,35 @@ +import arrow.core.Ior +import arrow.core.identity +import arrow.typeclasses.Semigroup + +suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior = + cont> { + val effect = IorEffect(semigroup, this) + val res = f(effect) + if (effect.leftState === EmptyValue) Ior.Right(res) + else Ior.Both(EmptyValue.unbox(effect.leftState), res) + }.fold({ Ior.Left(it) }, ::identity) + +class IorEffect(semigroup: Semigroup, private val cont: ContEffect) : ContEffect, + Semigroup by semigroup { + internal var leftState: Any? = EmptyValue + + private fun combine(other: E): E = + if (leftState === EmptyValue) { + leftState = other + other + } else EmptyValue.unbox(leftState).combine(other) + + suspend fun Ior.bind(): B = + when (this) { + is Ior.Left -> shift(value) + is Ior.Right -> value + is Ior.Both -> { + leftState = combine(leftValue) + rightValue + } + } + + override suspend fun shift(r: E): B = + cont.shift(combine(r)) +} diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt index e6bdeb7e042..0b70590829c 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/option.kt @@ -5,11 +5,11 @@ import arrow.core.identity import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract -suspend fun option(f: ContEffect.() -> A): Option = +suspend fun option(f: OptionEffect.() -> A): Option = cont { f(OptionEffect(this)) }.fold(::identity) { Some(it) } -class OptionEffect(private val cont: ContEffect) : ContEffect by cont { - suspend fun Option.bind(): A = +class OptionEffect(private val cont: ContEffect) : ContEffect by cont { + suspend fun Option.bind(): B = when (this) { None -> shift(None) is Some -> value @@ -20,7 +20,7 @@ class OptionEffect(private val cont: ContEffect) : ContEffect ContEffect.ensureNotNull(value: B?): B { +public suspend fun ContEffect.ensureNotNull(value: B?): B { contract { returns() implies (value != null) } return value ?: shift(None) } diff --git a/src/commonMain/kotlin/predef.kt b/src/commonMain/kotlin/predef.kt new file mode 100644 index 00000000000..496aa7ecb77 --- /dev/null +++ b/src/commonMain/kotlin/predef.kt @@ -0,0 +1,7 @@ + +@PublishedApi +internal object EmptyValue { + @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") + public inline fun unbox(value: Any?): A = + if (value === this) null as A else value as A +} diff --git a/src/commonTest/kotlin/IorSpec.kt b/src/commonTest/kotlin/IorSpec.kt new file mode 100644 index 00000000000..36c2525009f --- /dev/null +++ b/src/commonTest/kotlin/IorSpec.kt @@ -0,0 +1,23 @@ +import arrow.core.Either +import arrow.core.Ior +import arrow.typeclasses.Semigroup +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe + +class IorSpec : StringSpec({ + "Accumulates" { + ior(Semigroup.string()) { + val one = Ior.Both("Hello", 1).bind() + val two = Ior.Both(", World!", 2).bind() + one + two + } shouldBe Ior.Both("Hello, World!", 3) + } + + "Accumulates with Either" { + ior(Semigroup.string()) { + val one = Ior.Both("Hello", 1).bind() + val two: Int = Either.Left(", World!").bind() + one + two + } shouldBe Ior.Left("Hello, World!") + } +}) From d79382a594901f47b7a63869ab0b98ac9d33aff1 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 20:07:15 +0200 Subject: [PATCH 004/108] Reformat --- src/commonMain/kotlin/ior.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt index b643b05acfb..20cd521b2ad 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/ior.kt @@ -10,8 +10,11 @@ suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A) else Ior.Both(EmptyValue.unbox(effect.leftState), res) }.fold({ Ior.Left(it) }, ::identity) -class IorEffect(semigroup: Semigroup, private val cont: ContEffect) : ContEffect, - Semigroup by semigroup { +class IorEffect( + semigroup: Semigroup, + private val cont: ContEffect +) : ContEffect, Semigroup by semigroup { + internal var leftState: Any? = EmptyValue private fun combine(other: E): E = From 5678c42aabdfc4bc9ec46b037c03bf608b57415c Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 21:57:37 +0200 Subject: [PATCH 005/108] Add Cont#toEither, and optimise OptionEffect --- src/commonMain/kotlin/Cont.kt | 6 ++++++ src/commonMain/kotlin/either.kt | 2 +- src/commonMain/kotlin/option.kt | 14 +++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 8e38e3c2b68..0df62972931 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -21,6 +21,12 @@ public fun cont(f: suspend ContEffect.() -> A): Cont = */ public interface Cont { suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B + + suspend fun toEither(): Either = + fold({ Either.Left(it) }) { Either.Right(it) } + + suspend fun toValidated(): Validated = + fold({ Validated.Invalid(it) }) { Validated.Valid(it) } } interface ContEffect { diff --git a/src/commonMain/kotlin/either.kt b/src/commonMain/kotlin/either.kt index 9bd5ebfd72f..e43c4fcf345 100644 --- a/src/commonMain/kotlin/either.kt +++ b/src/commonMain/kotlin/either.kt @@ -1,4 +1,4 @@ import arrow.core.Either suspend fun either(f: suspend ContEffect.() -> A): Either = - cont(f).fold({ Either.Left(it) }) { Either.Right(it) } + cont(f).toEither() diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt index 0b70590829c..e93b0837a28 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/option.kt @@ -4,11 +4,16 @@ import arrow.core.Some import arrow.core.identity import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract +import kotlin.jvm.JvmInline -suspend fun option(f: OptionEffect.() -> A): Option = - cont { f(OptionEffect(this)) }.fold(::identity) { Some(it) } +suspend fun option(f: OptionEffect.() -> A): Option = + cont { f(OptionEffect(this)) }.toOption() -class OptionEffect(private val cont: ContEffect) : ContEffect by cont { +suspend fun Cont.toOption(): Option = + fold(::identity) { Some(it) } + +@JvmInline +value class OptionEffect(private val cont: ContEffect) : ContEffect { suspend fun Option.bind(): B = when (this) { None -> shift(None) @@ -17,6 +22,9 @@ class OptionEffect(private val cont: ContEffect) : ContEffect by public suspend fun ensure(value: Boolean): Unit = if (value) Unit else shift(None) + + override suspend fun shift(r: None): B = + cont.shift(r) } @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. From d1b098501afe64b6fd80ea1104280fc6d06150dd Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 23:21:14 +0200 Subject: [PATCH 006/108] Add some docs --- src/commonMain/kotlin/Cont.kt | 34 +++++++++++++++++++++++++-------- src/commonMain/kotlin/option.kt | 8 ++++---- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 0df62972931..e7d5d919f13 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -1,4 +1,7 @@ import arrow.core.Either +import arrow.core.None +import arrow.core.Option +import arrow.core.Some import arrow.core.Validated import arrow.core.identity import kotlin.contracts.ExperimentalContracts @@ -10,14 +13,17 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.resumeWithException +import kotlin.jvm.JvmInline public fun cont(f: suspend ContEffect.() -> A): Cont = Continuation(f) /** - * A Continuation of type [R] and [A] will - * - "Successfully" complete with a value of [A]. + * [Cont] represents a suspending computation that runs will either + * - Complete with a value of [A]. * - Short-circuit with a value of [R]. + * + * So [Cont] is defined by [fold], to map both values of [R] and [A] to a value of `B`. */ public interface Cont { suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B @@ -29,7 +35,11 @@ public interface Cont { fold({ Validated.Invalid(it) }) { Validated.Valid(it) } } +/** Context of the [Cont] DSL. */ interface ContEffect { + /** + * Short-circuit the [Cont] computation with value [R]. + */ public suspend fun shift(r: R): B public suspend fun Cont.bind(): B = @@ -52,11 +62,17 @@ interface ContEffect { shift(transform(throwable)) } + public suspend fun Option.bind(shift: () -> R): B = + when (this) { + None -> shift(shift()) + is Some -> value + } + public suspend fun ensure(value: Boolean, shift: () -> R): Unit = if (value) Unit else shift(shift()) } -@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. +@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so top-level. public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { contract { returns() implies (value != null) } return value ?: shift(shift()) @@ -65,20 +81,22 @@ public suspend fun ContEffect.ensureNotNull(value: B?, shift: () // We create a `Token` for every scope, so we can properly differentiate between nested scopes private class ShiftCancellationException(val token: Token) : CancellationException("Shifted Continuation") +// Class that represents a unique token by hash comparison private class Token { override fun toString(): String = "Token(${hashCode().toUInt().toString(16)})" } -private class Continuation(private val f: suspend ContEffect.() -> A) : Cont { +// Reification of Cont program +@JvmInline +private value class Continuation(private val f: suspend ContEffect.() -> A) : Cont { override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> var token: Token? = null var shifted: B? = null val effect = object : ContEffect { - // Shift away from this Continuation by intercepting it, and completing it. - // The Continuation we grab here, is the same one from line 25 which is constructed on line 40 - // So this is a single continuation, completing it with it's final value means the remainder of the - // continuation program is short-circuited + // Shift away from this Continuation by intercepting it, and completing it with ShiftCancellationException + // This is needed because this function will never yield a result, + // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B { shifted = f(r) token = Token() diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt index e93b0837a28..16bdf97ce49 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/option.kt @@ -12,13 +12,13 @@ suspend fun option(f: OptionEffect.() -> A): Option = suspend fun Cont.toOption(): Option = fold(::identity) { Some(it) } +// Can be replaced by multiple receivers +// context(ContEffect) +// fun Option.bind(): A = ... @JvmInline value class OptionEffect(private val cont: ContEffect) : ContEffect { suspend fun Option.bind(): B = - when (this) { - None -> shift(None) - is Some -> value - } + bind { None } public suspend fun ensure(value: Boolean): Unit = if (value) Unit else shift(None) From 9d6448b2dae5ab6d947373e2f21fff1ff7cd3307 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 30 Oct 2021 23:52:57 +0200 Subject: [PATCH 007/108] Concurrency fix Ior --- src/commonMain/kotlin/Cont.kt | 6 ++---- src/commonMain/kotlin/ior.kt | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index e7d5d919f13..b2ff0bc17b3 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -91,6 +91,7 @@ private class Token { private value class Continuation(private val f: suspend ContEffect.() -> A) : Cont { override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> + // TODO: Fix, and test concurrency var token: Token? = null var shifted: B? = null val effect = object : ContEffect { @@ -107,10 +108,7 @@ private value class Continuation(private val f: suspend ContEffect.() - } } - suspend { - val a = f(effect) - g(a) - }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> + suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> res.fold(cont::resume) { throwable -> if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted!!) else cont.resumeWith(res) diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt index 20cd521b2ad..52be4a01675 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/ior.kt @@ -1,3 +1,5 @@ +import arrow.continuations.generic.AtomicRef +import arrow.continuations.generic.updateAndGet import arrow.core.Ior import arrow.core.identity import arrow.typeclasses.Semigroup @@ -6,8 +8,9 @@ suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A) cont> { val effect = IorEffect(semigroup, this) val res = f(effect) - if (effect.leftState === EmptyValue) Ior.Right(res) - else Ior.Both(EmptyValue.unbox(effect.leftState), res) + val state = effect.leftState.get() + if (state === EmptyValue) Ior.Right(res) + else Ior.Both(EmptyValue.unbox(state), res) }.fold({ Ior.Left(it) }, ::identity) class IorEffect( @@ -15,20 +18,20 @@ class IorEffect( private val cont: ContEffect ) : ContEffect, Semigroup by semigroup { - internal var leftState: Any? = EmptyValue + internal var leftState: AtomicRef = AtomicRef(EmptyValue) private fun combine(other: E): E = - if (leftState === EmptyValue) { - leftState = other - other - } else EmptyValue.unbox(leftState).combine(other) + leftState.updateAndGet { state -> + if (state === EmptyValue) other + else EmptyValue.unbox(leftState).combine(other) + } as E suspend fun Ior.bind(): B = when (this) { is Ior.Left -> shift(value) is Ior.Right -> value is Ior.Both -> { - leftState = combine(leftValue) + combine(leftValue) rightValue } } From 60ce519e9b7cebd55888dd9e82035e5ef10f69e1 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 31 Oct 2021 20:51:34 +0100 Subject: [PATCH 008/108] Add monadic syntax --- src/commonMain/kotlin/Cont.kt | 74 +++++++++++++++++-- .../{predef.kt => internal/EmptyValue.kt} | 1 + src/commonMain/kotlin/ior.kt | 9 ++- src/commonTest/kotlin/ContSpec.kt | 31 ++++++-- 4 files changed, 98 insertions(+), 17 deletions(-) rename src/commonMain/kotlin/{predef.kt => internal/EmptyValue.kt} (91%) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index b2ff0bc17b3..719295c9f9e 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -1,9 +1,12 @@ +import arrow.continuations.generic.AtomicRef +import arrow.continuations.generic.loop import arrow.core.Either import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.Validated import arrow.core.identity +import internal.EmptyValue import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation @@ -33,8 +36,32 @@ public interface Cont { suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + + fun map(f: suspend (A) -> B): Cont = + cont { fold(this::shift, f) } + + fun flatMap(f: suspend (A) -> Cont): Cont = + cont { fold(this::shift, f).bind() } + + fun handleError(f: suspend (R) -> A): Cont = + cont { fold(f, ::identity) } + + fun handleErrorWith(f: suspend (R) -> Cont): Cont = + cont { fold({ f(it).bind() }, ::identity) } + + fun redeem(f: suspend (R) -> B, g: suspend (A) -> B): Cont = + cont { fold(f, g) } + + fun redeemWith(f: suspend (R) -> Cont, g: suspend (A) -> Cont): Cont = + cont { fold(f, g).bind() } } +fun Iterable.traverseCont(f: (A) -> Cont): Cont> = + cont { map { f(it).bind() } } + +fun Iterable>.sequence(): Cont> = + traverseCont(::identity) + /** Context of the [Cont] DSL. */ interface ContEffect { /** @@ -42,6 +69,10 @@ interface ContEffect { */ public suspend fun shift(r: R): B + /** ApplicativeError alias for shift */ + public suspend fun raiseError(r: R): B = + shift(r) + public suspend fun Cont.bind(): B = fold(this@ContEffect::shift, ::identity) @@ -68,16 +99,20 @@ interface ContEffect { is Some -> value } + // Monadic version of kotlin.require public suspend fun ensure(value: Boolean, shift: () -> R): Unit = if (value) Unit else shift(shift()) } +// Monadic version of kotlin.requireNotNull @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so top-level. public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { contract { returns() implies (value != null) } return value ?: shift(shift()) } +// Full internal runtime implementation of Cont below + // We create a `Token` for every scope, so we can properly differentiate between nested scopes private class ShiftCancellationException(val token: Token) : CancellationException("Shifted Continuation") @@ -86,23 +121,48 @@ private class Token { override fun toString(): String = "Token(${hashCode().toUInt().toString(16)})" } +@JvmInline +private value class Shifted(private val state: AtomicRef = AtomicRef(EmptyValue)) { + inline fun update(f: () -> A): Boolean { + var backing: Any? = EmptyValue + state.loop { a -> + if (a === EmptyValue) { + if (state.compareAndSet( + EmptyValue, + if (backing === EmptyValue) { + backing = f() + backing + } else backing + ) + ) return true + } else { + return false + } + } + } + + fun value(): A = EmptyValue.unbox(state.get()) +} + // Reification of Cont program @JvmInline private value class Continuation(private val f: suspend ContEffect.() -> A) : Cont { override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> - // TODO: Fix, and test concurrency - var token: Token? = null - var shifted: B? = null + val token = Token() + val shifted = Shifted() + val effect = object : ContEffect { // Shift away from this Continuation by intercepting it, and completing it with ShiftCancellationException // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B { - shifted = f(r) - token = Token() + // TODO if a concurrent coroutine called shift, do we also complete with `ShiftCancellationException`? + // NOTE: This _should_ only possible if coroutines are already coupled to each-other with structured concurrency + // So re-emitting CancellationException might not be needed ?? + shifted.update { f(r) } return suspendCoroutineUninterceptedOrReturn { contB -> - contB.resumeWithException(ShiftCancellationException(token!!)) + contB.resumeWithException(ShiftCancellationException(token)) COROUTINE_SUSPENDED } } @@ -110,7 +170,7 @@ private value class Continuation(private val f: suspend ContEffect.() - suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> res.fold(cont::resume) { throwable -> - if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted!!) + if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted.value()) else cont.resumeWith(res) } }) diff --git a/src/commonMain/kotlin/predef.kt b/src/commonMain/kotlin/internal/EmptyValue.kt similarity index 91% rename from src/commonMain/kotlin/predef.kt rename to src/commonMain/kotlin/internal/EmptyValue.kt index 496aa7ecb77..c5857a1dd69 100644 --- a/src/commonMain/kotlin/predef.kt +++ b/src/commonMain/kotlin/internal/EmptyValue.kt @@ -1,3 +1,4 @@ +package internal @PublishedApi internal object EmptyValue { diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt index 52be4a01675..4688188818a 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/ior.kt @@ -3,14 +3,15 @@ import arrow.continuations.generic.updateAndGet import arrow.core.Ior import arrow.core.identity import arrow.typeclasses.Semigroup +import internal.EmptyValue suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior = cont> { val effect = IorEffect(semigroup, this) val res = f(effect) - val state = effect.leftState.get() - if (state === EmptyValue) Ior.Right(res) - else Ior.Both(EmptyValue.unbox(state), res) + val leftState = effect.leftState.get() + if (leftState === EmptyValue) Ior.Right(res) + else Ior.Both(EmptyValue.unbox(leftState), res) }.fold({ Ior.Left(it) }, ::identity) class IorEffect( @@ -23,7 +24,7 @@ class IorEffect( private fun combine(other: E): E = leftState.updateAndGet { state -> if (state === EmptyValue) other - else EmptyValue.unbox(leftState).combine(other) + else EmptyValue.unbox(state).combine(other) } as E suspend fun Ior.bind(): B = diff --git a/src/commonTest/kotlin/ContSpec.kt b/src/commonTest/kotlin/ContSpec.kt index 9ed96c6a678..565ff23fcef 100644 --- a/src/commonTest/kotlin/ContSpec.kt +++ b/src/commonTest/kotlin/ContSpec.kt @@ -4,6 +4,7 @@ import arrow.core.left import arrow.core.right import io.kotest.assertions.fail import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import io.kotest.property.Arb @@ -24,6 +25,8 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeout @@ -33,6 +36,9 @@ class ContSpec : StringSpec({ suspend fun Cont.value(): A = fold(::identity, ::identity) + suspend fun Cont<*, *>.runCont(): Unit = + fold({ }, { }) + "immediate values" { cont { 1 @@ -62,7 +68,7 @@ class ContSpec : StringSpec({ Either.catch { cont { throw e - }.value() + }.runCont() } shouldBe Either.Left(e) } @@ -71,20 +77,20 @@ class ContSpec : StringSpec({ Either.catch { cont { e.suspend() - }.value() + }.runCont() } shouldBe Either.Left(e) } "Can short-circuit immediately from nested blocks" { cont { - cont { shift("test") }.value() + cont { shift("test") }.runCont() fail("Should never reach this point") }.fold(::identity, ::identity) shouldBe "test" } "Can short-circuit suspended from nested blocks" { cont { - cont { shift("test".suspend()) }.value() + cont { shift("test".suspend()) }.runCont() fail("Should never reach this point") }.fold(::identity, ::identity) shouldBe "test" } @@ -94,7 +100,7 @@ class ContSpec : StringSpec({ cont { 1L.suspend() shift("test".suspend()) - }.value() + }.runCont() fail("Should never reach this point") }.fold(::identity, ::identity) shouldBe "test" } @@ -149,7 +155,20 @@ class ContSpec : StringSpec({ val parentCtx = currentContext() cont { currentContext() shouldBe parentCtx - }.value() + }.runCont() + } + + "Concurrent shift" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + fa.await() + fb.await() + } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + } } }) From 404b7d5d47b705afb7e5bb3845463dd2c67f85e3 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 1 Nov 2021 19:59:47 +0100 Subject: [PATCH 009/108] Fix bug shift --- src/commonMain/kotlin/Cont.kt | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 719295c9f9e..94f2d989dbc 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -14,8 +14,6 @@ import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.resume import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.resumeWithException import kotlin.jvm.JvmInline public fun cont(f: suspend ContEffect.() -> A): Cont = @@ -160,19 +158,21 @@ private value class Continuation(private val f: suspend ContEffect.() - // TODO if a concurrent coroutine called shift, do we also complete with `ShiftCancellationException`? // NOTE: This _should_ only possible if coroutines are already coupled to each-other with structured concurrency // So re-emitting CancellationException might not be needed ?? + // Related test: https://github.com/nomisRev/Continuation/blob/main/src/commonTest/kotlin/ContSpec.kt#L161 shifted.update { f(r) } - return suspendCoroutineUninterceptedOrReturn { contB -> - contB.resumeWithException(ShiftCancellationException(token)) - COROUTINE_SUSPENDED - } + throw ShiftCancellationException(token) } } - suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> - res.fold(cont::resume) { throwable -> - if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted.value()) - else cont.resumeWith(res) - } - }) + try { + suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> + res.fold(cont::resume) { throwable -> + if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted.value()) + else cont.resumeWith(res) + } + }) + } catch (e: ShiftCancellationException) { + if (token == e.token) shifted.value() else throw e + } } } From 97cb17626afae8c5322ecdec083dbefe96aefd52 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 2 Nov 2021 14:33:15 +0100 Subject: [PATCH 010/108] Add attempt --- src/commonMain/kotlin/Cont.kt | 3 +++ src/commonMain/kotlin/either.kt | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 94f2d989dbc..7c7bef6aebf 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -35,6 +35,9 @@ public interface Cont { suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + fun attempt(): Cont> = + cont { runCatching { bind() } } + fun map(f: suspend (A) -> B): Cont = cont { fold(this::shift, f) } diff --git a/src/commonMain/kotlin/either.kt b/src/commonMain/kotlin/either.kt index e43c4fcf345..f8f049e0204 100644 --- a/src/commonMain/kotlin/either.kt +++ b/src/commonMain/kotlin/either.kt @@ -1,4 +1,4 @@ import arrow.core.Either suspend fun either(f: suspend ContEffect.() -> A): Either = - cont(f).toEither() + cont(f).toEither() From 43084757deae47df6e0041980676c2fb4800a5ed Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 6 Nov 2021 20:50:00 +0100 Subject: [PATCH 011/108] Add restricted cont implementation --- src/commonMain/kotlin/RestrictedCont.kt | 100 ++++++++++++++++++ .../kotlin/ContSpec.kt | 8 +- src/{commonTest => jvmTest}/kotlin/IorSpec.kt | 0 3 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 src/commonMain/kotlin/RestrictedCont.kt rename src/{commonTest => jvmTest}/kotlin/ContSpec.kt (95%) rename src/{commonTest => jvmTest}/kotlin/IorSpec.kt (100%) diff --git a/src/commonMain/kotlin/RestrictedCont.kt b/src/commonMain/kotlin/RestrictedCont.kt new file mode 100644 index 00000000000..201f0992308 --- /dev/null +++ b/src/commonMain/kotlin/RestrictedCont.kt @@ -0,0 +1,100 @@ +import arrow.core.Either +import arrow.core.Validated +import arrow.core.identity +import internal.EmptyValue +import kotlin.coroutines.Continuation +import kotlin.coroutines.EmptyCoroutineContext +import kotlin.coroutines.RestrictsSuspension +import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED +import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn +import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn +import kotlin.jvm.JvmInline + +public fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont = + RestrictedContDsl(f) + +@RestrictsSuspension +public interface RestrictedContEffect { + + /** + * Short-circuit the [Cont] computation with value [R]. + */ + public suspend fun shift(r: R): B + + public suspend fun RestrictedCont.bind(): A { + var left: Any? = EmptyValue + var right: Any? = EmptyValue + fold({ r -> + left = r + }, { a -> + right = a + }) + return if (left === EmptyValue) EmptyValue.unbox(right) + else shift(EmptyValue.unbox(left)) + } + + + shift(r) + }, ::identity) +} + +public interface RestrictedCont { + public fun fold(f: (R) -> B, g: (A) -> B): B + + public fun toEither(): Either = + fold({ Either.Left(it) }) { Either.Right(it) } + + public fun toValidated(): Validated = + fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + + public fun map(f: (A) -> B): RestrictedCont = + flatMap { a -> + restrictedCont { f(a) } + } + + public fun flatMap(f: (A) -> RestrictedCont): RestrictedCont = + restrictedCont { f(bind()).bind() } + + public fun attempt(): RestrictedCont> = + restrictedCont { kotlin.runCatching { bind() } } + + public fun handleError(f: (R) -> A): RestrictedCont = + restrictedCont { fold(f, ::identity) } + + public fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont = + restrictedCont { + toEither().fold({ r -> + f(r).bind() + }, ::identity) + } + + public fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont = + restrictedCont { fold(f, g) } + + public fun redeemWith( + f: (R) -> RestrictedCont, + g: (A) -> RestrictedCont + ): RestrictedCont = + restrictedCont { fold(f, g).bind() } +} + +@JvmInline +private value class RestrictedContDsl(private val cont: suspend RestrictedContEffect.() -> A) : + RestrictedCont { + override fun fold(f: (R) -> B, g: (A) -> B): B { + var reset: Any? = EmptyValue + val effect = object : RestrictedContEffect { + override suspend fun shift(r: R): B = + suspendCoroutineUninterceptedOrReturn { cont -> + reset = f(r) + COROUTINE_SUSPENDED + } + } + val a: Any? = cont.startCoroutineUninterceptedOrReturn(effect, Continuation(EmptyCoroutineContext) { shifted -> + // If we reach here, then it means we shifted. + shifted.getOrThrow() + }) + return if (a === COROUTINE_SUSPENDED && reset !== EmptyValue) EmptyValue.unbox(reset) + else g(a as A) + } +} diff --git a/src/commonTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt similarity index 95% rename from src/commonTest/kotlin/ContSpec.kt rename to src/jvmTest/kotlin/ContSpec.kt index 565ff23fcef..a39e8862449 100644 --- a/src/commonTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -1,3 +1,4 @@ +import arrow.continuations.generic.AtomicRef import arrow.core.Either import arrow.core.identity import arrow.core.left @@ -22,11 +23,10 @@ import kotlin.coroutines.startCoroutine import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeout @@ -162,8 +162,8 @@ class ContSpec : StringSpec({ checkAll(Arb.int(), Arb.int()) { a, b -> cont { coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } + val fa = async(start = CoroutineStart.UNDISPATCHED) { shift(a) } + val fb = async(start = CoroutineStart.UNDISPATCHED) { shift(b) } fa.await() fb.await() } diff --git a/src/commonTest/kotlin/IorSpec.kt b/src/jvmTest/kotlin/IorSpec.kt similarity index 100% rename from src/commonTest/kotlin/IorSpec.kt rename to src/jvmTest/kotlin/IorSpec.kt From 2d3ed2124fc5954500cf7ec9d3d28b96f0519c37 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 6 Nov 2021 20:51:27 +0100 Subject: [PATCH 012/108] Run workflow on push main --- .github/workflows/build.yaml | 10 +++++++++- src/commonMain/kotlin/RestrictedCont.kt | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 51db0bb91b7..42703d3ab6f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,6 +1,14 @@ name: "Build" -on: pull_request +on: + # Trigger the workflow on push or pull request, + # but only for the main branch + push: + branches: + - main + pull_request: + branches: + - main env: JAVA_OPTS: -Xms1g -Xmx3g diff --git a/src/commonMain/kotlin/RestrictedCont.kt b/src/commonMain/kotlin/RestrictedCont.kt index 201f0992308..f57a74adfab 100644 --- a/src/commonMain/kotlin/RestrictedCont.kt +++ b/src/commonMain/kotlin/RestrictedCont.kt @@ -32,10 +32,6 @@ public interface RestrictedContEffect { return if (left === EmptyValue) EmptyValue.unbox(right) else shift(EmptyValue.unbox(left)) } - - - shift(r) - }, ::identity) } public interface RestrictedCont { From 89657b8ee6881c2d85d70d59e33bf98f42f15ef4 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 6 Nov 2021 20:56:00 +0100 Subject: [PATCH 013/108] Fix workflow --- .github/workflows/build.yaml | 48 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 42703d3ab6f..f86b54981fe 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -36,9 +36,9 @@ jobs: key: linux-step-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | linux-step-gradle- - - name: Build - run: ./gradlew linuxX64Test jvmTest jsTest + - name: Build + run: ./gradlew jvmTest - name: "Prepare test reports" if: ${{ always() }} @@ -55,25 +55,25 @@ jobs: name: test-reports path: test-reports - windows: - runs-on: windows-latest - timeout-minutes: 20 - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Restore Gradle cache - id: cache - uses: actions/cache@v2.1.6 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - ~/.konan - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- - - name: Build - run: ./gradlew mingwX64Test +# windows: +# runs-on: windows-latest +# timeout-minutes: 20 +# +# steps: +# - uses: actions/checkout@v2 +# with: +# fetch-depth: 0 +# +# - name: Restore Gradle cache +# id: cache +# uses: actions/cache@v2.1.6 +# with: +# path: | +# ~/.gradle/caches +# ~/.gradle/wrapper +# ~/.konan +# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} +# restore-keys: | +# ${{ runner.os }}-gradle- +# - name: Build +# run: ./gradlew mingwX64Test From b05bde8289599379b49deaca066c6a46b8371f49 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 6 Nov 2021 22:33:08 +0100 Subject: [PATCH 014/108] Fix try/catch over shift --- src/commonMain/kotlin/Cont.kt | 48 +++++----------------------------- src/jvmTest/kotlin/ContSpec.kt | 39 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 41 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 7c7bef6aebf..d7641f65bb4 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -1,12 +1,9 @@ -import arrow.continuations.generic.AtomicRef -import arrow.continuations.generic.loop import arrow.core.Either import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.Validated import arrow.core.identity -import internal.EmptyValue import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation @@ -114,68 +111,37 @@ public suspend fun ContEffect.ensureNotNull(value: B?, shift: () // Full internal runtime implementation of Cont below -// We create a `Token` for every scope, so we can properly differentiate between nested scopes -private class ShiftCancellationException(val token: Token) : CancellationException("Shifted Continuation") +// Reification of Cont program +private class ShiftCancellationException(val token: Token, val value: Any?) : CancellationException("Shifted Continuation") // Class that represents a unique token by hash comparison private class Token { override fun toString(): String = "Token(${hashCode().toUInt().toString(16)})" } -@JvmInline -private value class Shifted(private val state: AtomicRef = AtomicRef(EmptyValue)) { - inline fun update(f: () -> A): Boolean { - var backing: Any? = EmptyValue - state.loop { a -> - if (a === EmptyValue) { - if (state.compareAndSet( - EmptyValue, - if (backing === EmptyValue) { - backing = f() - backing - } else backing - ) - ) return true - } else { - return false - } - } - } - - fun value(): A = EmptyValue.unbox(state.get()) -} - -// Reification of Cont program @JvmInline private value class Continuation(private val f: suspend ContEffect.() -> A) : Cont { + // We create a `Token` for fold Continuation, so we can properly differentiate between nested folds override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> val token = Token() - val shifted = Shifted() - val effect = object : ContEffect { // Shift away from this Continuation by intercepting it, and completing it with ShiftCancellationException // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation - override suspend fun shift(r: R): B { - // TODO if a concurrent coroutine called shift, do we also complete with `ShiftCancellationException`? - // NOTE: This _should_ only possible if coroutines are already coupled to each-other with structured concurrency - // So re-emitting CancellationException might not be needed ?? - // Related test: https://github.com/nomisRev/Continuation/blob/main/src/commonTest/kotlin/ContSpec.kt#L161 - shifted.update { f(r) } - throw ShiftCancellationException(token) - } + override suspend fun shift(r: R): B = + throw ShiftCancellationException(token, f(r)) } try { suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> res.fold(cont::resume) { throwable -> - if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(shifted.value()) + if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(throwable.value as B) else cont.resumeWith(res) } }) } catch (e: ShiftCancellationException) { - if (token == e.token) shifted.value() else throw e + if (token == e.token) e.value else throw e } } } diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index a39e8862449..bc59831de32 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -39,6 +39,45 @@ class ContSpec : StringSpec({ suspend fun Cont<*, *>.runCont(): Unit = fold({ }, { }) + "Doesn't break try catch" { + checkAll(Arb.int(), Arb.string()) { i, s -> + cont { + try { + shift(s) + } catch (e: Throwable) { + i + } + }.fold({ fail("Should never come here") }, ::identity) shouldBe i + } + } + + "Caught shift is ignored" { + checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + cont { + val x: Int = try { + shift(s) + } catch (e: Throwable) { + i + } + shift(s2) + }.fold(::identity) { fail("Should never come here") } shouldBe s2 + } + } + + "Finally runs" { + checkAll(Arb.string(), Arb.int()) { s, i -> + val promise = CompletableDeferred() + cont { + try { + shift(s) + } finally { + require(promise.complete(i)) + } + }.fold(::identity) { fail("Should never come here") } shouldBe s + promise.await() shouldBe i + } + } + "immediate values" { cont { 1 From e4b62183584195714e5eb28f55a23c6350c57ecd Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sat, 6 Nov 2021 22:41:39 +0100 Subject: [PATCH 015/108] Add docs --- src/commonMain/kotlin/Cont.kt | 6 ++++++ src/jvmTest/kotlin/ContSpec.kt | 7 +++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index d7641f65bb4..01fa2a7c005 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -130,6 +130,12 @@ private value class Continuation(private val f: suspend ContEffect.() - // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B = + + //Some interesting consequences of how Continuation Cancellation works in Kotlin. + // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. + // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. + // This means try/catch is also capable of recovering from monadic errors. + // See: ContSpec - try/catch tests throw ShiftCancellationException(token, f(r)) } diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index bc59831de32..970191d8690 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -1,4 +1,3 @@ -import arrow.continuations.generic.AtomicRef import arrow.core.Either import arrow.core.identity import arrow.core.left @@ -39,7 +38,7 @@ class ContSpec : StringSpec({ suspend fun Cont<*, *>.runCont(): Unit = fold({ }, { }) - "Doesn't break try catch" { + "try/catch - can recover from shift" { checkAll(Arb.int(), Arb.string()) { i, s -> cont { try { @@ -51,7 +50,7 @@ class ContSpec : StringSpec({ } } - "Caught shift is ignored" { + "try/catch - First shift is ignored and second is returned" { checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> cont { val x: Int = try { @@ -64,7 +63,7 @@ class ContSpec : StringSpec({ } } - "Finally runs" { + "try/catch - finally works" { checkAll(Arb.string(), Arb.int()) { s, i -> val promise = CompletableDeferred() cont { From d0dbf79ee45f0f4d488755e07e1768b799df7c61 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 14:52:41 +0100 Subject: [PATCH 016/108] Use ControlThrowable, and add more tests Structured Concurrency --- DOC.md | 181 +++++++++++++++++++++++++++++++++ src/commonMain/kotlin/Cont.kt | 25 +++-- src/jvmTest/kotlin/ContSpec.kt | 131 +++++++++++++++++++++--- 3 files changed, 316 insertions(+), 21 deletions(-) create mode 100644 DOC.md diff --git a/DOC.md b/DOC.md new file mode 100644 index 00000000000..dcbfb9f6a34 --- /dev/null +++ b/DOC.md @@ -0,0 +1,181 @@ +# Semantics of Structured Concurrency + Cont + +KotlinX Structured Concurrency is super important for eco-system, and thus important to us for wide-adoption of this pattern + +There are two options we can take to signal `shift` cancelled the Coroutine. +Using `kotlin.coroutines.CancellationException`, or `arrow.continuations.generics.ControlThrowable` +as the baseclass of our "ShiftedException". + +Below we're going to discuss the scenarios of `context(CoroutineScope, ContEffect)`, +thus the mixing the effects of Structured Concurrency with Continuation Shifting. + +Short recap: + - `launch` launches a **new** coroutine that gets cancelled when it's outer `CoroutineScope` gets cancelled, + and it will re-throw any uncaught unexpected exceptions. Unless an `CoroutineExceptionHandler` is installed. + => This excludes `CancellationException`. + + - `async` launches a **new** coroutine that gets cancelled when it's outer `CoroutineScope` gets cancelled, + and it will re-throw any uncaught unexpected exceptions. If you do not call `await` it will not re-throw `CancellationException`. + +## Scenario 1 (launch): + +```kotlin +import arrow.core.identity +import kotlin.system.measureTimeMillis +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +measureTimeMillis { + cont { + coroutineScope { + val fa = launch { shift("error") } + val fb = launch { delay(2000) } + fa.join() // With or without `join` has no effect on semantics + fb.join() // With or without `join` has no effect on semantics + 1 + } + } + .fold(::identity, ::identity) + .let { println("Result is: $it") } +}.let { println("Took $it milliseconds") } +``` + +In this case, we have 2 independent parallel tasks running within the same `CoroutineScope`. +When we shift from inside `val fa = launch { shift(error) }` this will attempt to short-circuit the `Continuation` created by `suspend Cont.fold`. + +#### CancellationException + +`CancellationException` is a special case, and is meant so signal cancellation, +so an internal cancellation of `fa`, will not cancel `fb` or the parent scope. +``` +Result is: 1 +Took 2141 milliseconds +``` +So with `CancellationException` this snippet *doesn't* see the `shift`. +It allows `fb` to finish, which means the whole scope takes 2000 milliseconds, +and it successfully returns `1`. + +This is probably a quite unexpected result, +what happened here is that `launch` swallowed `CancellationException` since a job that cancelled itself doesn't require further action. +If `fa` had other children `Job`s**, then those would've been cancelled. + +#### ControlThrowable + +Since `ControlThrowable` is seen as a regular exception by Kotlin(X) Coroutines, `launch` will rethrow the exception. +``` +Result is: error +Took 95 milliseconds +``` +This will cancel `fb`, and `coroutineScope` will also re-throw the exception. +This means that our `cont { }` DSL receives the exception, and thus we successfully short-circuit the `Continuation` created by `suspend Cont.fold`. + +## Scenario 2 (async { }.await()) + +```kotlin +import arrow.core.identity +import kotlin.system.measureTimeMillis +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.async + +measureTimeMillis { + cont { + coroutineScope { + val fa = async { shift("error") } + val fb = async { delay(2000); 1 } + fa.await() + fb.await() + } + }.fold(::identity, ::identity) + .let { println("Result is: $it") } +}.let { println("Took $it milliseconds") } +``` + +In this case, we have 2 deferred values computing within the same `CoroutineScope`. +When we shift from inside `val fa = async { shift(error) }` this will attempt to short-circuit the `Continuation` created by `suspend Cont.fold`. +We **explicitly** await the result of `async { }`. +``` +Result is: error +Took 3 milliseconds +``` +Due to the call to `await` it will rethrow `CancellationException`, or any other exception. +So this scenario behaves the same for both `CancellationException` and `ControlThrowable`. + +## Scenario 2 (async { }) + +```kotlin +import arrow.core.identity +import kotlin.system.measureTimeMillis +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.async + +measureTimeMillis { + cont { + coroutineScope { + val fa = async { shift("error") } + val fb = async { delay(2000); 1 } + -1 + } + }.fold(::identity, ::identity) + .let { println("Result is: $it") } +}.let { println("Took $it milliseconds") } +``` + +In this case, we have 2 deferred values computing within the same `CoroutineScope`. +When we shift from inside `val fa = async { shift(error) }` this will attempt to short-circuit the `Continuation` created by `suspend Cont.fold`. +We **don't** await the result of `async { }`. + +#### CancellationException + +`CancellationException` is a special case, and is meant so signal cancellation, +so an internal cancellation of `fa`, will not cancel `fb` or the parent scope **if** we don't rely on the result. +``` +Result is: -1 +Took 2008 milliseconds +``` +So with `CancellationException` this snippet *doesn't* see the `shift`. +It allows `fb` to finish, which means the whole scope takes 2000 milliseconds, +and it successfully returns `-1`. + +This is probably a quite unexpected result, +what happened here is that `async` didn't rethrow `CancellationException` since we never relied on the result. +If `fa` had other children `Job`s**, then those would've been cancelled. + +#### ControlThrowable + +Since `ControlThrowable` is seen as a regular exception by Kotlin(X) Coroutines, `async` will rethrow the exception. +``` +Result is: error +Took 3 milliseconds +``` +This will cancel `fb`, and `coroutineScope` will also re-throw the exception. +This means that our `cont { }` DSL receives the exception, and thus we successfully short-circuit the `Continuation` created by `suspend Cont.fold`. + +** Job: A Job represents a single running Coroutine, and it holds references to all its children `Job`s. + +# Conclusion + +It seems that continuing to use `ControlThrowable` for shifting/short-circuiting is the best option. + +With some additional work, we can also fix some current oddities in Arrow. +If we redefine the exception we use to `shift` or `short-circuit` to the following. +We can have a `ControlThrowable` that uses the `cause.stacktrace` as the stacktrace, +and holds a `CancellationException` with the stacktrace. + +```kotlin +private class ShiftCancellationException( + val token: Token, + val value: Any?, + override val cause: CancellationException = CancellationException() +) : ControlThrowable("Shifted Continuation", cause) +``` + +That way we can solve the issue we currently have with `bracketCase` that it signals, +`ExitCase.Failure` when a `ShortCircuit` has occurred (Arrow 1.0 computation runtime). + +Since `bracketCase` can be aware of our `ShiftCancellationException`, +then it can take the `cause` to signal `ExitCase.Cancelled`. + +Biggest downside: + With `CancellationException` we don't have to impose the rule **never catch ControlThrowable**. diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 01fa2a7c005..2b4fcb88129 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -8,9 +8,9 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation import kotlin.coroutines.cancellation.CancellationException -import kotlin.coroutines.resume -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn +import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn +import kotlin.coroutines.resume import kotlin.jvm.JvmInline public fun cont(f: suspend ContEffect.() -> A): Cont = @@ -111,8 +111,19 @@ public suspend fun ContEffect.ensureNotNull(value: B?, shift: () // Full internal runtime implementation of Cont below +public open class ControlThrowable( + override val message: String? = null, + override val cause: Throwable? = null +) : Throwable(message, cause) { + // Expect/actual JVM (fillStackTrace) +} + // Reification of Cont program -private class ShiftCancellationException(val token: Token, val value: Any?) : CancellationException("Shifted Continuation") +private class ShiftCancellationException( + val token: Token, + val value: Any?, + override val cause: CancellationException = CancellationException() +) : ControlThrowable("Shifted Continuation", cause) // Class that represents a unique token by hash comparison private class Token { @@ -131,10 +142,10 @@ private value class Continuation(private val f: suspend ContEffect.() - // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B = - //Some interesting consequences of how Continuation Cancellation works in Kotlin. - // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. - // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. - // This means try/catch is also capable of recovering from monadic errors. + //Some interesting consequences of how Continuation Cancellation works in Kotlin. + // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. + // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. + // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests throw ShiftCancellationException(token, f(r)) } diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index 970191d8690..3c619aac2a8 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -2,11 +2,15 @@ import arrow.core.Either import arrow.core.identity import arrow.core.left import arrow.core.right +import arrow.fx.coroutines.ExitCase +import arrow.fx.coroutines.guaranteeCase +import arrow.fx.coroutines.never import io.kotest.assertions.fail import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeTypeOf import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int @@ -21,11 +25,12 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.startCoroutine import kotlin.time.Duration import kotlin.time.ExperimentalTime +import kotlin.time.seconds import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeout @@ -50,16 +55,15 @@ class ContSpec : StringSpec({ } } - "try/catch - First shift is ignored and second is returned" { - checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + "try/catch - can recover from shift suspended" { + checkAll(Arb.int(), Arb.string()) { i, s -> cont { - val x: Int = try { - shift(s) + try { + shift(s.suspend()) } catch (e: Throwable) { i } - shift(s2) - }.fold(::identity) { fail("Should never come here") } shouldBe s2 + }.fold({ fail("Should never come here") }, ::identity) shouldBe i } } @@ -77,6 +81,46 @@ class ContSpec : StringSpec({ } } + "try/catch - finally works suspended" { + checkAll(Arb.string(), Arb.int()) { s, i -> + val promise = CompletableDeferred() + cont { + try { + shift(s.suspend()) + } finally { + require(promise.complete(i)) + } + }.fold(::identity) { fail("Should never come here") } shouldBe s + promise.await() shouldBe i + } + } + + "try/catch - First shift is ignored and second is returned" { + checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + cont { + val x: Int = try { + shift(s) + } catch (e: Throwable) { + i + } + shift(s2) + }.fold(::identity) { fail("Should never come here") } shouldBe s2 + } + } + + "try/catch - First shift is ignored and second is returned suspended" { + checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + cont { + val x: Int = try { + shift(s.suspend()) + } catch (e: Throwable) { + i + } + shift(s2.suspend()) + }.fold(::identity) { fail("Should never come here") } shouldBe s2 + } + } + "immediate values" { cont { 1 @@ -185,7 +229,9 @@ class ContSpec : StringSpec({ }.fold(::identity, ::identity) shouldBe "hello" withTimeout(Duration.Companion.seconds(2)) { - cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" + // KotlinX internally wraps exceptions + cancelled.await().shouldNotBeNull()?.cause?.message shouldBe "Shifted Continuation" +// cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" } } @@ -196,16 +242,73 @@ class ContSpec : StringSpec({ }.runCont() } - "Concurrent shift" { + "Concurrent shift - async await" { checkAll(Arb.int(), Arb.int()) { a, b -> + val promise = CompletableDeferred() cont { - coroutineScope { - val fa = async(start = CoroutineStart.UNDISPATCHED) { shift(a) } - val fb = async(start = CoroutineStart.UNDISPATCHED) { shift(b) } - fa.await() - fb.await() + guaranteeCase({ + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + fa.await() + fb.await() + } + }) { case -> require(promise.complete(case)) } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + withTimeout(2.seconds) { + promise.await().shouldBeTypeOf() + } + } + } + + "Concurrent shift - async" { + checkAll(Arb.int(), Arb.int()) { a, b -> + val promise = CompletableDeferred() + cont { + guaranteeCase({ + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + "" + } + }) { case -> require(promise.complete(case)) } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + withTimeout(2.seconds) { + promise.await().shouldBeTypeOf() + } + } + } + + "Concurrent shift - launch" { + checkAll(Arb.int(), Arb.int()) { a, b -> + val promise = CompletableDeferred() + val jobB = CompletableDeferred() + val started = CompletableDeferred() + cont { + guaranteeCase({ + coroutineScope { + val fa = launch { + started.await() + shift(a) + } + val fb = launch { + guaranteeCase({ + started.complete(Unit) + never() + }) { case -> + require(jobB.complete(case)) + } + } + } + }) { case -> + require(promise.complete(case)) } + fail("Should never come here") }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + withTimeout(2.seconds) { + promise.await().shouldBeTypeOf() + // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope + jobB.await().shouldBeTypeOf() + } } } }) From 116632eabe4294db3187e354471b9e3adffc40eb Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 18:31:12 +0100 Subject: [PATCH 017/108] Add documentation --- DOC.md => ContAndStructuredConcurrency.md | 27 +++++++++++++++++-- example/build.gradle.kts | 11 ++++++++ example/src/main/kotlin/example.kt | 28 ++++++++++++++++++++ src/commonMain/kotlin/Cont.kt | 32 +++++++++++++++++++++-- src/commonMain/kotlin/RestrictedCont.kt | 4 +++ src/jvmMain/kotlin/t.kt | 1 + 6 files changed, 99 insertions(+), 4 deletions(-) rename DOC.md => ContAndStructuredConcurrency.md (87%) create mode 100644 example/build.gradle.kts create mode 100644 example/src/main/kotlin/example.kt create mode 100644 src/jvmMain/kotlin/t.kt diff --git a/DOC.md b/ContAndStructuredConcurrency.md similarity index 87% rename from DOC.md rename to ContAndStructuredConcurrency.md index dcbfb9f6a34..a2e99486efa 100644 --- a/DOC.md +++ b/ContAndStructuredConcurrency.md @@ -177,5 +177,28 @@ That way we can solve the issue we currently have with `bracketCase` that it sig Since `bracketCase` can be aware of our `ShiftCancellationException`, then it can take the `cause` to signal `ExitCase.Cancelled`. -Biggest downside: - With `CancellationException` we don't have to impose the rule **never catch ControlThrowable**. +Downsides: + - With `CancellationException` we don't have to impose the rule **never catch ControlThrowable**. + +### Open ends.. + +##### Does this break any semantics? + +Ideally it seems that `shift` should not be callable from `launch`, but afaik that is not possible in vanilla Kotlin. +With `CanellationException`, `shift` from within `async` seems to follow the Structured Concurrency Spec, when you don't call `await` it cannot cancel/shift its surrounding scope. +But in that fashion `shift` should also ignore `shift` from within its calls. + +We could consider `launch`, `async`, and `coroutineScope` low-level operators where people need to keep the above restrictions in mind. + +Since Arrow Fx Coroutines offers high-level operators which don't expose any of the issues above. I.e. +```kotlin +cont> { + (0..100).parTraverse { i -> + shift("error") + } +} + +cont { + parZip({ shift("error") }, { 1 }) { a, b -> a + b } +} +``` diff --git a/example/build.gradle.kts b/example/build.gradle.kts new file mode 100644 index 00000000000..ae546b4211a --- /dev/null +++ b/example/build.gradle.kts @@ -0,0 +1,11 @@ +plugins { + kotlin("jvm") +} + +repositories { + mavenCentral() +} + +dependencies { + implementation(rootProject) +} diff --git a/example/src/main/kotlin/example.kt b/example/src/main/kotlin/example.kt new file mode 100644 index 00000000000..91c56e606e1 --- /dev/null +++ b/example/src/main/kotlin/example.kt @@ -0,0 +1,28 @@ +import arrow.core.None +import java.io.File +import java.io.FileNotFoundException + +sealed class FileError +data class SecurityError(val msg: String?) : FileError() +data class FileNotFound(val path: String): FileError() +object EmptyPath: FileError() +data class Content(val body: List) + +fun readFile(path: String): Cont = cont { + ensure(path.isNotEmpty()) { EmptyPath } + try { + Content(File(path).readLines()) + } catch (e: FileNotFoundException) { + shift(FileNotFound(path)) + } catch (e: SecurityException) { + shift(SecurityError(e.message)) + } +} + +suspend fun main() { + readFile("").toEither().let(::println) + readFile("not-found").toValidated().let(::println) + readFile("gradle.properties").toIor().let(::println) + readFile("not-found").toOption { None } .let(::println) + readFile("nullable").fold({ _: FileError -> null }, { it }).let(::println) +} diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 2b4fcb88129..0df6ad42d58 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -1,9 +1,11 @@ import arrow.core.Either +import arrow.core.Ior import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.Validated import arrow.core.identity +import arrow.core.nonFatalOrThrow import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation @@ -26,14 +28,36 @@ public fun cont(f: suspend ContEffect.() -> A): Cont = public interface Cont { suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B + suspend fun fold( + error: suspend (Throwable) -> B, + f: suspend (R) -> B, + g: suspend (A) -> B + ): B = try { + fold(f, g) + } catch (e: Throwable) { + error(e.nonFatalOrThrow()) + } + suspend fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } + suspend fun toIor(): Ior = + fold({ Ior.Left(it) }) { Ior.Right(it) } + suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + suspend fun toOption(orElse: suspend (R) -> Option): Option = + fold(orElse, ::Some) + fun attempt(): Cont> = - cont { runCatching { bind() } } + cont { + try { + Result.success(bind()) + } catch (e: Throwable) { + Result.failure(e.nonFatalOrThrow()) + } + } fun map(f: suspend (A) -> B): Cont = cont { fold(this::shift, f) } @@ -67,6 +91,9 @@ interface ContEffect { */ public suspend fun shift(r: R): B +// Can be implemented by catching ShiftCancellationException, and applying `g` over the shifted `R`. +// public suspend fun catch(f: () -> B, g: (R) -> B): B + /** ApplicativeError alias for shift */ public suspend fun raiseError(r: R): B = shift(r) @@ -102,6 +129,7 @@ interface ContEffect { if (value) Unit else shift(shift()) } + // Monadic version of kotlin.requireNotNull @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so top-level. public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { @@ -115,7 +143,7 @@ public open class ControlThrowable( override val message: String? = null, override val cause: Throwable? = null ) : Throwable(message, cause) { - // Expect/actual JVM (fillStackTrace) + // Expect/actual JVM (fillStackTrace) } // Reification of Cont program diff --git a/src/commonMain/kotlin/RestrictedCont.kt b/src/commonMain/kotlin/RestrictedCont.kt index f57a74adfab..70cb86262d1 100644 --- a/src/commonMain/kotlin/RestrictedCont.kt +++ b/src/commonMain/kotlin/RestrictedCont.kt @@ -10,6 +10,10 @@ import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.jvm.JvmInline +/** + * `RestrictsSuspension` version of `Cont`. + * This version runs eagerly, can can be used in non-suspending code. + */ public fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont = RestrictedContDsl(f) diff --git a/src/jvmMain/kotlin/t.kt b/src/jvmMain/kotlin/t.kt new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/jvmMain/kotlin/t.kt @@ -0,0 +1 @@ + From 31a878d8bad477675ae336228e2f7ea197f01c7d Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 19:12:22 +0100 Subject: [PATCH 018/108] Optimise how shift/fold run, and allow catching shift --- src/commonMain/kotlin/Cont.kt | 46 ++++++++++++++++++++++++++------- src/commonMain/kotlin/ior.kt | 3 +++ src/commonMain/kotlin/option.kt | 6 ++--- src/jvmTest/kotlin/ContSpec.kt | 10 +++++++ 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 0df6ad42d58..ead83154dd6 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -9,8 +9,10 @@ import arrow.core.nonFatalOrThrow import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation +import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn +import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.resume import kotlin.jvm.JvmInline @@ -92,7 +94,7 @@ interface ContEffect { public suspend fun shift(r: R): B // Can be implemented by catching ShiftCancellationException, and applying `g` over the shifted `R`. -// public suspend fun catch(f: () -> B, g: (R) -> B): B + public suspend fun catch(f: suspend () -> B, g: suspend (R) -> B): B /** ApplicativeError alias for shift */ public suspend fun raiseError(r: R): B = @@ -149,7 +151,8 @@ public open class ControlThrowable( // Reification of Cont program private class ShiftCancellationException( val token: Token, - val value: Any?, + val shifted: Any?, + val fold: suspend (Any?) -> Any?, override val cause: CancellationException = CancellationException() ) : ControlThrowable("Shifted Continuation", cause) @@ -175,18 +178,41 @@ private value class Continuation(private val f: suspend ContEffect.() - // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests - throw ShiftCancellationException(token, f(r)) + throw ShiftCancellationException(token, r, f as suspend (Any?) -> Any?) + + override suspend fun catch(f: suspend () -> B, g: suspend (R) -> B): B = try { + f() + } catch (e: ShiftCancellationException) { + if (e.token == token) g(e.shifted as R) else throw e + } } try { - suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(Continuation(cont.context) { res -> - res.fold(cont::resume) { throwable -> - if (throwable is ShiftCancellationException && token == throwable.token) cont.resume(throwable.value as B) - else cont.resumeWith(res) - } - }) + suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) } catch (e: ShiftCancellationException) { - if (token == e.token) e.value else throw e + if (token == e.token) { + val f: suspend () -> B = { e.fold(e.shifted) as B } + f.startCoroutineUninterceptedOrReturn(cont) + } else throw e } } } + +private class FoldContinuation( + private val token: Token, + override val context: CoroutineContext, + private val cont: Continuation +) : Continuation { + + override fun resumeWith(result: Result) { + result.fold(cont::resume) { throwable -> + if (throwable is ShiftCancellationException && token == throwable.token) { + val f: suspend () -> B = { throwable.fold(throwable.shifted) as B } + when(val res = f.startCoroutineUninterceptedOrReturn(cont)) { + COROUTINE_SUSPENDED -> Unit + else -> cont.resume(res as B) + } + } else cont.resumeWith(result) + } + } +} diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt index 4688188818a..9725916db2b 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/ior.kt @@ -39,4 +39,7 @@ class IorEffect( override suspend fun shift(r: E): B = cont.shift(combine(r)) + + override suspend fun catch(f: suspend () -> B, g: suspend (E) -> B): B = + cont.catch(f, g) } diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt index 16bdf97ce49..10523f420f1 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/option.kt @@ -12,9 +12,6 @@ suspend fun option(f: OptionEffect.() -> A): Option = suspend fun Cont.toOption(): Option = fold(::identity) { Some(it) } -// Can be replaced by multiple receivers -// context(ContEffect) -// fun Option.bind(): A = ... @JvmInline value class OptionEffect(private val cont: ContEffect) : ContEffect { suspend fun Option.bind(): B = @@ -25,6 +22,9 @@ value class OptionEffect(private val cont: ContEffect) : ContEffect override suspend fun shift(r: None): B = cont.shift(r) + + override suspend fun catch(f: suspend () -> B, g: suspend (None) -> B): B = + cont.catch(f, g) } @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index 3c619aac2a8..2603de07bd3 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -187,6 +187,16 @@ class ContSpec : StringSpec({ }.fold(::identity, ::identity) shouldBe "test" } + "Monadic catch" { + checkAll(Arb.string()) { s -> + cont { + catch({ + shift(s) + }) { error -> error.length } + }.toEither() shouldBe Either.Right(s.length) + } + } + // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 "ensure null in either computation" { checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> From 27a0a3698f7cf6dd288fd60d37925572effe7a29 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 19:21:36 +0100 Subject: [PATCH 019/108] Revert catch --- src/commonMain/kotlin/Cont.kt | 14 ++------------ src/commonMain/kotlin/ior.kt | 3 --- src/commonMain/kotlin/option.kt | 3 --- src/jvmMain/kotlin/t.kt | 1 - src/jvmTest/kotlin/ContSpec.kt | 10 ---------- 5 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 src/jvmMain/kotlin/t.kt diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index ead83154dd6..1cf2ede37ff 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -11,8 +11,8 @@ import kotlin.contracts.contract import kotlin.coroutines.Continuation import kotlin.coroutines.CoroutineContext import kotlin.coroutines.cancellation.CancellationException -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED +import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.resume import kotlin.jvm.JvmInline @@ -93,9 +93,6 @@ interface ContEffect { */ public suspend fun shift(r: R): B -// Can be implemented by catching ShiftCancellationException, and applying `g` over the shifted `R`. - public suspend fun catch(f: suspend () -> B, g: suspend (R) -> B): B - /** ApplicativeError alias for shift */ public suspend fun raiseError(r: R): B = shift(r) @@ -179,12 +176,6 @@ private value class Continuation(private val f: suspend ContEffect.() - // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests throw ShiftCancellationException(token, r, f as suspend (Any?) -> Any?) - - override suspend fun catch(f: suspend () -> B, g: suspend (R) -> B): B = try { - f() - } catch (e: ShiftCancellationException) { - if (e.token == token) g(e.shifted as R) else throw e - } } try { @@ -203,12 +194,11 @@ private class FoldContinuation( override val context: CoroutineContext, private val cont: Continuation ) : Continuation { - override fun resumeWith(result: Result) { result.fold(cont::resume) { throwable -> if (throwable is ShiftCancellationException && token == throwable.token) { val f: suspend () -> B = { throwable.fold(throwable.shifted) as B } - when(val res = f.startCoroutineUninterceptedOrReturn(cont)) { + when (val res = f.startCoroutineUninterceptedOrReturn(cont)) { COROUTINE_SUSPENDED -> Unit else -> cont.resume(res as B) } diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/ior.kt index 9725916db2b..4688188818a 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/ior.kt @@ -39,7 +39,4 @@ class IorEffect( override suspend fun shift(r: E): B = cont.shift(combine(r)) - - override suspend fun catch(f: suspend () -> B, g: suspend (E) -> B): B = - cont.catch(f, g) } diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/option.kt index 10523f420f1..640c3657c3e 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/option.kt @@ -22,9 +22,6 @@ value class OptionEffect(private val cont: ContEffect) : ContEffect override suspend fun shift(r: None): B = cont.shift(r) - - override suspend fun catch(f: suspend () -> B, g: suspend (None) -> B): B = - cont.catch(f, g) } @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. diff --git a/src/jvmMain/kotlin/t.kt b/src/jvmMain/kotlin/t.kt deleted file mode 100644 index 8b137891791..00000000000 --- a/src/jvmMain/kotlin/t.kt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index 2603de07bd3..3c619aac2a8 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -187,16 +187,6 @@ class ContSpec : StringSpec({ }.fold(::identity, ::identity) shouldBe "test" } - "Monadic catch" { - checkAll(Arb.string()) { s -> - cont { - catch({ - shift(s) - }) { error -> error.length } - }.toEither() shouldBe Either.Right(s.length) - } - } - // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 "ensure null in either computation" { checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> From 572ac3c8b5194672249f00fda402b3fb2731af96 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 21:56:07 +0100 Subject: [PATCH 020/108] Add deeply nested exception tests --- src/jvmTest/kotlin/ContSpec.kt | 167 +++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 30 deletions(-) diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index 3c619aac2a8..1c95b00f458 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -27,8 +27,12 @@ import kotlin.time.Duration import kotlin.time.ExperimentalTime import kotlin.time.seconds import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine @@ -244,70 +248,173 @@ class ContSpec : StringSpec({ "Concurrent shift - async await" { checkAll(Arb.int(), Arb.int()) { a, b -> - val promise = CompletableDeferred() + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + fa.await() + fb.await() + } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + } + } + + "Concurrent shift - async await exit results" { + checkAll(Arb.int()) { a -> + val scopeExit = CompletableDeferred() + val fbExit = CompletableDeferred() + val startLatches = (0..11).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + cont { guaranteeCase({ coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } - fa.await() + fb.await() + val fa = async { + startLatches.drop(1).zip(nestedExits) { start, promise -> + asyncTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + val fb = asyncTask(startLatches.first(), fbExit) + fa.await() + fb.await() } - }) { case -> require(promise.complete(case)) } - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + }) { case -> + require(scopeExit.complete(case)) + } + fail("Should never come here") + }.fold(::identity, ::identity) shouldBe a withTimeout(2.seconds) { - promise.await().shouldBeTypeOf() + scopeExit.await().shouldBeTypeOf() + // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope + fbExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } } } } "Concurrent shift - async" { checkAll(Arb.int(), Arb.int()) { a, b -> - val promise = CompletableDeferred() + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + "I will be overwritten by shift - coroutineScope waits until all async are finished" + } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + } + } + + "Concurrent shift - async exit results" { + checkAll(Arb.int()) { a -> + val scopeExit = CompletableDeferred() + val fbExit = CompletableDeferred() + val startLatches = (0..11).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + cont { guaranteeCase({ coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } - "" + val fa = async { + startLatches.drop(1).zip(nestedExits) { start, promise -> + asyncTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + val fb = asyncTask(startLatches.first(), fbExit) } - }) { case -> require(promise.complete(case)) } - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + }) { case -> + require(scopeExit.complete(case)) + } + fail("Should never come here") + }.fold(::identity, ::identity) shouldBe a withTimeout(2.seconds) { - promise.await().shouldBeTypeOf() + scopeExit.await().shouldBeTypeOf() + // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope + fbExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } } } } "Concurrent shift - launch" { checkAll(Arb.int(), Arb.int()) { a, b -> - val promise = CompletableDeferred() - val jobB = CompletableDeferred() - val started = CompletableDeferred() + cont { + coroutineScope { + launch { shift(a) } + launch { shift(b) } + "This will be overriden by shift - scope waits until all launch finished" + } + }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + } + } + + "Concurrent shift - launch exit results" { + checkAll(Arb.int()) { a -> + val scopeExit = CompletableDeferred() + val fbExit = CompletableDeferred() + val startLatches = (0..11).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.launchTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Job = launch { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + cont { guaranteeCase({ coroutineScope { val fa = launch { - started.await() - shift(a) - } - val fb = launch { - guaranteeCase({ - started.complete(Unit) - never() - }) { case -> - require(jobB.complete(case)) + startLatches.drop(1).zip(nestedExits) { start, promise -> + launchTask(start, promise) } + startLatches.awaitAll() + shift(a) } + val fb = launchTask(startLatches.first(), fbExit) } }) { case -> - require(promise.complete(case)) + require(scopeExit.complete(case)) } fail("Should never come here") - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) + }.fold(::identity, ::identity) shouldBe a withTimeout(2.seconds) { - promise.await().shouldBeTypeOf() + scopeExit.await().shouldBeTypeOf() // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope - jobB.await().shouldBeTypeOf() + fbExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } } } } From fd97ee1a852e2f0ae7544dc005cc444819aedaf8 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Sun, 7 Nov 2021 22:28:39 +0100 Subject: [PATCH 021/108] Add weird scenarios --- src/commonMain/kotlin/Cont.kt | 13 ++++++------- src/jvmTest/kotlin/ContSpec.kt | 33 +++++++++++++++++++++++++++++++++ src/jvmTest/kotlin/IorSpec.kt | 17 +++++++++++++++++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 1cf2ede37ff..3076e894e34 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -18,7 +18,7 @@ import kotlin.coroutines.resume import kotlin.jvm.JvmInline public fun cont(f: suspend ContEffect.() -> A): Cont = - Continuation(f) + ContImpl(f) /** * [Cont] represents a suspending computation that runs will either @@ -159,7 +159,7 @@ private class Token { } @JvmInline -private value class Continuation(private val f: suspend ContEffect.() -> A) : Cont { +private value class ContImpl(private val f: suspend ContEffect.() -> A) : Cont { // We create a `Token` for fold Continuation, so we can properly differentiate between nested folds override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> @@ -169,11 +169,10 @@ private value class Continuation(private val f: suspend ContEffect.() - // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B = - - //Some interesting consequences of how Continuation Cancellation works in Kotlin. - // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. - // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. - // This means try/catch is also capable of recovering from monadic errors. + // Some interesting consequences of how Continuation Cancellation works in Kotlin. + // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. + // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. + // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests throw ShiftCancellationException(token, r, f as suspend (Any?) -> Any?) } diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index 1c95b00f458..ee745ef1749 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -305,6 +305,39 @@ class ContSpec : StringSpec({ } } + "Concurrent shift - async funky scenario #1" { + val scenario = "I will NOT be overridden by shift, scope is waiting on async on the outside" + checkAll(Arb.int(), Arb.int()) { a, b -> + kotlin.runCatching { + coroutineScope { + cont { + val fa = async { shift(a) } + val fb = async { shift(b) } + scenario + }.fold({ + fail("shift never works here") + }, ::identity) shouldBe scenario + } + }.exceptionOrNull()?.message shouldBe "Shifted Continuation" + } + } + + "Concurrent shift - async funky scenario #2" { + val scenario = "I will NOT be overridden by shift, scope is waiting on async on the outside" + checkAll(Arb.int(), Arb.int()) { a, b -> + kotlin.runCatching { + coroutineScope { + cont> { + val fa = async { shift(a) } + async { shift(b) } + }.fold({ + fail("shift never works here") + }, ::identity).await() + } + }.exceptionOrNull()?.message shouldBe "Shifted Continuation" + } + } + "Concurrent shift - async" { checkAll(Arb.int(), Arb.int()) { a, b -> cont { diff --git a/src/jvmTest/kotlin/IorSpec.kt b/src/jvmTest/kotlin/IorSpec.kt index 36c2525009f..4d9f104b7a9 100644 --- a/src/jvmTest/kotlin/IorSpec.kt +++ b/src/jvmTest/kotlin/IorSpec.kt @@ -3,6 +3,13 @@ import arrow.core.Ior import arrow.typeclasses.Semigroup import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import io.kotest.property.Arb +import io.kotest.property.arbitrary.filter +import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll class IorSpec : StringSpec({ "Accumulates" { @@ -20,4 +27,14 @@ class IorSpec : StringSpec({ one + two } shouldBe Ior.Left("Hello, World!") } + + "Concurrent - ior bind" { + checkAll(Arb.list(Arb.string()).filter(List::isNotEmpty)) { strs -> + ior(Semigroup.list()) { + strs.mapIndexed { index, s -> + async { Ior.Both(listOf(s), index).bind() } + }.awaitAll() + }.mapLeft { it.toSet() } shouldBe Ior.Both(strs.toSet(), strs.indices.toList()) + } + } }) From 340a104f9bdde236c629f84704d5529433bc192d Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 8 Nov 2021 23:28:38 +0100 Subject: [PATCH 022/108] Add some docs structurred concurrency --- src/commonMain/kotlin/Cont.kt | 24 +- src/jvmTest/kotlin/ContSpec.kt | 277 +----------------- .../kotlin/StructuredConcurrencySpec.kt | 245 ++++++++++++++++ src/jvmTest/kotlin/predef.kt | 7 + 4 files changed, 280 insertions(+), 273 deletions(-) create mode 100644 src/jvmTest/kotlin/StructuredConcurrencySpec.kt create mode 100644 src/jvmTest/kotlin/predef.kt diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/Cont.kt index 3076e894e34..d38a08992f8 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/Cont.kt @@ -145,13 +145,13 @@ public open class ControlThrowable( // Expect/actual JVM (fillStackTrace) } -// Reification of Cont program -private class ShiftCancellationException( + +sealed class ShiftCancellationException : CancellationException("Shifted Continuation") +private class Internal( val token: Token, val shifted: Any?, - val fold: suspend (Any?) -> Any?, - override val cause: CancellationException = CancellationException() -) : ControlThrowable("Shifted Continuation", cause) + val fold: suspend (Any?) -> Any? +): ShiftCancellationException() // Class that represents a unique token by hash comparison private class Token { @@ -169,17 +169,17 @@ private value class ContImpl(private val f: suspend ContEffect.() -> A) // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B = - // Some interesting consequences of how Continuation Cancellation works in Kotlin. - // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. - // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. - // This means try/catch is also capable of recovering from monadic errors. + // Some interesting consequences of how Continuation Cancellation works in Kotlin. + // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. + // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. + // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests - throw ShiftCancellationException(token, r, f as suspend (Any?) -> Any?) + throw Internal(token, r, f as suspend (Any?) -> Any?) } try { suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) - } catch (e: ShiftCancellationException) { + } catch (e: Internal) { if (token == e.token) { val f: suspend () -> B = { e.fold(e.shifted) as B } f.startCoroutineUninterceptedOrReturn(cont) @@ -195,7 +195,7 @@ private class FoldContinuation( ) : Continuation { override fun resumeWith(result: Result) { result.fold(cont::resume) { throwable -> - if (throwable is ShiftCancellationException && token == throwable.token) { + if (throwable is Internal && token == throwable.token) { val f: suspend () -> B = { throwable.fold(throwable.shifted) as B } when (val res = f.startCoroutineUninterceptedOrReturn(cont)) { COROUTINE_SUSPENDED -> Unit diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/ContSpec.kt index ee745ef1749..72686adbc07 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/ContSpec.kt @@ -2,15 +2,9 @@ import arrow.core.Either import arrow.core.identity import arrow.core.left import arrow.core.right -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.never import io.kotest.assertions.fail import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.collections.shouldBeIn -import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int @@ -23,30 +17,16 @@ import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.intrinsics.intercepted import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.startCoroutine -import kotlin.time.Duration import kotlin.time.ExperimentalTime -import kotlin.time.seconds import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withTimeout @OptIn(ExperimentalTime::class) class ContSpec : StringSpec({ - - suspend fun Cont.value(): A = - fold(::identity, ::identity) - - suspend fun Cont<*, *>.runCont(): Unit = - fold({ }, { }) - "try/catch - can recover from shift" { checkAll(Arb.int(), Arb.string()) { i, s -> cont { @@ -112,6 +92,17 @@ class ContSpec : StringSpec({ } } + suspend fun test() { + val leakedAsync = coroutineScope Deferred> { + suspend { + async { + println("I am never going to run, until I get called invoked from outside") + } + } + } + leakedAsync.invoke().await() + } + "try/catch - First shift is ignored and second is returned suspended" { checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> cont { @@ -140,13 +131,13 @@ class ContSpec : StringSpec({ "immediate short-circuit" { cont { shift("hello") - }.fold(::identity, ::identity) shouldBe "hello" + }.runCont() shouldBe "hello" } "suspended short-circuit" { cont { shift("hello".suspend()) - }.fold(::identity, ::identity) shouldBe "hello" + }.runCont() shouldBe "hello" } "Rethrows immediate exceptions" { @@ -171,14 +162,14 @@ class ContSpec : StringSpec({ cont { cont { shift("test") }.runCont() fail("Should never reach this point") - }.fold(::identity, ::identity) shouldBe "test" + }.runCont() shouldBe "test" } "Can short-circuit suspended from nested blocks" { cont { cont { shift("test".suspend()) }.runCont() fail("Should never reach this point") - }.fold(::identity, ::identity) shouldBe "test" + }.runCont() shouldBe "test" } "Can short-circuit immediately after suspending from nested blocks" { @@ -188,7 +179,7 @@ class ContSpec : StringSpec({ shift("test".suspend()) }.runCont() fail("Should never reach this point") - }.fold(::identity, ::identity) shouldBe "test" + }.runCont() shouldBe "test" } // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 @@ -215,242 +206,6 @@ class ContSpec : StringSpec({ res shouldBe expected } } - - "Short-circuiting co-operates with KotlinX Structured Concurrency" { - val latch = CompletableDeferred() - val cancelled = CompletableDeferred() - - cont { - coroutineScope { - val never = async(Dispatchers.Default) { completeOnCancellation(latch, cancelled) } - val fail = async(Dispatchers.Default) { - latch.await() - shift("hello") - } - fail.await() // When this fails, it should also close never - never.await() - } - }.fold(::identity, ::identity) shouldBe "hello" - - withTimeout(Duration.Companion.seconds(2)) { - // KotlinX internally wraps exceptions - cancelled.await().shouldNotBeNull()?.cause?.message shouldBe "Shifted Continuation" -// cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" - } - } - - "Computation blocks run on parent context" { - val parentCtx = currentContext() - cont { - currentContext() shouldBe parentCtx - }.runCont() - } - - "Concurrent shift - async await" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } - fa.await() + fb.await() - } - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) - } - } - - "Concurrent shift - async await exit results" { - checkAll(Arb.int()) { a -> - val scopeExit = CompletableDeferred() - val fbExit = CompletableDeferred() - val startLatches = (0..11).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.asyncTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Deferred = async { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) - } - } - - cont { - guaranteeCase({ - coroutineScope { - val fa = async { - startLatches.drop(1).zip(nestedExits) { start, promise -> - asyncTask(start, promise) - } - startLatches.awaitAll() - shift(a) - } - val fb = asyncTask(startLatches.first(), fbExit) - fa.await() - fb.await() - } - }) { case -> - require(scopeExit.complete(case)) - } - fail("Should never come here") - }.fold(::identity, ::identity) shouldBe a - withTimeout(2.seconds) { - scopeExit.await().shouldBeTypeOf() - // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope - fbExit.await().shouldBeTypeOf() - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } - } - } - } - - "Concurrent shift - async funky scenario #1" { - val scenario = "I will NOT be overridden by shift, scope is waiting on async on the outside" - checkAll(Arb.int(), Arb.int()) { a, b -> - kotlin.runCatching { - coroutineScope { - cont { - val fa = async { shift(a) } - val fb = async { shift(b) } - scenario - }.fold({ - fail("shift never works here") - }, ::identity) shouldBe scenario - } - }.exceptionOrNull()?.message shouldBe "Shifted Continuation" - } - } - - "Concurrent shift - async funky scenario #2" { - val scenario = "I will NOT be overridden by shift, scope is waiting on async on the outside" - checkAll(Arb.int(), Arb.int()) { a, b -> - kotlin.runCatching { - coroutineScope { - cont> { - val fa = async { shift(a) } - async { shift(b) } - }.fold({ - fail("shift never works here") - }, ::identity).await() - } - }.exceptionOrNull()?.message shouldBe "Shifted Continuation" - } - } - - "Concurrent shift - async" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } - "I will be overwritten by shift - coroutineScope waits until all async are finished" - } - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) - } - } - - "Concurrent shift - async exit results" { - checkAll(Arb.int()) { a -> - val scopeExit = CompletableDeferred() - val fbExit = CompletableDeferred() - val startLatches = (0..11).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.asyncTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Deferred = async { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) - } - } - - cont { - guaranteeCase({ - coroutineScope { - val fa = async { - startLatches.drop(1).zip(nestedExits) { start, promise -> - asyncTask(start, promise) - } - startLatches.awaitAll() - shift(a) - } - val fb = asyncTask(startLatches.first(), fbExit) - } - }) { case -> - require(scopeExit.complete(case)) - } - fail("Should never come here") - }.fold(::identity, ::identity) shouldBe a - withTimeout(2.seconds) { - scopeExit.await().shouldBeTypeOf() - // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope - fbExit.await().shouldBeTypeOf() - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } - } - } - } - - "Concurrent shift - launch" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - launch { shift(a) } - launch { shift(b) } - "This will be overriden by shift - scope waits until all launch finished" - } - }.fold(::identity, ::identity) shouldBeIn listOf(a, b) - } - } - - "Concurrent shift - launch exit results" { - checkAll(Arb.int()) { a -> - val scopeExit = CompletableDeferred() - val fbExit = CompletableDeferred() - val startLatches = (0..11).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.launchTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Job = launch { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) - } - } - - cont { - guaranteeCase({ - coroutineScope { - val fa = launch { - startLatches.drop(1).zip(nestedExits) { start, promise -> - launchTask(start, promise) - } - startLatches.awaitAll() - shift(a) - } - val fb = launchTask(startLatches.first(), fbExit) - } - }) { case -> - require(scopeExit.complete(case)) - } - fail("Should never come here") - }.fold(::identity, ::identity) shouldBe a - withTimeout(2.seconds) { - scopeExit.await().shouldBeTypeOf() - // This is ExitCase.Cancelled since it was cancelled by KotlinX CoroutineScope - fbExit.await().shouldBeTypeOf() - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } - } - } - } }) suspend fun currentContext(): CoroutineContext = diff --git a/src/jvmTest/kotlin/StructuredConcurrencySpec.kt b/src/jvmTest/kotlin/StructuredConcurrencySpec.kt new file mode 100644 index 00000000000..6000e3f4296 --- /dev/null +++ b/src/jvmTest/kotlin/StructuredConcurrencySpec.kt @@ -0,0 +1,245 @@ +import arrow.core.identity +import arrow.fx.coroutines.ExitCase +import arrow.fx.coroutines.guaranteeCase +import arrow.fx.coroutines.never +import io.kotest.assertions.fail +import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.collections.shouldBeIn +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.matchers.types.shouldBeTypeOf +import io.kotest.property.Arb +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.string +import io.kotest.property.checkAll +import kotlin.time.Duration +import kotlin.time.ExperimentalTime +import kotlin.time.seconds +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withTimeout + +@OptIn(ExperimentalTime::class) +class StructuredConcurrencySpec : StringSpec({ + + "async - suspendCancellableCoroutine.invokeOnCancellation is called with Shifted Continuation" { + val started = CompletableDeferred() + val cancelled = CompletableDeferred() + + cont { + coroutineScope { + val never = async { + suspendCancellableCoroutine { cont -> + cont.invokeOnCancellation { cause -> + require(cancelled.complete(cause)) { "cancelled latch was completed twice" } + } + require(started.complete(Unit)) + } + } + async { + started.await() + shift("hello") + }.await() + never.await() + } + }.runCont() shouldBe "hello" + + withTimeout(Duration.seconds(2)) { + cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" + } + } + + "Computation blocks run on parent context" { + val parentCtx = currentContext() + cont { + currentContext() shouldBe parentCtx + }.runCont() + } + + "Concurrent shift - async await" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + fa.await() + fb.await() + } + }.runCont() shouldBeIn listOf(a, b) + } + } + + "Concurrent shift - async await exit results" { + checkAll(Arb.int()) { a -> + val scopeExit = CompletableDeferred() + val fbExit = CompletableDeferred() + val startLatches = (0..11).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + + cont { + guaranteeCase({ + coroutineScope { + val fa = async { + startLatches.drop(1).zip(nestedExits) { start, promise -> + asyncTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + val fb = asyncTask(startLatches.first(), fbExit) + fa.await() + fb.await() + } + }) { case -> + require(scopeExit.complete(case)) + } + fail("Should never come here") + }.runCont() shouldBe a + withTimeout(2.seconds) { + scopeExit.await().shouldBeTypeOf() + fbExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + } + } + } + + "Concurrent shift - async" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + "I will be overwritten by shift - coroutineScope waits until all async are finished" + } + }.fold({ + fail("Async is never awaited, and thus ignored.") + }, ::identity) shouldBe "I will be overwritten by shift - coroutineScope waits until all async are finished" + } + } + + "Concurrent shift - async exit results" { + checkAll(Arb.int(), Arb.string()) { a, str -> + val exitScope = CompletableDeferred() + val startLatches = (0..10).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + + cont { + guaranteeCase({ + coroutineScope { + val fa = async { + startLatches.zip(nestedExits) { start, promise -> + asyncTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + str + } + }) { case -> require(exitScope.complete(case)) } + }.runCont() shouldBe str + + withTimeout(2.seconds) { + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + } + } + } + + "Concurrent shift - launch" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + launch { shift(a) } + launch { shift(b) } + "shift does not escape `launch`" + } + }.runCont() shouldBe "shift does not escape `launch`" + } + } + + "Concurrent shift - launch exit results" { + checkAll(Arb.int(), Arb.string()) { a, str -> + val scopeExit = CompletableDeferred() + val startLatches = (0..10).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.launchTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Job = launch { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> + require(exit.complete(case)) + } + } + + cont { + guaranteeCase({ + coroutineScope { + val fa = launch { + startLatches.zip(nestedExits) { start, promise -> + launchTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + str + } + }) { case -> require(scopeExit.complete(case)) } + }.runCont() shouldBe str + withTimeout(2.seconds) { + scopeExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + } + } + } + + // `shift` escapes `cont` block, and gets rethrown inside `coroutineScope`. + // Effectively awaiting/executing DSL code, outside of the DSL... + "async funky scenario #1 - Extract `shift` from `cont` through `async`" { + checkAll(Arb.int(), Arb.int()) { a, b -> + runCatching { + coroutineScope { + val shiftedAsync = cont> { + val fa = async { shift(a) } + async { shift(b) } + }.fold({ + fail("shift was never awaited, so it never took effect") + }, ::identity) + shiftedAsync.await() + } + }.exceptionOrNull()?.message shouldBe "Shifted Continuation" + } + } +}) diff --git a/src/jvmTest/kotlin/predef.kt b/src/jvmTest/kotlin/predef.kt new file mode 100644 index 00000000000..fc0a9737fe4 --- /dev/null +++ b/src/jvmTest/kotlin/predef.kt @@ -0,0 +1,7 @@ +import arrow.core.identity + +suspend fun Cont.value(): A = + fold(::identity, ::identity) + +suspend fun Cont<*, *>.runCont(): Any? = + fold(::identity, ::identity) From 5773eb271343b231d78e2a8730e6dd1477b15b20 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 12:32:49 +0100 Subject: [PATCH 023/108] Try KotlinX Knit --- example/build.gradle.kts | 11 ----- example/src/main/kotlin/example.kt | 28 ------------- guide/example/example-readme-01.kt | 15 +++++++ guide/example/example-readme-02.kt | 41 +++++++++++++++++++ guide/example/example-readme-03.kt | 15 +++++++ guide/example/example-readme-04.kt | 33 +++++++++++++++ guide/example/example-readme-05.kt | 12 ++++++ guide/example/example-readme-06.kt | 13 ++++++ guide/example/example-readme-07.kt | 15 +++++++ guide/example/example-readme-08.kt | 40 ++++++++++++++++++ guide/test/ReadmeTest.kt | 29 +++++++++++++ knit.properties | 5 +++ src/commonMain/kotlin/{ => arrow}/Cont.kt | 2 + .../kotlin/{ => arrow}/RestrictedCont.kt | 4 +- src/commonMain/kotlin/{ => arrow}/either.kt | 2 + .../kotlin/{ => arrow}/internal/EmptyValue.kt | 2 +- src/commonMain/kotlin/{ => arrow}/ior.kt | 4 +- src/commonMain/kotlin/{ => arrow}/option.kt | 2 + src/jvmTest/kotlin/{ => arrow}/ContSpec.kt | 2 + src/jvmTest/kotlin/{ => arrow}/IorSpec.kt | 4 +- .../{ => arrow}/StructuredConcurrencySpec.kt | 2 + src/jvmTest/kotlin/{ => arrow}/predef.kt | 2 + 22 files changed, 240 insertions(+), 43 deletions(-) delete mode 100644 example/build.gradle.kts delete mode 100644 example/src/main/kotlin/example.kt create mode 100644 guide/example/example-readme-01.kt create mode 100644 guide/example/example-readme-02.kt create mode 100644 guide/example/example-readme-03.kt create mode 100644 guide/example/example-readme-04.kt create mode 100644 guide/example/example-readme-05.kt create mode 100644 guide/example/example-readme-06.kt create mode 100644 guide/example/example-readme-07.kt create mode 100644 guide/example/example-readme-08.kt create mode 100644 guide/test/ReadmeTest.kt create mode 100644 knit.properties rename src/commonMain/kotlin/{ => arrow}/Cont.kt (99%) rename src/commonMain/kotlin/{ => arrow}/RestrictedCont.kt (98%) rename src/commonMain/kotlin/{ => arrow}/either.kt (89%) rename src/commonMain/kotlin/{ => arrow}/internal/EmptyValue.kt (89%) rename src/commonMain/kotlin/{ => arrow}/ior.kt (96%) rename src/commonMain/kotlin/{ => arrow}/option.kt (98%) rename src/jvmTest/kotlin/{ => arrow}/ContSpec.kt (99%) rename src/jvmTest/kotlin/{ => arrow}/IorSpec.kt (96%) rename src/jvmTest/kotlin/{ => arrow}/StructuredConcurrencySpec.kt (99%) rename src/jvmTest/kotlin/{ => arrow}/predef.kt (92%) diff --git a/example/build.gradle.kts b/example/build.gradle.kts deleted file mode 100644 index ae546b4211a..00000000000 --- a/example/build.gradle.kts +++ /dev/null @@ -1,11 +0,0 @@ -plugins { - kotlin("jvm") -} - -repositories { - mavenCentral() -} - -dependencies { - implementation(rootProject) -} diff --git a/example/src/main/kotlin/example.kt b/example/src/main/kotlin/example.kt deleted file mode 100644 index 91c56e606e1..00000000000 --- a/example/src/main/kotlin/example.kt +++ /dev/null @@ -1,28 +0,0 @@ -import arrow.core.None -import java.io.File -import java.io.FileNotFoundException - -sealed class FileError -data class SecurityError(val msg: String?) : FileError() -data class FileNotFound(val path: String): FileError() -object EmptyPath: FileError() -data class Content(val body: List) - -fun readFile(path: String): Cont = cont { - ensure(path.isNotEmpty()) { EmptyPath } - try { - Content(File(path).readLines()) - } catch (e: FileNotFoundException) { - shift(FileNotFound(path)) - } catch (e: SecurityException) { - shift(SecurityError(e.message)) - } -} - -suspend fun main() { - readFile("").toEither().let(::println) - readFile("not-found").toValidated().let(::println) - readFile("gradle.properties").toIor().let(::println) - readFile("not-found").toOption { None } .let(::println) - readFile("nullable").fold({ _: FileError -> null }, { it }).let(::println) -} diff --git a/guide/example/example-readme-01.kt b/guide/example/example-readme-01.kt new file mode 100644 index 00000000000..ae5448ca915 --- /dev/null +++ b/guide/example/example-readme-01.kt @@ -0,0 +1,15 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme01 + +import arrow.Cont +import arrow.cont + +object EmptyPath + +fun readFile(path: String): Cont = cont { + if (path.isNotEmpty()) shift(EmptyPath) else Unit +} + +fun readFile2(path: String?): Cont = cont { + ensure(!path.isNullOrBlank()) { EmptyPath } +} diff --git a/guide/example/example-readme-02.kt b/guide/example/example-readme-02.kt new file mode 100644 index 00000000000..a5aecc0792d --- /dev/null +++ b/guide/example/example-readme-02.kt @@ -0,0 +1,41 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme02 + +import arrow.Cont +import arrow.cont +import arrow.ensureNotNull +import arrow.core.None +import java.io.File +import java.io.FileNotFoundException +import kotlinx.coroutines.runBlocking + +@JvmInline +value class Content(val body: List) + +sealed interface FileError +@JvmInline value class SecurityError(val msg: String?) : FileError +@JvmInline value class FileNotFound(val path: String) : FileError +object EmptyPath : FileError { + override fun toString() = "EmptyPath" +} + +fun readFile(path: String?): Cont = cont { + ensureNotNull(path) { EmptyPath } + ensure(path.isNotEmpty()) { EmptyPath } + try { + val lines = File(path).readLines() + Content(lines) + } catch (e: FileNotFoundException) { + shift(FileNotFound(path)) + } catch (e: SecurityException) { + shift(SecurityError(e.message)) + } +} + +fun main() = runBlocking { + readFile("").toEither().also(::println) + readFile("not-found").toValidated().also(::println) + readFile("gradle.properties").toIor().also(::println) + readFile("not-found").toOption { None }.also(::println) + readFile("nullable").fold({ _: FileError -> null }, { it }).also(::println) +} diff --git a/guide/example/example-readme-03.kt b/guide/example/example-readme-03.kt new file mode 100644 index 00000000000..33b02b57355 --- /dev/null +++ b/guide/example/example-readme-03.kt @@ -0,0 +1,15 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme03 + +import arrow.Cont +import arrow.core.identity +import arrow.core.Either +import arrow.core.Option +import arrow.core.None +import arrow.core.Some + +suspend fun Cont.toEither(): Either = + fold({ Either.Left(it) }) { Either.Right(it) } + +suspend fun Cont.toOption(): Option = + fold(::identity) { Some(it) } diff --git a/guide/example/example-readme-04.kt b/guide/example/example-readme-04.kt new file mode 100644 index 00000000000..1b4ddf2021a --- /dev/null +++ b/guide/example/example-readme-04.kt @@ -0,0 +1,33 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme04 + +import arrow.Cont +import arrow.cont +import arrow.core.identity +import kotlinx.coroutines.runBlocking + +val failed: Cont = + cont { shift("failed") } + +val resolved: Cont = + failed.handleError { it.length } + +val newError: Cont, Int> = + failed.handleErrorWith { str -> + cont { shift(str.reversed().toList()) } + } + +val redeemed: Cont = + failed.redeem({ str -> str.length }, ::identity) + +val captured: Cont> = cont { + throw RuntimeException("Boom") +}.attempt() + +fun main() = runBlocking { + println(failed.toEither()) + println(resolved.toEither()) + println(newError.toEither()) + println(redeemed.toEither()) + println(captured.toEither()) +} diff --git a/guide/example/example-readme-05.kt b/guide/example/example-readme-05.kt new file mode 100644 index 00000000000..372e324358c --- /dev/null +++ b/guide/example/example-readme-05.kt @@ -0,0 +1,12 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme05 + +import arrow.cont +import arrow.fx.coroutines.parZip +import kotlinx.coroutines.delay + +suspend fun parZip(): Unit = cont { + parZip({ + delay(1_000_000) // Cancelled by shift + }, { shift("error") }) { _, int -> int } +}.fold(::println, ::println) // "error" diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt new file mode 100644 index 00000000000..63618021304 --- /dev/null +++ b/guide/example/example-readme-06.kt @@ -0,0 +1,13 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme06 + +import arrow.cont +import arrow.fx.coroutines.parTraverse +import kotlinx.coroutines.delay + +suspend fun parTraverse() = cont> { + (0..100).parTraverse { index -> // running tasks + if(index == 50) shift("error") + else index.also { delay(1_000_000) } // Cancelled by shift + } +}.fold(::println, ::println) // "error" diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt new file mode 100644 index 00000000000..aedf18eab06 --- /dev/null +++ b/guide/example/example-readme-07.kt @@ -0,0 +1,15 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme07 + +import arrow.cont +import arrow.core.merge +import arrow.fx.coroutines.raceN +import kotlinx.coroutines.delay + +suspend fun race() = cont { + raceN({ + delay(1_000_000) // Cancelled by shift + 5 + }) { shift("error") } + .merge() // Flatten Either result from race into Int +}.fold(::println, ::println) // "error" diff --git a/guide/example/example-readme-08.kt b/guide/example/example-readme-08.kt new file mode 100644 index 00000000000..18d5e43399f --- /dev/null +++ b/guide/example/example-readme-08.kt @@ -0,0 +1,40 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme08 + +import arrow.cont +import arrow.fx.coroutines.ExitCase +import arrow.fx.coroutines.bracketCase +import arrow.fx.coroutines.Resource +import arrow.fx.coroutines.fromAutoCloseable +import java.io.BufferedReader +import java.io.File + +suspend fun bracketCase() = cont { + bracketCase( + acquire = { File("gradle.properties").bufferedReader() }, + use = { reader -> + // some logic + shift("file doesn't contain right content") + }, + release = { reader, exitCase -> + reader.close() + println(exitCase) // ExitCase.Cancelled(ShiftCancellationException("Shifted Continuation")) + } + ) +}.fold(::println, ::println) // "file doesn't contain right content" + +// Available from Arrow 1.1.x +fun Resource.releaseCase(releaseCase: (A, ExitCase) -> Unit): Resource = + flatMap { a -> Resource({ a }, releaseCase) } + +fun bufferedReader(path: String): Resource = + Resource.fromAutoCloseable { + File(path).bufferedReader() + }.releaseCase { _, exitCase -> println(exitCase) } + +suspend fun resource() = cont { + bufferedReader("gradle.properties").use { reader -> + // some logic + shift("file doesn't contain right content") + } // ExitCase.Cancelled(ShiftCancellationException("Shifted Continuation")) printed from release +} diff --git a/guide/test/ReadmeTest.kt b/guide/test/ReadmeTest.kt new file mode 100644 index 00000000000..cb46d53ee45 --- /dev/null +++ b/guide/test/ReadmeTest.kt @@ -0,0 +1,29 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.test + +import org.junit.Test +import kotlinx.knit.test.* + +class ReadmeTest { + @Test + fun testExampleReadme02() { + captureOutput("ExampleReadme02") { example.exampleReadme02.main() }.verifyOutputLines( + "Either.Left(EmptyPath)", + "Validated.Invalid(FileNotFound(path=not-found))", + "Ior.Left(FileNotFound(path=gradle.properties))", + "Option.None", + "null" + ) + } + + @Test + fun testExampleReadme04() { + captureOutput("ExampleReadme04") { example.exampleReadme04.main() }.verifyOutputLines( + "Either.Left(failed)", + "Either.Right(6)", + "Either.Left([d, e, l, i, a, f])", + "Either.Right(6)", + "Either.Right(Failure(java.lang.RuntimeException: Boom))" + ) + } +} diff --git a/knit.properties b/knit.properties new file mode 100644 index 00000000000..a267d497a18 --- /dev/null +++ b/knit.properties @@ -0,0 +1,5 @@ +knit.dir=guide/example/ +knit.package=example + +test.dir=guide/test/ +test.package=example.test \ No newline at end of file diff --git a/src/commonMain/kotlin/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt similarity index 99% rename from src/commonMain/kotlin/Cont.kt rename to src/commonMain/kotlin/arrow/Cont.kt index d38a08992f8..1089e4110ae 100644 --- a/src/commonMain/kotlin/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.Either import arrow.core.Ior import arrow.core.None diff --git a/src/commonMain/kotlin/RestrictedCont.kt b/src/commonMain/kotlin/arrow/RestrictedCont.kt similarity index 98% rename from src/commonMain/kotlin/RestrictedCont.kt rename to src/commonMain/kotlin/arrow/RestrictedCont.kt index 70cb86262d1..45731050e87 100644 --- a/src/commonMain/kotlin/RestrictedCont.kt +++ b/src/commonMain/kotlin/arrow/RestrictedCont.kt @@ -1,7 +1,9 @@ +package arrow + import arrow.core.Either import arrow.core.Validated import arrow.core.identity -import internal.EmptyValue +import arrow.internal.EmptyValue import kotlin.coroutines.Continuation import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.RestrictsSuspension diff --git a/src/commonMain/kotlin/either.kt b/src/commonMain/kotlin/arrow/either.kt similarity index 89% rename from src/commonMain/kotlin/either.kt rename to src/commonMain/kotlin/arrow/either.kt index f8f049e0204..820effdfdb4 100644 --- a/src/commonMain/kotlin/either.kt +++ b/src/commonMain/kotlin/arrow/either.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.Either suspend fun either(f: suspend ContEffect.() -> A): Either = diff --git a/src/commonMain/kotlin/internal/EmptyValue.kt b/src/commonMain/kotlin/arrow/internal/EmptyValue.kt similarity index 89% rename from src/commonMain/kotlin/internal/EmptyValue.kt rename to src/commonMain/kotlin/arrow/internal/EmptyValue.kt index c5857a1dd69..452af289c90 100644 --- a/src/commonMain/kotlin/internal/EmptyValue.kt +++ b/src/commonMain/kotlin/arrow/internal/EmptyValue.kt @@ -1,4 +1,4 @@ -package internal +package arrow.internal @PublishedApi internal object EmptyValue { diff --git a/src/commonMain/kotlin/ior.kt b/src/commonMain/kotlin/arrow/ior.kt similarity index 96% rename from src/commonMain/kotlin/ior.kt rename to src/commonMain/kotlin/arrow/ior.kt index 4688188818a..35108033aad 100644 --- a/src/commonMain/kotlin/ior.kt +++ b/src/commonMain/kotlin/arrow/ior.kt @@ -1,9 +1,11 @@ +package arrow + import arrow.continuations.generic.AtomicRef import arrow.continuations.generic.updateAndGet import arrow.core.Ior import arrow.core.identity +import arrow.internal.EmptyValue import arrow.typeclasses.Semigroup -import internal.EmptyValue suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior = cont> { diff --git a/src/commonMain/kotlin/option.kt b/src/commonMain/kotlin/arrow/option.kt similarity index 98% rename from src/commonMain/kotlin/option.kt rename to src/commonMain/kotlin/arrow/option.kt index 640c3657c3e..2946f08cadc 100644 --- a/src/commonMain/kotlin/option.kt +++ b/src/commonMain/kotlin/arrow/option.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.None import arrow.core.Option import arrow.core.Some diff --git a/src/jvmTest/kotlin/ContSpec.kt b/src/jvmTest/kotlin/arrow/ContSpec.kt similarity index 99% rename from src/jvmTest/kotlin/ContSpec.kt rename to src/jvmTest/kotlin/arrow/ContSpec.kt index 72686adbc07..56b47d3fe1d 100644 --- a/src/jvmTest/kotlin/ContSpec.kt +++ b/src/jvmTest/kotlin/arrow/ContSpec.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.Either import arrow.core.identity import arrow.core.left diff --git a/src/jvmTest/kotlin/IorSpec.kt b/src/jvmTest/kotlin/arrow/IorSpec.kt similarity index 96% rename from src/jvmTest/kotlin/IorSpec.kt rename to src/jvmTest/kotlin/arrow/IorSpec.kt index 4d9f104b7a9..5d9eacb06c9 100644 --- a/src/jvmTest/kotlin/IorSpec.kt +++ b/src/jvmTest/kotlin/arrow/IorSpec.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.Either import arrow.core.Ior import arrow.typeclasses.Semigroup @@ -28,7 +30,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Left("Hello, World!") } - "Concurrent - ior bind" { + "Concurrent - arrow.ior bind" { checkAll(Arb.list(Arb.string()).filter(List::isNotEmpty)) { strs -> ior(Semigroup.list()) { strs.mapIndexed { index, s -> diff --git a/src/jvmTest/kotlin/StructuredConcurrencySpec.kt b/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt similarity index 99% rename from src/jvmTest/kotlin/StructuredConcurrencySpec.kt rename to src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt index 6000e3f4296..b8f6d6d267b 100644 --- a/src/jvmTest/kotlin/StructuredConcurrencySpec.kt +++ b/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.identity import arrow.fx.coroutines.ExitCase import arrow.fx.coroutines.guaranteeCase diff --git a/src/jvmTest/kotlin/predef.kt b/src/jvmTest/kotlin/arrow/predef.kt similarity index 92% rename from src/jvmTest/kotlin/predef.kt rename to src/jvmTest/kotlin/arrow/predef.kt index fc0a9737fe4..3fabb2352f3 100644 --- a/src/jvmTest/kotlin/predef.kt +++ b/src/jvmTest/kotlin/arrow/predef.kt @@ -1,3 +1,5 @@ +package arrow + import arrow.core.identity suspend fun Cont.value(): A = From 1134615f76cde76a49417dba4e688229fdc28517 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 20:25:05 +0100 Subject: [PATCH 024/108] Add more Knit examples, and setup Dokka --- guide/example/example-cont-01.kt | 22 ++++ guide/example/example-cont-02.kt | 17 +++ guide/example/example-readme-06.kt | 16 ++- guide/example/example-readme-07.kt | 18 +-- guide/example/example-readme-09.kt | 57 ++++++++++ guide/test/ContTest.kt | 23 ++++ guide/test/ReadmeTest.kt | 28 +++++ src/commonMain/kotlin/arrow/Cont.kt | 168 ++++++++++++++++++++++------ 8 files changed, 299 insertions(+), 50 deletions(-) create mode 100644 guide/example/example-cont-01.kt create mode 100644 guide/example/example-cont-02.kt create mode 100644 guide/example/example-readme-09.kt create mode 100644 guide/test/ContTest.kt diff --git a/guide/example/example-cont-01.kt b/guide/example/example-cont-01.kt new file mode 100644 index 00000000000..8e4a95aad48 --- /dev/null +++ b/guide/example/example-cont-01.kt @@ -0,0 +1,22 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont01 + +import arrow.core.* +import arrow.cont +import kotlinx.coroutines.runBlocking + +fun main() = runBlocking { + cont { + val x = Either.Right(1).bind() + val y = Validated.Valid(2).bind() + val z = Option(3).bind { "Option was empty" } + x + y + z + }.fold(::println, ::println) + + cont { + val x = Either.Right(1).bind() + val y = Validated.Valid(2).bind() + val z: Int = None.bind { "Option was empty" } + x + y + z + }.fold(::println, ::println) +} diff --git a/guide/example/example-cont-02.kt b/guide/example/example-cont-02.kt new file mode 100644 index 00000000000..8eaa912c481 --- /dev/null +++ b/guide/example/example-cont-02.kt @@ -0,0 +1,17 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont02 + +import arrow.cont +import kotlinx.coroutines.runBlocking + +fun main() = runBlocking { + cont { + shift("Hello, World!") + }.fold({ str: String -> str }, { int -> int.toString() }) + .let(::println) + + cont { + 1000 + }.fold({ str: String -> str.length }, { int -> int }) + .let(::println) +} diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt index 63618021304..5a11b949feb 100644 --- a/guide/example/example-readme-06.kt +++ b/guide/example/example-readme-06.kt @@ -2,12 +2,16 @@ package example.exampleReadme06 import arrow.cont +import arrow.fx.coroutines.onCancel import arrow.fx.coroutines.parTraverse import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking -suspend fun parTraverse() = cont> { - (0..100).parTraverse { index -> // running tasks - if(index == 50) shift("error") - else index.also { delay(1_000_000) } // Cancelled by shift - } -}.fold(::println, ::println) // "error" +fun main() = runBlocking { + cont> { + (1..5).parTraverse { index -> + if (index == 5) shift("error") + else onCancel({ delay(1_000_000) }) { println("I got cancelled") } + } + }.fold(::println, ::println) +} diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt index aedf18eab06..c0641d88ba5 100644 --- a/guide/example/example-readme-07.kt +++ b/guide/example/example-readme-07.kt @@ -3,13 +3,17 @@ package example.exampleReadme07 import arrow.cont import arrow.core.merge +import arrow.fx.coroutines.onCancel import arrow.fx.coroutines.raceN import kotlinx.coroutines.delay +import kotlinx.coroutines.runBlocking -suspend fun race() = cont { - raceN({ - delay(1_000_000) // Cancelled by shift - 5 - }) { shift("error") } - .merge() // Flatten Either result from race into Int -}.fold(::println, ::println) // "error" +fun main() = runBlocking { + cont { + raceN({ + onCancel({ delay(1_000_000) }) { println("I lost the race...") } + 5 + }) { shift("error") } + .merge() // Flatten Either result from race into Int + }.fold(::println, ::println) +} diff --git a/guide/example/example-readme-09.kt b/guide/example/example-readme-09.kt new file mode 100644 index 00000000000..3dac0160762 --- /dev/null +++ b/guide/example/example-readme-09.kt @@ -0,0 +1,57 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme09 + +import arrow.cont +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import arrow.Cont +import arrow.ensureNotNull +import java.io.File +import java.io.FileNotFoundException +import kotlin.coroutines.cancellation.CancellationException +import kotlinx.coroutines.Job +import kotlinx.coroutines.runBlocking + +@JvmInline +value class Content(val body: List) + +sealed interface FileError +@JvmInline value class SecurityError(val msg: String?) : FileError +@JvmInline value class FileNotFound(val path: String) : FileError +object EmptyPath : FileError { + override fun toString() = "EmptyPath" +} + +fun readFile(path: String?): Cont = cont { + ensureNotNull(path) { EmptyPath } + ensure(path.isNotEmpty()) { EmptyPath } + try { + val lines = File(path).readLines() + Content(lines) + } catch (e: FileNotFoundException) { + shift(FileNotFound(path)) + } catch (e: SecurityException) { + shift(SecurityError(e.message)) + } +} + +fun A.onCancel(f: (CancellationException) -> Unit): A = also { + invokeOnCompletion { error -> + if (error is CancellationException) f(error) else Unit + } +} + +fun main() = runBlocking { + cont { + withContext(Dispatchers.IO) { + launch { delay(1_000_000) }.onCancel { println("Cancelled due to shift: $it") } + val sleeper = async { delay(1_000_000) }.onCancel { println("Cancelled due to shift: $it") } + val content = readFile("failure").bind() + sleeper.await() + content.body.size + } + }.fold(::println, ::println) +} diff --git a/guide/test/ContTest.kt b/guide/test/ContTest.kt new file mode 100644 index 00000000000..ecb36e05805 --- /dev/null +++ b/guide/test/ContTest.kt @@ -0,0 +1,23 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.test + +import org.junit.Test +import kotlinx.knit.test.* + +class ContTest { + @Test + fun testExampleCont01() { + captureOutput("ExampleCont01") { example.exampleCont01.main() }.verifyOutputLines( + "6", + "Option was empty" + ) + } + + @Test + fun testExampleCont02() { + captureOutput("ExampleCont02") { example.exampleCont02.main() }.verifyOutputLines( + "Hello, World!", + "1000" + ) + } +} diff --git a/guide/test/ReadmeTest.kt b/guide/test/ReadmeTest.kt index cb46d53ee45..2b847cbd18a 100644 --- a/guide/test/ReadmeTest.kt +++ b/guide/test/ReadmeTest.kt @@ -26,4 +26,32 @@ class ReadmeTest { "Either.Right(Failure(java.lang.RuntimeException: Boom))" ) } + + @Test + fun testExampleReadme06() { + captureOutput("ExampleReadme06") { example.exampleReadme06.main() }.verifyOutputLines( + "I got cancelled", + "I got cancelled", + "I got cancelled", + "I got cancelled", + "error" + ) + } + + @Test + fun testExampleReadme07() { + captureOutput("ExampleReadme07") { example.exampleReadme07.main() }.verifyOutputLines( + "I lost the race...", + "error" + ) + } + + @Test + fun testExampleReadme09() { + captureOutput("ExampleReadme09") { example.exampleReadme09.main() }.verifyOutputLines( + "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", + "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", + "FileNotFound(path=failure)" + ) + } } diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index 1089e4110ae..988295873d2 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -1,6 +1,8 @@ package arrow import arrow.core.Either +import arrow.core.NonFatal +import kotlin.Result import arrow.core.Ior import arrow.core.None import arrow.core.Option @@ -19,6 +21,38 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.resume import kotlin.jvm.JvmInline +/** + * DSL for constructing Cont values + * + * + * ```kotlin + * import arrow.core.* + * import arrow.cont + * import kotlinx.coroutines.runBlocking + * + * fun main() = runBlocking { + * cont { + * val x = Either.Right(1).bind() + * val y = Validated.Valid(2).bind() + * val z = Option(3).bind { "Option was empty" } + * x + y + z + * }.fold(::println, ::println) + * + * cont { + * val x = Either.Right(1).bind() + * val y = Validated.Valid(2).bind() + * val z: Int = None.bind { "Option was empty" } + * x + y + z + * }.fold(::println, ::println) + * } + * ``` + * + * ```text + * 6 + * Option was empty + * ``` + * + */ public fun cont(f: suspend ContEffect.() -> A): Cont = ContImpl(f) @@ -30,30 +64,85 @@ public fun cont(f: suspend ContEffect.() -> A): Cont = * So [Cont] is defined by [fold], to map both values of [R] and [A] to a value of `B`. */ public interface Cont { - suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B + /** + * Runs the suspending computation by creating a [Continuation], + * and running the `fold` function over the computation. + * + * When the [Cont] has shifted with [R] it will [recover] the shifted value to [B], + * and when it ran the computation to completion it will [transform] the value [A] to [B]. + * + * ```kotlin + * import arrow.cont + * import kotlinx.coroutines.runBlocking + * + * fun main() = runBlocking { + * cont { + * shift("Hello, World!") + * }.fold({ str: String -> str }, { int -> int.toString() }) + * .let(::println) + * + * cont { + * 1000 + * }.fold({ str: String -> str.length }, { int -> int }) + * .let(::println) + * } + * ``` + * + * ```text + * Hello, World! + * 1000 + * ``` + * + */ + suspend fun fold(recover: suspend (shifted: R) -> B, transform: suspend (value: A) -> B): B + /** + * Like `fold` but also allows folding over any unexpected [Throwable] that might have occurred. + * @see fold + */ suspend fun fold( - error: suspend (Throwable) -> B, - f: suspend (R) -> B, - g: suspend (A) -> B + error: suspend (error: Throwable) -> B, + recover: suspend (shifted: R) -> B, + transform: suspend (value: A) -> B ): B = try { - fold(f, g) + fold(recover, transform) } catch (e: Throwable) { error(e.nonFatalOrThrow()) } + /** + * [fold] the [Cont] into an [Either]. + * Where the shifted value [R] is mapped to [Either.Left], + * and result value [A] is mapped to [Either.Right]. + */ suspend fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } + /** + * [fold] the [Cont] into an [Ior]. + * Where the shifted value [R] is mapped to [Ior.Left], + * and result value [A] is mapped to [Ior.Right]. + */ suspend fun toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } + /** + * [fold] the [Cont] into an [Validated]. + * Where the shifted value [R] is mapped to [Validated.Invalid], + * and result value [A] is mapped to [Validated.Valid]. + */ suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + /** + * [fold] the [Cont] into an [Option]. + * Where the shifted value [R] is mapped to [Option] by the provided function [orElse], + * and result value [A] is mapped to [Some]. + */ suspend fun toOption(orElse: suspend (R) -> Option): Option = fold(orElse, ::Some) + /** Runs the [Cont] and captures any [NonFatal] exception into [Result]. */ fun attempt(): Cont> = cont { try { @@ -63,27 +152,29 @@ public interface Cont { } } - fun map(f: suspend (A) -> B): Cont = - cont { fold(this::shift, f) } + /** Maps the values [A] with the [transform] function into [B]. */ + fun map(transform: suspend (A) -> B): Cont = + cont { fold(this::shift, transform) } - fun flatMap(f: suspend (A) -> Cont): Cont = - cont { fold(this::shift, f).bind() } + /** Maps the values [A] with the [transform] function into another [Cont] effect. */ + fun flatMap(transform: suspend (A) -> Cont): Cont = + cont { fold(this::shift, transform).bind() } - fun handleError(f: suspend (R) -> A): Cont = - cont { fold(f, ::identity) } + fun handleError(recover: suspend (R) -> A): Cont = + cont { fold(recover, ::identity) } - fun handleErrorWith(f: suspend (R) -> Cont): Cont = - cont { fold({ f(it).bind() }, ::identity) } + fun handleErrorWith(recover: suspend (R) -> Cont): Cont = + cont { fold({ recover(it).bind() }, ::identity) } - fun redeem(f: suspend (R) -> B, g: suspend (A) -> B): Cont = - cont { fold(f, g) } + fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont = + cont { fold(recover, transform) } - fun redeemWith(f: suspend (R) -> Cont, g: suspend (A) -> Cont): Cont = - cont { fold(f, g).bind() } + fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont = + cont { fold(recover, transform).bind() } } -fun Iterable.traverseCont(f: (A) -> Cont): Cont> = - cont { map { f(it).bind() } } +fun Iterable.traverseCont(transform: (A) -> Cont): Cont> = + cont { map { transform(it).bind() } } fun Iterable>.sequence(): Cont> = traverseCont(::identity) @@ -95,10 +186,6 @@ interface ContEffect { */ public suspend fun shift(r: R): B - /** ApplicativeError alias for shift */ - public suspend fun raiseError(r: R): B = - shift(r) - public suspend fun Cont.bind(): B = fold(this@ContEffect::shift, ::identity) @@ -138,22 +225,14 @@ public suspend fun ContEffect.ensureNotNull(value: B?, shift: () return value ?: shift(shift()) } -// Full internal runtime implementation of Cont below - -public open class ControlThrowable( - override val message: String? = null, - override val cause: Throwable? = null -) : Throwable(message, cause) { - // Expect/actual JVM (fillStackTrace) -} - - sealed class ShiftCancellationException : CancellationException("Shifted Continuation") private class Internal( val token: Token, val shifted: Any?, val fold: suspend (Any?) -> Any? -): ShiftCancellationException() +): ShiftCancellationException() { + override fun toString(): String = "ShiftCancellationException($message)" +} // Class that represents a unique token by hash comparison private class Token { @@ -162,8 +241,23 @@ private class Token { @JvmInline private value class ContImpl(private val f: suspend ContEffect.() -> A) : Cont { + + override fun attempt(): Cont> = ContImpl { + try { + Result.success(f()) + } catch (e: Throwable) { + Result.failure(e.nonFatalOrThrow()) + } + } + + override fun map(transform: suspend (A) -> B): Cont = + ContImpl { transform(f()) } + + override fun flatMap(transform: suspend (A) -> Cont): Cont = + ContImpl { transform(f()).bind() } + // We create a `Token` for fold Continuation, so we can properly differentiate between nested folds - override suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B = + override suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B = suspendCoroutineUninterceptedOrReturn { cont -> val token = Token() val effect = object : ContEffect { @@ -176,11 +270,11 @@ private value class ContImpl(private val f: suspend ContEffect.() -> A) // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests - throw Internal(token, r, f as suspend (Any?) -> Any?) + throw Internal(token, r, recover as suspend (Any?) -> Any?) } try { - suspend { g(f(effect)) }.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) + suspend { transform(f(effect)) }.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) } catch (e: Internal) { if (token == e.token) { val f: suspend () -> B = { e.fold(e.shifted) as B } From edadce49d242a16750b92aeaeff565281cf44204 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 21:35:45 +0100 Subject: [PATCH 025/108] Setup docs --- .github/workflows/pr.yaml | 72 ++++++++++++++++++++++++++++++ guide/example/example-readme-10.kt | 19 ++++++++ guide/test/ReadmeTest.kt | 57 ----------------------- 3 files changed, 91 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/pr.yaml create mode 100644 guide/example/example-readme-10.kt delete mode 100644 guide/test/ReadmeTest.kt diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml new file mode 100644 index 00000000000..3c1a06fe770 --- /dev/null +++ b/.github/workflows/pr.yaml @@ -0,0 +1,72 @@ +name: "Build main" + +on: + pull_request: + paths-ignore: + - 'docs/**' + - '*.md' + +env: + JAVA_OPTS: -Xms512m -Xmx1024m + GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" + +jobs: + check: + strategy: + matrix: + os: [ windows-latest, ubuntu-latest ] + runs-on: ${{matrix.os}} + timeout-minutes: 20 + steps: + - name: Checkout the repo + uses: actions/checkout@v2 + + - name: Restore Gradle cache + id: cache + uses: actions/cache@v2.1.6 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + ~/.gradle/yarn + ~/.gradle/nodejs + ~/.konan + key: ${{ runner.os }}-check-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-check- + + - name: Run Ubuntu tests + if: matrix.os == 'ubuntu-latest' + run: ./gradlew check + + - name: Run Windows tests + if: matrix.os == 'windows-latest' + run: ./gradlew mingwX64Test + + - name: Bundle the build report + if: failure() + run: find . -type d -name 'reports' | zip -@ -r build-reports.zip + + - name: Upload the build report + if: failure() + uses: actions/upload-artifact@master + with: + name: error-report + path: build-reports.zip + + docs: + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Dokka + id: Dokka + continue-on-error: true + run: ./gradlew dokkaHtml + + - uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Auto update docs \ No newline at end of file diff --git a/guide/example/example-readme-10.kt b/guide/example/example-readme-10.kt new file mode 100644 index 00000000000..8569201a7e7 --- /dev/null +++ b/guide/example/example-readme-10.kt @@ -0,0 +1,19 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme10 + +import arrow.cont +import arrow.core.identity +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.runBlocking +import io.kotest.matchers.collections.shouldBeIn + +fun main() = runBlocking { + coroutineScope { + cont { + val fa = async { shift(1) } + val fb = async { shift(2) } + fa.await() + fb.await() + }.fold(::identity, ::identity) shouldBeIn listOf(1, 2) + } +} diff --git a/guide/test/ReadmeTest.kt b/guide/test/ReadmeTest.kt deleted file mode 100644 index 2b847cbd18a..00000000000 --- a/guide/test/ReadmeTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -// This file was automatically generated from README.md by Knit tool. Do not edit. -package example.test - -import org.junit.Test -import kotlinx.knit.test.* - -class ReadmeTest { - @Test - fun testExampleReadme02() { - captureOutput("ExampleReadme02") { example.exampleReadme02.main() }.verifyOutputLines( - "Either.Left(EmptyPath)", - "Validated.Invalid(FileNotFound(path=not-found))", - "Ior.Left(FileNotFound(path=gradle.properties))", - "Option.None", - "null" - ) - } - - @Test - fun testExampleReadme04() { - captureOutput("ExampleReadme04") { example.exampleReadme04.main() }.verifyOutputLines( - "Either.Left(failed)", - "Either.Right(6)", - "Either.Left([d, e, l, i, a, f])", - "Either.Right(6)", - "Either.Right(Failure(java.lang.RuntimeException: Boom))" - ) - } - - @Test - fun testExampleReadme06() { - captureOutput("ExampleReadme06") { example.exampleReadme06.main() }.verifyOutputLines( - "I got cancelled", - "I got cancelled", - "I got cancelled", - "I got cancelled", - "error" - ) - } - - @Test - fun testExampleReadme07() { - captureOutput("ExampleReadme07") { example.exampleReadme07.main() }.verifyOutputLines( - "I lost the race...", - "error" - ) - } - - @Test - fun testExampleReadme09() { - captureOutput("ExampleReadme09") { example.exampleReadme09.main() }.verifyOutputLines( - "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", - "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", - "FileNotFound(path=failure)" - ) - } -} From a2e4cfc3aa1aa5e3ed29b8d2ac6c568fe50eb582 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 21:39:29 +0100 Subject: [PATCH 026/108] Rename branch --- .github/workflows/build.yaml | 8 ++++---- .github/workflows/pr.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index f86b54981fe..53c37586c1c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -4,9 +4,9 @@ on: # Trigger the workflow on push or pull request, # but only for the main branch push: - branches: - - main - pull_request: + paths-ignore: + - 'docs/**' + - '*.md' branches: - main @@ -38,7 +38,7 @@ jobs: linux-step-gradle- - name: Build - run: ./gradlew jvmTest + run: ./gradlew check - name: "Prepare test reports" if: ${{ always() }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 3c1a06fe770..b52a5cb4709 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -14,7 +14,7 @@ jobs: check: strategy: matrix: - os: [ windows-latest, ubuntu-latest ] + os: [ ubuntu-latest ] runs-on: ${{matrix.os}} timeout-minutes: 20 steps: From 65c325ecd942bc2ff03f8d480398ea2bedb36741 Mon Sep 17 00:00:00 2001 From: nomisRev Date: Tue, 9 Nov 2021 20:41:19 +0000 Subject: [PATCH 027/108] Auto update docs --- .../arrow/-cont-effect/bind.html | 38 + .../arrow/-cont-effect/ensure.html | 49 + .../arrow/-cont-effect/index.html | 141 ++ .../arrow/-cont-effect/shift.html | 49 + docs/-continuation/arrow/-cont/attempt.html | 49 + docs/-continuation/arrow/-cont/flat-map.html | 49 + docs/-continuation/arrow/-cont/fold.html | 44 + .../arrow/-cont/handle-error-with.html | 49 + .../arrow/-cont/handle-error.html | 49 + docs/-continuation/arrow/-cont/index.html | 280 ++++ docs/-continuation/arrow/-cont/map.html | 49 + .../arrow/-cont/redeem-with.html | 49 + docs/-continuation/arrow/-cont/redeem.html | 49 + docs/-continuation/arrow/-cont/to-either.html | 49 + docs/-continuation/arrow/-cont/to-ior.html | 49 + docs/-continuation/arrow/-cont/to-option.html | 49 + .../arrow/-cont/to-validated.html | 49 + .../arrow/-ior-effect/-ior-effect.html | 49 + .../-continuation/arrow/-ior-effect/bind.html | 49 + .../arrow/-ior-effect/index.html | 153 ++ .../arrow/-ior-effect/shift.html | 49 + .../arrow/-option-effect/-option-effect.html | 49 + .../arrow/-option-effect/bind.html | 49 + .../arrow/-option-effect/ensure.html | 49 + .../arrow/-option-effect/index.html | 102 ++ .../arrow/-option-effect/shift.html | 49 + .../arrow/-restricted-cont-effect/bind.html | 49 + .../arrow/-restricted-cont-effect/index.html | 85 ++ .../arrow/-restricted-cont-effect/shift.html | 49 + .../arrow/-restricted-cont/attempt.html | 49 + .../arrow/-restricted-cont/flat-map.html | 49 + .../arrow/-restricted-cont/fold.html | 49 + .../-restricted-cont/handle-error-with.html | 49 + .../arrow/-restricted-cont/handle-error.html | 49 + .../arrow/-restricted-cont/index.html | 221 +++ .../arrow/-restricted-cont/map.html | 49 + .../arrow/-restricted-cont/redeem-with.html | 49 + .../arrow/-restricted-cont/redeem.html | 49 + .../arrow/-restricted-cont/to-either.html | 49 + .../arrow/-restricted-cont/to-validated.html | 49 + .../-shift-cancellation-exception/index.html | 77 ++ docs/-continuation/arrow/cont.html | 49 + docs/-continuation/arrow/either.html | 49 + docs/-continuation/arrow/ensure-not-null.html | 38 + docs/-continuation/arrow/index.html | 313 +++++ docs/-continuation/arrow/ior.html | 49 + docs/-continuation/arrow/option.html | 49 + docs/-continuation/arrow/restricted-cont.html | 49 + docs/-continuation/arrow/sequence.html | 49 + docs/-continuation/arrow/to-option.html | 49 + docs/-continuation/arrow/traverse-cont.html | 49 + docs/-continuation/package-list | 61 + docs/images/anchor-copy-button.svg | 4 + docs/images/arrow_down.svg | 3 + docs/images/copy-icon.svg | 3 + docs/images/copy-successful-icon.svg | 3 + docs/images/docs_logo.svg | 7 + docs/images/footer-go-to-link.svg | 3 + docs/images/go-to-top-icon.svg | 4 + docs/images/logo-icon.svg | 3 + docs/index.html | 46 + docs/navigation.html | 55 + docs/scripts/clipboard.js | 52 + docs/scripts/main.js | 67 + docs/scripts/navigation-loader.js | 64 + docs/scripts/navigation-pane.json | 1 + docs/scripts/pages.json | 1 + docs/scripts/platform-content-handler.js | 346 +++++ docs/scripts/sourceset_dependencies.js | 1 + docs/styles/jetbrains-mono.css | 17 + docs/styles/logo-styles.css | 3 + docs/styles/main.css | 113 ++ docs/styles/style.css | 1228 +++++++++++++++++ 73 files changed, 5537 insertions(+) create mode 100644 docs/-continuation/arrow/-cont-effect/bind.html create mode 100644 docs/-continuation/arrow/-cont-effect/ensure.html create mode 100644 docs/-continuation/arrow/-cont-effect/index.html create mode 100644 docs/-continuation/arrow/-cont-effect/shift.html create mode 100644 docs/-continuation/arrow/-cont/attempt.html create mode 100644 docs/-continuation/arrow/-cont/flat-map.html create mode 100644 docs/-continuation/arrow/-cont/fold.html create mode 100644 docs/-continuation/arrow/-cont/handle-error-with.html create mode 100644 docs/-continuation/arrow/-cont/handle-error.html create mode 100644 docs/-continuation/arrow/-cont/index.html create mode 100644 docs/-continuation/arrow/-cont/map.html create mode 100644 docs/-continuation/arrow/-cont/redeem-with.html create mode 100644 docs/-continuation/arrow/-cont/redeem.html create mode 100644 docs/-continuation/arrow/-cont/to-either.html create mode 100644 docs/-continuation/arrow/-cont/to-ior.html create mode 100644 docs/-continuation/arrow/-cont/to-option.html create mode 100644 docs/-continuation/arrow/-cont/to-validated.html create mode 100644 docs/-continuation/arrow/-ior-effect/-ior-effect.html create mode 100644 docs/-continuation/arrow/-ior-effect/bind.html create mode 100644 docs/-continuation/arrow/-ior-effect/index.html create mode 100644 docs/-continuation/arrow/-ior-effect/shift.html create mode 100644 docs/-continuation/arrow/-option-effect/-option-effect.html create mode 100644 docs/-continuation/arrow/-option-effect/bind.html create mode 100644 docs/-continuation/arrow/-option-effect/ensure.html create mode 100644 docs/-continuation/arrow/-option-effect/index.html create mode 100644 docs/-continuation/arrow/-option-effect/shift.html create mode 100644 docs/-continuation/arrow/-restricted-cont-effect/bind.html create mode 100644 docs/-continuation/arrow/-restricted-cont-effect/index.html create mode 100644 docs/-continuation/arrow/-restricted-cont-effect/shift.html create mode 100644 docs/-continuation/arrow/-restricted-cont/attempt.html create mode 100644 docs/-continuation/arrow/-restricted-cont/flat-map.html create mode 100644 docs/-continuation/arrow/-restricted-cont/fold.html create mode 100644 docs/-continuation/arrow/-restricted-cont/handle-error-with.html create mode 100644 docs/-continuation/arrow/-restricted-cont/handle-error.html create mode 100644 docs/-continuation/arrow/-restricted-cont/index.html create mode 100644 docs/-continuation/arrow/-restricted-cont/map.html create mode 100644 docs/-continuation/arrow/-restricted-cont/redeem-with.html create mode 100644 docs/-continuation/arrow/-restricted-cont/redeem.html create mode 100644 docs/-continuation/arrow/-restricted-cont/to-either.html create mode 100644 docs/-continuation/arrow/-restricted-cont/to-validated.html create mode 100644 docs/-continuation/arrow/-shift-cancellation-exception/index.html create mode 100644 docs/-continuation/arrow/cont.html create mode 100644 docs/-continuation/arrow/either.html create mode 100644 docs/-continuation/arrow/ensure-not-null.html create mode 100644 docs/-continuation/arrow/index.html create mode 100644 docs/-continuation/arrow/ior.html create mode 100644 docs/-continuation/arrow/option.html create mode 100644 docs/-continuation/arrow/restricted-cont.html create mode 100644 docs/-continuation/arrow/sequence.html create mode 100644 docs/-continuation/arrow/to-option.html create mode 100644 docs/-continuation/arrow/traverse-cont.html create mode 100644 docs/-continuation/package-list create mode 100644 docs/images/anchor-copy-button.svg create mode 100644 docs/images/arrow_down.svg create mode 100644 docs/images/copy-icon.svg create mode 100644 docs/images/copy-successful-icon.svg create mode 100644 docs/images/docs_logo.svg create mode 100644 docs/images/footer-go-to-link.svg create mode 100644 docs/images/go-to-top-icon.svg create mode 100644 docs/images/logo-icon.svg create mode 100644 docs/index.html create mode 100644 docs/navigation.html create mode 100644 docs/scripts/clipboard.js create mode 100644 docs/scripts/main.js create mode 100644 docs/scripts/navigation-loader.js create mode 100644 docs/scripts/navigation-pane.json create mode 100644 docs/scripts/pages.json create mode 100644 docs/scripts/platform-content-handler.js create mode 100644 docs/scripts/sourceset_dependencies.js create mode 100644 docs/styles/jetbrains-mono.css create mode 100644 docs/styles/logo-styles.css create mode 100644 docs/styles/main.css create mode 100644 docs/styles/style.css diff --git a/docs/-continuation/arrow/-cont-effect/bind.html b/docs/-continuation/arrow/-cont-effect/bind.html new file mode 100644 index 00000000000..ea811f6e6fa --- /dev/null +++ b/docs/-continuation/arrow/-cont-effect/bind.html @@ -0,0 +1,38 @@ + + + + bind + + + + + + diff --git a/docs/-continuation/arrow/-cont-effect/ensure.html b/docs/-continuation/arrow/-cont-effect/ensure.html new file mode 100644 index 00000000000..7c799a3d725 --- /dev/null +++ b/docs/-continuation/arrow/-cont-effect/ensure.html @@ -0,0 +1,49 @@ + + + + ensure + + +
+
+ + +
+
+
+
+
+
+ +
+

ensure

+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> R)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont-effect/index.html b/docs/-continuation/arrow/-cont-effect/index.html new file mode 100644 index 00000000000..20ba2f0257a --- /dev/null +++ b/docs/-continuation/arrow/-cont-effect/index.html @@ -0,0 +1,141 @@ + + + + ContEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

ContEffect

+
interface ContEffect<R>

Context of the Cont DSL.

+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> R)
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Inheritors

+
+
+
+
IorEffect +
Link copied to clipboard
+
+
+
+
+ +
+
+
OptionEffect +
Link copied to clipboard
+
+
+
+
+
+

Extensions

+
+
+
+
ensureNotNull +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont-effect/shift.html b/docs/-continuation/arrow/-cont-effect/shift.html new file mode 100644 index 00000000000..4fb153f5644 --- /dev/null +++ b/docs/-continuation/arrow/-cont-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/attempt.html b/docs/-continuation/arrow/-cont/attempt.html new file mode 100644 index 00000000000..55e2c6c32a6 --- /dev/null +++ b/docs/-continuation/arrow/-cont/attempt.html @@ -0,0 +1,49 @@ + + + + attempt + + +
+
+ + +
+
+
+
+
+
+ +
+

attempt

+
+
+ +
+
open fun attempt(): Cont<R, Result<A>>
+
+

Runs the Cont and captures any NonFatal exception into Result.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/flat-map.html b/docs/-continuation/arrow/-cont/flat-map.html new file mode 100644 index 00000000000..294f0e5bbf9 --- /dev/null +++ b/docs/-continuation/arrow/-cont/flat-map.html @@ -0,0 +1,49 @@ + + + + flatMap + + +
+
+ + +
+
+
+
+
+
+ +
+

flatMap

+
+
+ +
+
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
+
+

Maps the values A with the transform function into another Cont effect.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/fold.html b/docs/-continuation/arrow/-cont/fold.html new file mode 100644 index 00000000000..25ebbab7111 --- /dev/null +++ b/docs/-continuation/arrow/-cont/fold.html @@ -0,0 +1,44 @@ + + + + fold + + +
+
+ + +
+
+
+
+
+
+ +
+

fold

+
+
+ +
+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
.let(::println)

cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
.let(::println)
}
Hello, World!
1000
+
+ +
+
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/handle-error-with.html b/docs/-continuation/arrow/-cont/handle-error-with.html new file mode 100644 index 00000000000..f35dc87a3d7 --- /dev/null +++ b/docs/-continuation/arrow/-cont/handle-error-with.html @@ -0,0 +1,49 @@ + + + + handleErrorWith + + +
+
+ + +
+
+
+
+
+
+ +
+

handleErrorWith

+
+
+ +
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/handle-error.html b/docs/-continuation/arrow/-cont/handle-error.html new file mode 100644 index 00000000000..8fa296f3699 --- /dev/null +++ b/docs/-continuation/arrow/-cont/handle-error.html @@ -0,0 +1,49 @@ + + + + handleError + + +
+
+ + +
+
+
+
+
+
+ +
+

handleError

+
+
+ +
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/index.html b/docs/-continuation/arrow/-cont/index.html new file mode 100644 index 00000000000..da8ee04e718 --- /dev/null +++ b/docs/-continuation/arrow/-cont/index.html @@ -0,0 +1,280 @@ + + + + Cont + + +
+
+ + +
+
+
+
+
+
+ +
+

Cont

+
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

+
+
+
+
+

Functions

+
+
+
+
attempt +
Link copied to clipboard
+
+
+
+ +
+
open fun attempt(): Cont<R, Result<A>>
+
+

Runs the Cont and captures any NonFatal exception into Result.

+
+
+
+
+ +
+
+
flatMap +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
+
+

Maps the values A with the transform function into another Cont effect.

+
+
+
+
+ +
+
+
fold +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

+
+ +
+
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Like fold but also allows folding over any unexpected Throwable that might have occurred.

+
+
+
+
+ +
+
+
handleError +
Link copied to clipboard
+
+
+
+ +
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
+
+
+
+
+
+
+ +
+
+
handleErrorWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
+
+
+
+
+
+
+ +
+
+
map +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
+
+

Maps the values A with the transform function into B.

+
+
+
+
+ +
+
+
redeem +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
+
+
+
+
+
+
+ +
+
+
redeemWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
+
+
+
+
+
+
+ +
+
+
toEither +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toEither(): Either<R, A>
+
+

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+
+
+
+
+ +
+
+
toIor +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toIor(): Ior<R, A>
+
+

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+
+
+
+
+ +
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
+
+

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+
+
+
+
+ +
+
+
toValidated +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toValidated(): Validated<R, A>
+
+

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+
+
+
+
+
+

Extensions

+
+
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/map.html b/docs/-continuation/arrow/-cont/map.html new file mode 100644 index 00000000000..36a33383701 --- /dev/null +++ b/docs/-continuation/arrow/-cont/map.html @@ -0,0 +1,49 @@ + + + + map + + +
+
+ + +
+
+
+
+
+
+ +
+

map

+
+
+ +
+
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
+
+

Maps the values A with the transform function into B.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/redeem-with.html b/docs/-continuation/arrow/-cont/redeem-with.html new file mode 100644 index 00000000000..64ffbae01eb --- /dev/null +++ b/docs/-continuation/arrow/-cont/redeem-with.html @@ -0,0 +1,49 @@ + + + + redeemWith + + +
+
+ + +
+
+
+
+
+
+ +
+

redeemWith

+
+
+ +
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/redeem.html b/docs/-continuation/arrow/-cont/redeem.html new file mode 100644 index 00000000000..1d34126822e --- /dev/null +++ b/docs/-continuation/arrow/-cont/redeem.html @@ -0,0 +1,49 @@ + + + + redeem + + +
+
+ + +
+
+
+
+
+
+ +
+

redeem

+
+
+ +
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/to-either.html b/docs/-continuation/arrow/-cont/to-either.html new file mode 100644 index 00000000000..80d3f31cebd --- /dev/null +++ b/docs/-continuation/arrow/-cont/to-either.html @@ -0,0 +1,49 @@ + + + + toEither + + +
+
+ + +
+
+
+
+
+
+ +
+

toEither

+
+
+ +
+
open suspend fun toEither(): Either<R, A>
+
+

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/to-ior.html b/docs/-continuation/arrow/-cont/to-ior.html new file mode 100644 index 00000000000..9b37b90c48e --- /dev/null +++ b/docs/-continuation/arrow/-cont/to-ior.html @@ -0,0 +1,49 @@ + + + + toIor + + +
+
+ + +
+
+
+
+
+
+ +
+

toIor

+
+
+ +
+
open suspend fun toIor(): Ior<R, A>
+
+

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/to-option.html b/docs/-continuation/arrow/-cont/to-option.html new file mode 100644 index 00000000000..d083137aea2 --- /dev/null +++ b/docs/-continuation/arrow/-cont/to-option.html @@ -0,0 +1,49 @@ + + + + toOption + + +
+
+ + +
+
+
+
+
+
+ +
+

toOption

+
+
+ +
+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
+
+

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-cont/to-validated.html b/docs/-continuation/arrow/-cont/to-validated.html new file mode 100644 index 00000000000..f8c20cc77ee --- /dev/null +++ b/docs/-continuation/arrow/-cont/to-validated.html @@ -0,0 +1,49 @@ + + + + toValidated + + +
+
+ + +
+
+
+
+
+
+ +
+

toValidated

+
+
+ +
+
open suspend fun toValidated(): Validated<R, A>
+
+

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-ior-effect/-ior-effect.html b/docs/-continuation/arrow/-ior-effect/-ior-effect.html new file mode 100644 index 00000000000..bfc2746ecd1 --- /dev/null +++ b/docs/-continuation/arrow/-ior-effect/-ior-effect.html @@ -0,0 +1,49 @@ + + + + IorEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

IorEffect

+
+
+ +
+
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-ior-effect/bind.html b/docs/-continuation/arrow/-ior-effect/bind.html new file mode 100644 index 00000000000..9603c2beaf3 --- /dev/null +++ b/docs/-continuation/arrow/-ior-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
suspend fun <B> Ior<E, B>.bind(): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-ior-effect/index.html b/docs/-continuation/arrow/-ior-effect/index.html new file mode 100644 index 00000000000..3f7f5cfb294 --- /dev/null +++ b/docs/-continuation/arrow/-ior-effect/index.html @@ -0,0 +1,153 @@ + + + + IorEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

IorEffect

+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<E, B>.bind(): B
open suspend fun <B> Either<E, B>.bind(): B
open suspend fun <B> Validated<E, B>.bind(): B
suspend fun <B> Ior<E, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> E): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
+
+
+
+
+
+
+ +
+
+
combine +
Link copied to clipboard
+
+
+
+ +
+
open override fun E.combine(b: E): E
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> E)
+
+
+
+
+
+
+ +
+
+
maybeCombine +
Link copied to clipboard
+
+
+
+ +
+
open override fun E.maybeCombine(b: E?): E
+
+
+
+
+
+
+ +
+
+
plus +
Link copied to clipboard
+
+
+
+ +
+
open operator override fun E.plus(b: E): E
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
open suspend override fun <B> shift(r: E): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-ior-effect/shift.html b/docs/-continuation/arrow/-ior-effect/shift.html new file mode 100644 index 00000000000..cdda291eb20 --- /dev/null +++ b/docs/-continuation/arrow/-ior-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
open suspend override fun <B> shift(r: E): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-option-effect/-option-effect.html b/docs/-continuation/arrow/-option-effect/-option-effect.html new file mode 100644 index 00000000000..79ae4e9ad3f --- /dev/null +++ b/docs/-continuation/arrow/-option-effect/-option-effect.html @@ -0,0 +1,49 @@ + + + + OptionEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

OptionEffect

+
+
+ +
+
fun OptionEffect(cont: ContEffect<None>)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-option-effect/bind.html b/docs/-continuation/arrow/-option-effect/bind.html new file mode 100644 index 00000000000..65c50d497ef --- /dev/null +++ b/docs/-continuation/arrow/-option-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
suspend fun <B> Option<B>.bind(): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-option-effect/ensure.html b/docs/-continuation/arrow/-option-effect/ensure.html new file mode 100644 index 00000000000..1473fbd564f --- /dev/null +++ b/docs/-continuation/arrow/-option-effect/ensure.html @@ -0,0 +1,49 @@ + + + + ensure + + +
+
+ + +
+
+
+
+
+
+ +
+

ensure

+
+
+ +
+
suspend fun ensure(value: Boolean)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-option-effect/index.html b/docs/-continuation/arrow/-option-effect/index.html new file mode 100644 index 00000000000..c9720cec4df --- /dev/null +++ b/docs/-continuation/arrow/-option-effect/index.html @@ -0,0 +1,102 @@ + + + + OptionEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

OptionEffect

+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<None, B>.bind(): B
open suspend fun <B> Either<None, B>.bind(): B
open suspend fun <B> Validated<None, B>.bind(): B
suspend fun <B> Option<B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> None): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
suspend fun ensure(value: Boolean)
open suspend fun ensure(value: Boolean, shift: () -> None)
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
open suspend override fun <B> shift(r: None): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-option-effect/shift.html b/docs/-continuation/arrow/-option-effect/shift.html new file mode 100644 index 00000000000..543ebed5eae --- /dev/null +++ b/docs/-continuation/arrow/-option-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
open suspend override fun <B> shift(r: None): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont-effect/bind.html b/docs/-continuation/arrow/-restricted-cont-effect/bind.html new file mode 100644 index 00000000000..4a237f713fa --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont-effect/index.html b/docs/-continuation/arrow/-restricted-cont-effect/index.html new file mode 100644 index 00000000000..7393b400496 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont-effect/index.html @@ -0,0 +1,85 @@ + + + + RestrictedContEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

RestrictedContEffect

+
interface RestrictedContEffect<R>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont-effect/shift.html b/docs/-continuation/arrow/-restricted-cont-effect/shift.html new file mode 100644 index 00000000000..9a7de49fe40 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/attempt.html b/docs/-continuation/arrow/-restricted-cont/attempt.html new file mode 100644 index 00000000000..c256d0f28f5 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/attempt.html @@ -0,0 +1,49 @@ + + + + attempt + + +
+
+ + +
+
+
+
+
+
+ +
+

attempt

+
+
+ +
+
open fun attempt(): RestrictedCont<R, Result<A>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/flat-map.html b/docs/-continuation/arrow/-restricted-cont/flat-map.html new file mode 100644 index 00000000000..88d5c49771d --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/flat-map.html @@ -0,0 +1,49 @@ + + + + flatMap + + +
+
+ + +
+
+
+
+
+
+ +
+

flatMap

+
+
+ +
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/fold.html b/docs/-continuation/arrow/-restricted-cont/fold.html new file mode 100644 index 00000000000..68d2d16569a --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/fold.html @@ -0,0 +1,49 @@ + + + + fold + + +
+
+ + +
+
+
+
+
+
+ +
+

fold

+
+
+ +
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/handle-error-with.html b/docs/-continuation/arrow/-restricted-cont/handle-error-with.html new file mode 100644 index 00000000000..5051a0306e7 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/handle-error-with.html @@ -0,0 +1,49 @@ + + + + handleErrorWith + + +
+
+ + +
+
+
+
+
+
+ +
+

handleErrorWith

+
+
+ +
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/handle-error.html b/docs/-continuation/arrow/-restricted-cont/handle-error.html new file mode 100644 index 00000000000..e88b7bf681f --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/handle-error.html @@ -0,0 +1,49 @@ + + + + handleError + + +
+
+ + +
+
+
+
+
+
+ +
+

handleError

+
+
+ +
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/index.html b/docs/-continuation/arrow/-restricted-cont/index.html new file mode 100644 index 00000000000..dd86932c806 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/index.html @@ -0,0 +1,221 @@ + + + + RestrictedCont + + +
+
+ + +
+
+
+
+
+
+ +
+

RestrictedCont

+
interface RestrictedCont<R, A>
+
+
+
+
+

Functions

+
+
+
+
attempt +
Link copied to clipboard
+
+
+
+ +
+
open fun attempt(): RestrictedCont<R, Result<A>>
+
+
+
+
+
+
+ +
+
+
flatMap +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
+
+
+
+
+
+
+ +
+
+
fold +
Link copied to clipboard
+
+
+
+ +
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
+
+
+
+
+
+
+ +
+
+
handleError +
Link copied to clipboard
+
+
+
+ +
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
+
+
+
+
+
+
+ +
+
+
handleErrorWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
+
+
+
+
+
+
+ +
+
+
map +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
+
+
+
+
+
+
+ +
+
+
redeem +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
+
+
+
+
+
+
+ +
+
+
redeemWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
+
+
+
+
+
+
+ +
+
+
toEither +
Link copied to clipboard
+
+
+
+ +
+
open fun toEither(): Either<R, A>
+
+
+
+
+
+
+ +
+
+
toValidated +
Link copied to clipboard
+
+
+
+ +
+
open fun toValidated(): Validated<R, A>
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/map.html b/docs/-continuation/arrow/-restricted-cont/map.html new file mode 100644 index 00000000000..724eb070771 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/map.html @@ -0,0 +1,49 @@ + + + + map + + +
+
+ + +
+
+
+
+
+
+ +
+

map

+
+
+ +
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/redeem-with.html b/docs/-continuation/arrow/-restricted-cont/redeem-with.html new file mode 100644 index 00000000000..fb364445780 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/redeem-with.html @@ -0,0 +1,49 @@ + + + + redeemWith + + +
+
+ + +
+
+
+
+
+
+ +
+

redeemWith

+
+
+ +
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/redeem.html b/docs/-continuation/arrow/-restricted-cont/redeem.html new file mode 100644 index 00000000000..46490f72c51 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/redeem.html @@ -0,0 +1,49 @@ + + + + redeem + + +
+
+ + +
+
+
+
+
+
+ +
+

redeem

+
+
+ +
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/to-either.html b/docs/-continuation/arrow/-restricted-cont/to-either.html new file mode 100644 index 00000000000..3e2ec14d5f9 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/to-either.html @@ -0,0 +1,49 @@ + + + + toEither + + +
+
+ + +
+
+
+
+
+
+ +
+

toEither

+
+
+ +
+
open fun toEither(): Either<R, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-restricted-cont/to-validated.html b/docs/-continuation/arrow/-restricted-cont/to-validated.html new file mode 100644 index 00000000000..728384f62d4 --- /dev/null +++ b/docs/-continuation/arrow/-restricted-cont/to-validated.html @@ -0,0 +1,49 @@ + + + + toValidated + + +
+
+ + +
+
+
+
+
+
+ +
+

toValidated

+
+
+ +
+
open fun toValidated(): Validated<R, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/-shift-cancellation-exception/index.html b/docs/-continuation/arrow/-shift-cancellation-exception/index.html new file mode 100644 index 00000000000..fd74753fbec --- /dev/null +++ b/docs/-continuation/arrow/-shift-cancellation-exception/index.html @@ -0,0 +1,77 @@ + + + + ShiftCancellationException + + +
+
+ + +
+
+
+
+
+
+ +
+

ShiftCancellationException

+
sealed class ShiftCancellationException : CancellationException
+
+
+
+
+

Properties

+
+
+
+
cause +
Link copied to clipboard
+
+
+
+
open val cause: Throwable?
+
+
+
+
+ +
+
+
message +
Link copied to clipboard
+
+
+
+
open val message: String?
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/cont.html b/docs/-continuation/arrow/cont.html new file mode 100644 index 00000000000..2e33fb68104 --- /dev/null +++ b/docs/-continuation/arrow/cont.html @@ -0,0 +1,49 @@ + + + + cont + + +
+
+ + +
+
+
+
+
+
+ +
+

cont

+
+
+ +
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
+
+

DSL for constructing Cont values

import arrow.core.*
import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)
}
6
Option was empty
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/either.html b/docs/-continuation/arrow/either.html new file mode 100644 index 00000000000..f2201c282b8 --- /dev/null +++ b/docs/-continuation/arrow/either.html @@ -0,0 +1,49 @@ + + + + either + + +
+
+ + +
+
+
+
+
+
+ +
+

either

+
+
+ +
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/ensure-not-null.html b/docs/-continuation/arrow/ensure-not-null.html new file mode 100644 index 00000000000..8ea4e5d042e --- /dev/null +++ b/docs/-continuation/arrow/ensure-not-null.html @@ -0,0 +1,38 @@ + + + + ensureNotNull + + +
+
+ + +
+
+
+
+
+
+ +
+

ensureNotNull

+
+
+ +
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/index.html b/docs/-continuation/arrow/index.html new file mode 100644 index 00000000000..3f0f0ffbf28 --- /dev/null +++ b/docs/-continuation/arrow/index.html @@ -0,0 +1,313 @@ + + + + arrow + + +
+
+ + +
+
+
+
+
+
+ +
+

Package arrow

+
+
+
+
+

Types

+
+
+
+
Cont +
Link copied to clipboard
+
+
+
+ +
+
interface Cont<R, A>
+
+

Cont represents a suspending computation that runs will either

+
+
+
+
+ +
+
+
ContEffect +
Link copied to clipboard
+
+
+
+ +
+
interface ContEffect<R>
+
+

Context of the Cont DSL.

+
+
+
+
+ +
+
+
IorEffect +
Link copied to clipboard
+
+
+
+ +
+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
+
+
+
+
+
+ +
+
+
OptionEffect +
Link copied to clipboard
+
+
+
+ +
+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
+
+
+
+
+
+ +
+
+
RestrictedCont +
Link copied to clipboard
+
+
+
+ +
+
interface RestrictedCont<R, A>
+
+
+
+
+
+
+ +
+
+
RestrictedContEffect +
Link copied to clipboard
+
+
+
+ +
+
interface RestrictedContEffect<R>
+
+
+
+
+
+
+ +
+
+
ShiftCancellationException +
Link copied to clipboard
+
+
+
+ +
+
sealed class ShiftCancellationException : CancellationException
+
+
+
+
+
+
+
+

Functions

+
+
+
+
cont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
+
+

DSL for constructing Cont values

+
+
+
+
+ +
+
+
either +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
+
+
+
+
+
+
+ +
+
+
ensureNotNull +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
+
+
+
+
+
+ +
+
+
ior +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
+
+
+
+
+
+
+ +
+
+
option +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
+
+
+
+
+
+
+ +
+
+
restrictedCont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
+
+

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+
+
+
+
+ +
+
+
sequence +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
+
+
+
+
+
+
+ +
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+
+
+
+
+ +
+
+
traverseCont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
+
+
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/ior.html b/docs/-continuation/arrow/ior.html new file mode 100644 index 00000000000..fff8760bce5 --- /dev/null +++ b/docs/-continuation/arrow/ior.html @@ -0,0 +1,49 @@ + + + + ior + + +
+
+ + +
+
+
+
+
+
+ +
+

ior

+
+
+ +
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/option.html b/docs/-continuation/arrow/option.html new file mode 100644 index 00000000000..91e56e8f851 --- /dev/null +++ b/docs/-continuation/arrow/option.html @@ -0,0 +1,49 @@ + + + + option + + +
+
+ + +
+
+
+
+
+
+ +
+

option

+
+
+ +
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/restricted-cont.html b/docs/-continuation/arrow/restricted-cont.html new file mode 100644 index 00000000000..7586bc9d1a0 --- /dev/null +++ b/docs/-continuation/arrow/restricted-cont.html @@ -0,0 +1,49 @@ + + + + restrictedCont + + +
+
+ + +
+
+
+
+
+
+ +
+

restrictedCont

+
+
+ +
+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
+
+

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/sequence.html b/docs/-continuation/arrow/sequence.html new file mode 100644 index 00000000000..d0777547d7a --- /dev/null +++ b/docs/-continuation/arrow/sequence.html @@ -0,0 +1,49 @@ + + + + sequence + + +
+
+ + +
+
+
+
+
+
+ +
+

sequence

+
+
+ +
+
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/to-option.html b/docs/-continuation/arrow/to-option.html new file mode 100644 index 00000000000..76026ba991b --- /dev/null +++ b/docs/-continuation/arrow/to-option.html @@ -0,0 +1,49 @@ + + + + toOption + + +
+
+ + +
+
+
+
+
+
+ +
+

toOption

+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/arrow/traverse-cont.html b/docs/-continuation/arrow/traverse-cont.html new file mode 100644 index 00000000000..9a5a51c21d7 --- /dev/null +++ b/docs/-continuation/arrow/traverse-cont.html @@ -0,0 +1,49 @@ + + + + traverseCont + + +
+
+ + +
+
+
+
+
+
+ +
+

traverseCont

+
+
+ +
+
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-continuation/package-list b/docs/-continuation/package-list new file mode 100644 index 00000000000..ce9d3bcdcd8 --- /dev/null +++ b/docs/-continuation/package-list @@ -0,0 +1,61 @@ +$dokka.format:html-v1 +$dokka.linkExtension:html +$dokka.location:arrow////PointingToDeclaration/-continuation/arrow/index.html +$dokka.location:arrow//cont/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/cont.html +$dokka.location:arrow//either/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/either.html +$dokka.location:arrow//ensureNotNull/arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]#TypeParam(bounds=[kotlin.Any])?#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/ensure-not-null.html +$dokka.location:arrow//ensureNotNull/arrow.ContEffect[arrow.core.None]#TypeParam(bounds=[kotlin.Any])?/PointingToDeclaration/-continuation/arrow/ensure-not-null.html +$dokka.location:arrow//ior/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[arrow.IorEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/ior.html +$dokka.location:arrow//option/#kotlin.Function1[arrow.OptionEffect,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/option.html +$dokka.location:arrow//restrictedCont/#kotlin.coroutines.SuspendFunction1[arrow.RestrictedContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/restricted-cont.html +$dokka.location:arrow//sequence/kotlin.collections.Iterable[arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#/PointingToDeclaration/-continuation/arrow/sequence.html +$dokka.location:arrow//toOption/arrow.Cont[arrow.core.None,TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/to-option.html +$dokka.location:arrow//traverseCont/kotlin.collections.Iterable[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/traverse-cont.html +$dokka.location:arrow/Cont///PointingToDeclaration/-continuation/arrow/-cont/index.html +$dokka.location:arrow/Cont/attempt/#/PointingToDeclaration/-continuation/arrow/-cont/attempt.html +$dokka.location:arrow/Cont/flatMap/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/flat-map.html +$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/fold.html +$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/fold.html +$dokka.location:arrow/Cont/handleError/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/handle-error.html +$dokka.location:arrow/Cont/handleErrorWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/handle-error-with.html +$dokka.location:arrow/Cont/map/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/map.html +$dokka.location:arrow/Cont/redeem/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/redeem.html +$dokka.location:arrow/Cont/redeemWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/redeem-with.html +$dokka.location:arrow/Cont/toEither/#/PointingToDeclaration/-continuation/arrow/-cont/to-either.html +$dokka.location:arrow/Cont/toIor/#/PointingToDeclaration/-continuation/arrow/-cont/to-ior.html +$dokka.location:arrow/Cont/toOption/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/to-option.html +$dokka.location:arrow/Cont/toValidated/#/PointingToDeclaration/-continuation/arrow/-cont/to-validated.html +$dokka.location:arrow/ContEffect///PointingToDeclaration/-continuation/arrow/-cont-effect/index.html +$dokka.location:arrow/ContEffect/bind/arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Either[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Validated[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/kotlin.Result[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/ensure/#kotlin.Boolean#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/ensure.html +$dokka.location:arrow/ContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-cont-effect/shift.html +$dokka.location:arrow/IorEffect///PointingToDeclaration/-continuation/arrow/-ior-effect/index.html +$dokka.location:arrow/IorEffect/IorEffect/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-ior-effect/-ior-effect.html +$dokka.location:arrow/IorEffect/bind/arrow.core.Ior[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-ior-effect/bind.html +$dokka.location:arrow/IorEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-ior-effect/shift.html +$dokka.location:arrow/OptionEffect///PointingToDeclaration/-continuation/arrow/-option-effect/index.html +$dokka.location:arrow/OptionEffect/OptionEffect/#arrow.ContEffect[arrow.core.None]/PointingToDeclaration/-continuation/arrow/-option-effect/-option-effect.html +$dokka.location:arrow/OptionEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-option-effect/bind.html +$dokka.location:arrow/OptionEffect/ensure/#kotlin.Boolean/PointingToDeclaration/-continuation/arrow/-option-effect/ensure.html +$dokka.location:arrow/OptionEffect/shift/#arrow.core.None/PointingToDeclaration/-continuation/arrow/-option-effect/shift.html +$dokka.location:arrow/RestrictedCont///PointingToDeclaration/-continuation/arrow/-restricted-cont/index.html +$dokka.location:arrow/RestrictedCont/attempt/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/attempt.html +$dokka.location:arrow/RestrictedCont/flatMap/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/flat-map.html +$dokka.location:arrow/RestrictedCont/fold/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/fold.html +$dokka.location:arrow/RestrictedCont/handleError/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/handle-error.html +$dokka.location:arrow/RestrictedCont/handleErrorWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/handle-error-with.html +$dokka.location:arrow/RestrictedCont/map/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/map.html +$dokka.location:arrow/RestrictedCont/redeem/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/redeem.html +$dokka.location:arrow/RestrictedCont/redeemWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/redeem-with.html +$dokka.location:arrow/RestrictedCont/toEither/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/to-either.html +$dokka.location:arrow/RestrictedCont/toValidated/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/to-validated.html +$dokka.location:arrow/RestrictedContEffect///PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/index.html +$dokka.location:arrow/RestrictedContEffect/bind/arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/bind.html +$dokka.location:arrow/RestrictedContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/shift.html +$dokka.location:arrow/ShiftCancellationException///PointingToDeclaration/-continuation/arrow/-shift-cancellation-exception/index.html +arrow + diff --git a/docs/images/anchor-copy-button.svg b/docs/images/anchor-copy-button.svg new file mode 100644 index 00000000000..bab9d747ff4 --- /dev/null +++ b/docs/images/anchor-copy-button.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/images/arrow_down.svg b/docs/images/arrow_down.svg new file mode 100644 index 00000000000..89e7df4710b --- /dev/null +++ b/docs/images/arrow_down.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/images/copy-icon.svg b/docs/images/copy-icon.svg new file mode 100644 index 00000000000..61440f0a40a --- /dev/null +++ b/docs/images/copy-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/images/copy-successful-icon.svg b/docs/images/copy-successful-icon.svg new file mode 100644 index 00000000000..1865f739b09 --- /dev/null +++ b/docs/images/copy-successful-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/images/docs_logo.svg b/docs/images/docs_logo.svg new file mode 100644 index 00000000000..7c1e3ae8ea4 --- /dev/null +++ b/docs/images/docs_logo.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/docs/images/footer-go-to-link.svg b/docs/images/footer-go-to-link.svg new file mode 100644 index 00000000000..0137e22313f --- /dev/null +++ b/docs/images/footer-go-to-link.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/docs/images/go-to-top-icon.svg b/docs/images/go-to-top-icon.svg new file mode 100644 index 00000000000..d987f3eadcf --- /dev/null +++ b/docs/images/go-to-top-icon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/images/logo-icon.svg b/docs/images/logo-icon.svg new file mode 100644 index 00000000000..1b3b3670e0d --- /dev/null +++ b/docs/images/logo-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000000..5474bc43139 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,46 @@ + + + + Continuation + + +
+
+ + +
+
+
+
+
+
+ +
+

Continuation

+
+

Packages

+
+
+
+
+
arrow +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/navigation.html b/docs/navigation.html new file mode 100644 index 00000000000..aaad0d5ee9e --- /dev/null +++ b/docs/navigation.html @@ -0,0 +1,55 @@ + + diff --git a/docs/scripts/clipboard.js b/docs/scripts/clipboard.js new file mode 100644 index 00000000000..b00ce246ef3 --- /dev/null +++ b/docs/scripts/clipboard.js @@ -0,0 +1,52 @@ +window.addEventListener('load', () => { + document.querySelectorAll('span.copy-icon').forEach(element => { + element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); + }) + + document.querySelectorAll('span.anchor-icon').forEach(element => { + element.addEventListener('click', (el) => { + if(element.hasAttribute('pointing-to')){ + const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') + copyTextToClipboard(element, location) + } + }); + }) +}) + +const copyElementsContentToClipboard = (element) => { + const selection = window.getSelection(); + const range = document.createRange(); + range.selectNodeContents(element.parentNode.parentNode); + selection.removeAllRanges(); + selection.addRange(range); + + copyAndShowPopup(element, () => selection.removeAllRanges()) +} + +const copyTextToClipboard = (element, text) => { + var textarea = document.createElement("textarea"); + textarea.textContent = text; + textarea.style.position = "fixed"; + document.body.appendChild(textarea); + textarea.select(); + + copyAndShowPopup(element, () => document.body.removeChild(textarea)) +} + +const copyAndShowPopup = (element, after) => { + try { + document.execCommand('copy'); + element.nextElementSibling.classList.add('active-popup'); + setTimeout(() => { + element.nextElementSibling.classList.remove('active-popup'); + }, 1200); + } catch (e) { + console.error('Failed to write to clipboard:', e) + } + finally { + if(after) after() + } +} + +const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] + diff --git a/docs/scripts/main.js b/docs/scripts/main.js new file mode 100644 index 00000000000..b9637fa31ba --- /dev/null +++ b/docs/scripts/main.js @@ -0,0 +1,67 @@ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=390)}([function(e,t,n){e.exports=n(264)()},function(e,t,n){"use strict";e.exports=n(239)},function(e,t,n){var r; +/*! + Copyright (c) 2017 Jed Watson. + Licensed under the MIT License (MIT), see + http://jedwatson.github.io/classnames +*/!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;to;)Q(e,n=r[o++],t[n]);return e},X=function(e){var t=F.call(this,e=x(e,!0));return!(this===W&&o(H,e)&&!o(U,e))&&(!(t||!o(this,e)||!o(H,e)||o(this,A)&&this[A][e])||t)},J=function(e,t){if(e=w(e),t=x(t,!0),e!==W||!o(H,t)||o(U,t)){var n=I(e,t);return!n||!o(H,t)||o(e,A)&&e[A][t]||(n.enumerable=!0),n}},Z=function(e){for(var t,n=z(w(e)),r=[],i=0;n.length>i;)o(H,t=n[i++])||t==A||t==c||r.push(t);return r},ee=function(e){for(var t,n=e===W,r=z(n?U:w(e)),i=[],a=0;r.length>a;)!o(H,t=r[a++])||n&&!o(W,t)||i.push(H[t]);return i};B||(l((R=function(){if(this instanceof R)throw TypeError("Symbol is not a constructor!");var e=p(arguments.length>0?arguments[0]:void 0),t=function(n){this===W&&t.call(U,n),o(this,A)&&o(this[A],e)&&(this[A][e]=!1),K(this,e,S(1,n))};return i&&G&&K(W,e,{configurable:!0,set:t}),q(e)}).prototype,"toString",(function(){return this._k})),E.f=J,C.f=Q,n(114).f=O.f=Z,n(95).f=X,T.f=ee,i&&!n(111)&&l(W,"propertyIsEnumerable",X,!0),h.f=function(e){return q(d(e))}),a(a.G+a.W+a.F*!B,{Symbol:R});for(var te="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),ne=0;te.length>ne;)d(te[ne++]);for(var re=P(d.store),oe=0;re.length>oe;)v(re[oe++]);a(a.S+a.F*!B,"Symbol",{for:function(e){return o(D,e+="")?D[e]:D[e]=R(e)},keyFor:function(e){if(!$(e))throw TypeError(e+" is not a symbol!");for(var t in D)if(D[t]===e)return t},useSetter:function(){G=!0},useSimple:function(){G=!1}}),a(a.S+a.F*!B,"Object",{create:function(e,t){return void 0===t?k(e):Y(k(e),t)},defineProperty:Q,defineProperties:Y,getOwnPropertyDescriptor:J,getOwnPropertyNames:Z,getOwnPropertySymbols:ee});var ie=u((function(){T.f(1)}));a(a.S+a.F*ie,"Object",{getOwnPropertySymbols:function(e){return T.f(_(e))}}),M&&a(a.S+a.F*(!B||u((function(){var e=R();return"[null]"!=N([e])||"{}"!=N({a:e})||"{}"!=N(Object(e))}))),"JSON",{stringify:function(e){for(var t,n,r=[e],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=t=r[1],(b(t)||void 0!==e)&&!$(e))return m(t)||(t=function(e,t){if("function"==typeof n&&(t=n.call(this,e,t)),!$(t))return t}),r[1]=t,N.apply(M,r)}}),R.prototype[L]||n(59)(R.prototype,L,R.prototype.valueOf),f(R,"Symbol"),f(Math,"Math",!0),f(r.JSON,"JSON",!0)},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperty:n(39).f})},function(e,t,n){"use strict";n(257);var r=n(27),o=n(135),i=n(30),a=/./.toString,l=function(e){n(42)(RegExp.prototype,"toString",e,!0)};n(31)((function(){return"/a/b"!=a.call({source:"a",flags:"b"})}))?l((function(){var e=r(this);return"/".concat(e.source,"/","flags"in e?e.flags:!i&&e instanceof RegExp?o.call(e):void 0)})):"toString"!=a.name&&l((function(){return a.call(this)}))},function(e,t,n){var r=Date.prototype,o=r.toString,i=r.getTime;new Date(NaN)+""!="Invalid Date"&&n(42)(r,"toString",(function(){var e=i.call(this);return e==e?o.call(this):"Invalid Date"}))},function(e,t,n){n(182)("asyncIterator")},function(e,t,n){var r=n(32),o=n(79),i=n(59),a=n(42),l=n(80),c=function(e,t,n){var u,s,f,p,d=e&c.F,h=e&c.G,v=e&c.S,g=e&c.P,m=e&c.B,y=h?r:v?r[t]||(r[t]={}):(r[t]||{}).prototype,b=h?o:o[t]||(o[t]={}),_=b.prototype||(b.prototype={});for(u in h&&(n=t),n)f=((s=!d&&y&&void 0!==y[u])?y:n)[u],p=m&&s?l(f,r):g&&"function"==typeof f?l(Function.call,f):f,y&&a(y,u,f,e&c.U),b[u]!=f&&i(b,u,p),g&&_[u]!=f&&(_[u]=f)};r.core=o,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){for(var r=n(12),o=n(69),i=n(42),a=n(32),l=n(59),c=n(96),u=n(25),s=u("iterator"),f=u("toStringTag"),p=c.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=o(d),v=0;v=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])}),"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(e,t,n){var r=n(10);r(r.S,"Object",{create:n(83)})},function(e,t,n){var r=n(10),o=n(83),i=n(81),a=n(27),l=n(29),c=n(31),u=n(184),s=(n(32).Reflect||{}).construct,f=c((function(){function e(){}return!(s((function(){}),[],e)instanceof e)})),p=!c((function(){s((function(){}))}));r(r.S+r.F*(f||p),"Reflect",{construct:function(e,t){i(e),a(t);var n=arguments.length<3?e:i(arguments[2]);if(p&&!f)return s(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var r=[null];return r.push.apply(r,t),new(u.apply(e,r))}var c=n.prototype,d=o(l(c)?c:Object.prototype),h=Function.apply.call(e,d,t);return l(h)?h:d}})},function(e,t,n){var r=n(10);r(r.S,"Object",{setPrototypeOf:n(180).set})},function(e,t,n){var r=n(54),o=n(69);n(252)("keys",(function(){return function(e){return o(r(e))}}))},function(e,t,n){"use strict";var r=n(10),o=n(130)(!1),i=[].indexOf,a=!!i&&1/[1].indexOf(1,-0)<0;r(r.P+r.F*(a||!n(71)(i)),"Array",{indexOf:function(e){return a?i.apply(this,arguments)||0:o(this,e,arguments[1])}})},function(e,t,n){var r=n(26),o=n(266);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(10);r(r.S+r.F,"Object",{assign:n(185)})},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,l=btoa(unescape(encodeURIComponent(JSON.stringify(a)))),c="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(l),"/*# ".concat(c," */")),i=r.sources.map((function(e){return"/*# sourceURL=".concat(r.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([o]).join("\n")}var a,l,c;return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(r)for(var i=0;i=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})}))},function(e,t,n){var r=n(35),o=n(28),i=n(98),a=n(73),l=n(74),c=function(e,t,n){var u,s,f,p=e&c.F,d=e&c.G,h=e&c.S,v=e&c.P,g=e&c.B,m=e&c.W,y=d?o:o[t]||(o[t]={}),b=y.prototype,_=d?r:h?r[t]:(r[t]||{}).prototype;for(u in d&&(n=t),n)(s=!p&&_&&void 0!==_[u])&&l(y,u)||(f=s?_[u]:n[u],y[u]=d&&"function"!=typeof _[u]?n[u]:g&&s?i(f,r):m&&_[u]==f?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(f):v&&"function"==typeof f?i(Function.call,f):f,v&&((y.virtual||(y.virtual={}))[u]=f,e&c.R&&b&&!b[u]&&a(b,u,f)))};c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){var r=n(26),o=n(332);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(113),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(70);e.exports=function(e){return Object(r(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(1);r(r.P+r.F*!n(71)([].map,!0),"Array",{map:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(64);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){e.exports=!n(85)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";var r=n(80),o=n(10),i=n(54),a=n(189),l=n(190),c=n(53),u=n(174),s=n(191);o(o.S+o.F*!n(192)((function(e){Array.from(e)})),"Array",{from:function(e){var t,n,o,f,p=i(e),d="function"==typeof this?this:Array,h=arguments.length,v=h>1?arguments[1]:void 0,g=void 0!==v,m=0,y=s(p);if(g&&(v=r(v,h>2?arguments[2]:void 0,2)),null==y||d==Array&&l(y))for(n=new d(t=c(p.length));t>m;m++)u(n,m,g?v(p[m],m):p[m]);else for(f=y.call(p),n=new d;!(o=f.next()).done;m++)u(n,m,g?a(f,v,[o.value,m],!0):o.value);return n.length=m,n}})},function(e,t,n){var r=n(39),o=n(91);e.exports=n(30)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(112),o=n(70);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(0),i=n(71)([].forEach,!0);r(r.P+r.F*!i,"Array",{forEach:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(80),o=n(112),i=n(54),a=n(53),l=n(259);e.exports=function(e,t){var n=1==e,c=2==e,u=3==e,s=4==e,f=6==e,p=5==e||f,d=t||l;return function(t,l,h){for(var v,g,m=i(t),y=o(m),b=r(l,h,3),_=a(y.length),w=0,x=n?d(t,_):c?d(t,0):void 0;_>w;w++)if((p||w in y)&&(g=b(v=y[w],w,m),e))if(n)x[w]=g;else if(g)switch(e){case 3:return!0;case 5:return v;case 6:return w;case 2:x.push(v)}else if(s)return!1;return f?-1:u||s?s:x}}},function(e,t,n){var r=n(56),o=n(200),i=n(147),a=Object.defineProperty;t.f=n(57)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){e.exports={default:n(282),__esModule:!0}},function(e,t,n){"use strict";t.__esModule=!0;var r=a(n(304)),o=a(n(308)),i=a(n(205));function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+(void 0===t?"undefined":(0,i.default)(t)));e.prototype=(0,o.default)(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(r.default?(0,r.default)(e,t):e.__proto__=t)}},function(e,t,n){var r=n(26),o=n(335);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(26),o=n(376);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(173),o=n(132);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){"use strict";var r=n(31);e.exports=function(e,t){return!!e&&r((function(){t?e.call(null,(function(){}),1):e.call(null)}))}},function(e,t,n){"use strict";var r=n(27),o=n(54),i=n(53),a=n(113),l=n(138),c=n(139),u=Math.max,s=Math.min,f=Math.floor,p=/\$([$&`']|\d\d?|<[^>]*>)/g,d=/\$([$&`']|\d\d?)/g;n(140)("replace",2,(function(e,t,n,h){return[function(r,o){var i=e(this),a=null==r?void 0:r[t];return void 0!==a?a.call(r,i,o):n.call(String(i),r,o)},function(e,t){var o=h(n,e,this,t);if(o.done)return o.value;var f=r(e),p=String(this),d="function"==typeof t;d||(t=String(t));var g=f.global;if(g){var m=f.unicode;f.lastIndex=0}for(var y=[];;){var b=c(f,p);if(null===b)break;if(y.push(b),!g)break;""===String(b[0])&&(f.lastIndex=l(p,i(f.lastIndex),m))}for(var _,w="",x=0,S=0;S=x&&(w+=p.slice(x,O)+I,x=O+k.length)}return w+p.slice(x)}];function v(e,t,r,i,a,l){var c=r+e.length,u=i.length,s=d;return void 0!==a&&(a=o(a),s=p),n.call(l,s,(function(n,o){var l;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,r);case"'":return t.slice(c);case"<":l=a[o.slice(1,-1)];break;default:var s=+o;if(0===s)return n;if(s>u){var p=f(s/10);return 0===p?n:p<=u?void 0===i[p-1]?o.charAt(1):i[p-1]+o.charAt(1):n}l=i[s-1]}return void 0===l?"":l}))}}))},function(e,t,n){var r=n(63),o=n(121);e.exports=n(57)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(202),o=n(148);e.exports=function(e){return r(o(e))}},function(e,t,n){(function(e,r){var o; +/** + * @license + * Lodash + * Copyright OpenJS Foundation and other contributors + * Released under MIT license + * Based on Underscore.js 1.8.3 + * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors + */(function(){var i="Expected a function",a="__lodash_placeholder__",l=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],c="[object Arguments]",u="[object Array]",s="[object Boolean]",f="[object Date]",p="[object Error]",d="[object Function]",h="[object GeneratorFunction]",v="[object Map]",g="[object Number]",m="[object Object]",y="[object RegExp]",b="[object Set]",_="[object String]",w="[object Symbol]",x="[object WeakMap]",S="[object ArrayBuffer]",k="[object DataView]",O="[object Float32Array]",E="[object Float64Array]",T="[object Int8Array]",C="[object Int16Array]",P="[object Int32Array]",I="[object Uint8Array]",j="[object Uint16Array]",z="[object Uint32Array]",R=/\b__p \+= '';/g,M=/\b(__p \+=) '' \+/g,N=/(__e\(.*?\)|\b__t\)) \+\n'';/g,A=/&(?:amp|lt|gt|quot|#39);/g,L=/[&<>"']/g,F=RegExp(A.source),D=RegExp(L.source),H=/<%-([\s\S]+?)%>/g,U=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,B=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,V=/^\w*$/,G=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,K=/[\\^$.*+?()[\]{}|]/g,q=RegExp(K.source),$=/^\s+|\s+$/g,Q=/^\s+/,Y=/\s+$/,X=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,J=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,ee=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,te=/\\(\\)?/g,ne=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,re=/\w*$/,oe=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,ae=/^\[object .+?Constructor\]$/,le=/^0o[0-7]+$/i,ce=/^(?:0|[1-9]\d*)$/,ue=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,se=/($^)/,fe=/['\n\r\u2028\u2029\\]/g,pe="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",de="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",he="[\\ud800-\\udfff]",ve="["+de+"]",ge="["+pe+"]",me="\\d+",ye="[\\u2700-\\u27bf]",be="[a-z\\xdf-\\xf6\\xf8-\\xff]",_e="[^\\ud800-\\udfff"+de+me+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",we="\\ud83c[\\udffb-\\udfff]",xe="[^\\ud800-\\udfff]",Se="(?:\\ud83c[\\udde6-\\uddff]){2}",ke="[\\ud800-\\udbff][\\udc00-\\udfff]",Oe="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ee="(?:"+be+"|"+_e+")",Te="(?:"+Oe+"|"+_e+")",Ce="(?:"+ge+"|"+we+")"+"?",Pe="[\\ufe0e\\ufe0f]?"+Ce+("(?:\\u200d(?:"+[xe,Se,ke].join("|")+")[\\ufe0e\\ufe0f]?"+Ce+")*"),Ie="(?:"+[ye,Se,ke].join("|")+")"+Pe,je="(?:"+[xe+ge+"?",ge,Se,ke,he].join("|")+")",ze=RegExp("['’]","g"),Re=RegExp(ge,"g"),Me=RegExp(we+"(?="+we+")|"+je+Pe,"g"),Ne=RegExp([Oe+"?"+be+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[ve,Oe,"$"].join("|")+")",Te+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[ve,Oe+Ee,"$"].join("|")+")",Oe+"?"+Ee+"+(?:['’](?:d|ll|m|re|s|t|ve))?",Oe+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",me,Ie].join("|"),"g"),Ae=RegExp("[\\u200d\\ud800-\\udfff"+pe+"\\ufe0e\\ufe0f]"),Le=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Fe=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],De=-1,He={};He[O]=He[E]=He[T]=He[C]=He[P]=He[I]=He["[object Uint8ClampedArray]"]=He[j]=He[z]=!0,He[c]=He[u]=He[S]=He[s]=He[k]=He[f]=He[p]=He[d]=He[v]=He[g]=He[m]=He[y]=He[b]=He[_]=He[x]=!1;var Ue={};Ue[c]=Ue[u]=Ue[S]=Ue[k]=Ue[s]=Ue[f]=Ue[O]=Ue[E]=Ue[T]=Ue[C]=Ue[P]=Ue[v]=Ue[g]=Ue[m]=Ue[y]=Ue[b]=Ue[_]=Ue[w]=Ue[I]=Ue["[object Uint8ClampedArray]"]=Ue[j]=Ue[z]=!0,Ue[p]=Ue[d]=Ue[x]=!1;var We={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Be=parseFloat,Ve=parseInt,Ge="object"==typeof e&&e&&e.Object===Object&&e,Ke="object"==typeof self&&self&&self.Object===Object&&self,qe=Ge||Ke||Function("return this")(),$e=t&&!t.nodeType&&t,Qe=$e&&"object"==typeof r&&r&&!r.nodeType&&r,Ye=Qe&&Qe.exports===$e,Xe=Ye&&Ge.process,Je=function(){try{var e=Qe&&Qe.require&&Qe.require("util").types;return e||Xe&&Xe.binding&&Xe.binding("util")}catch(e){}}(),Ze=Je&&Je.isArrayBuffer,et=Je&&Je.isDate,tt=Je&&Je.isMap,nt=Je&&Je.isRegExp,rt=Je&&Je.isSet,ot=Je&&Je.isTypedArray;function it(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function at(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function pt(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function Mt(e,t){for(var n=e.length;n--&&wt(t,e[n],0)>-1;);return n}function Nt(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var At=Et({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),Lt=Et({"&":"&","<":"<",">":">",'"':""","'":"'"});function Ft(e){return"\\"+We[e]}function Dt(e){return Ae.test(e)}function Ht(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function Ut(e,t){return function(n){return e(t(n))}}function Wt(e,t){for(var n=-1,r=e.length,o=0,i=[];++n",""":'"',"'":"'"});var $t=function e(t){var n,r=(t=null==t?qe:$t.defaults(qe.Object(),t,$t.pick(qe,Fe))).Array,o=t.Date,pe=t.Error,de=t.Function,he=t.Math,ve=t.Object,ge=t.RegExp,me=t.String,ye=t.TypeError,be=r.prototype,_e=de.prototype,we=ve.prototype,xe=t["__core-js_shared__"],Se=_e.toString,ke=we.hasOwnProperty,Oe=0,Ee=(n=/[^.]+$/.exec(xe&&xe.keys&&xe.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Te=we.toString,Ce=Se.call(ve),Pe=qe._,Ie=ge("^"+Se.call(ke).replace(K,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=Ye?t.Buffer:void 0,Me=t.Symbol,Ae=t.Uint8Array,We=je?je.allocUnsafe:void 0,Ge=Ut(ve.getPrototypeOf,ve),Ke=ve.create,$e=we.propertyIsEnumerable,Qe=be.splice,Xe=Me?Me.isConcatSpreadable:void 0,Je=Me?Me.iterator:void 0,yt=Me?Me.toStringTag:void 0,Et=function(){try{var e=ei(ve,"defineProperty");return e({},"",{}),e}catch(e){}}(),Qt=t.clearTimeout!==qe.clearTimeout&&t.clearTimeout,Yt=o&&o.now!==qe.Date.now&&o.now,Xt=t.setTimeout!==qe.setTimeout&&t.setTimeout,Jt=he.ceil,Zt=he.floor,en=ve.getOwnPropertySymbols,tn=je?je.isBuffer:void 0,nn=t.isFinite,rn=be.join,on=Ut(ve.keys,ve),an=he.max,ln=he.min,cn=o.now,un=t.parseInt,sn=he.random,fn=be.reverse,pn=ei(t,"DataView"),dn=ei(t,"Map"),hn=ei(t,"Promise"),vn=ei(t,"Set"),gn=ei(t,"WeakMap"),mn=ei(ve,"create"),yn=gn&&new gn,bn={},_n=Ti(pn),wn=Ti(dn),xn=Ti(hn),Sn=Ti(vn),kn=Ti(gn),On=Me?Me.prototype:void 0,En=On?On.valueOf:void 0,Tn=On?On.toString:void 0;function Cn(e){if(Va(e)&&!Ra(e)&&!(e instanceof zn)){if(e instanceof jn)return e;if(ke.call(e,"__wrapped__"))return Ci(e)}return new jn(e)}var Pn=function(){function e(){}return function(t){if(!Ba(t))return{};if(Ke)return Ke(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();function In(){}function jn(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=void 0}function zn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Rn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function Yn(e,t,n,r,o,i){var a,l=1&t,u=2&t,p=4&t;if(n&&(a=o?n(e,r,o,i):n(e)),void 0!==a)return a;if(!Ba(e))return e;var x=Ra(e);if(x){if(a=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&ke.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!l)return yo(e,a)}else{var R=ri(e),M=R==d||R==h;if(La(e))return fo(e,l);if(R==m||R==c||M&&!o){if(a=u||M?{}:ii(e),!l)return u?function(e,t){return bo(e,ni(e),t)}(e,function(e,t){return e&&bo(t,wl(t),e)}(a,e)):function(e,t){return bo(e,ti(e),t)}(e,Kn(a,e))}else{if(!Ue[R])return o?e:{};a=function(e,t,n){var r=e.constructor;switch(t){case S:return po(e);case s:case f:return new r(+e);case k:return function(e,t){var n=t?po(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case O:case E:case T:case C:case P:case I:case"[object Uint8ClampedArray]":case j:case z:return ho(e,n);case v:return new r;case g:case _:return new r(e);case y:return function(e){var t=new e.constructor(e.source,re.exec(e));return t.lastIndex=e.lastIndex,t}(e);case b:return new r;case w:return o=e,En?ve(En.call(o)):{}}var o}(e,R,l)}}i||(i=new Ln);var N=i.get(e);if(N)return N;i.set(e,a),Qa(e)?e.forEach((function(r){a.add(Yn(r,t,n,r,e,i))})):Ga(e)&&e.forEach((function(r,o){a.set(o,Yn(r,t,n,o,e,i))}));var A=x?void 0:(p?u?qo:Ko:u?wl:_l)(e);return lt(A||e,(function(r,o){A&&(r=e[o=r]),Bn(a,o,Yn(r,t,n,o,e,i))})),a}function Xn(e,t,n){var r=n.length;if(null==e)return!r;for(e=ve(e);r--;){var o=n[r],i=t[o],a=e[o];if(void 0===a&&!(o in e)||!i(a))return!1}return!0}function Jn(e,t,n){if("function"!=typeof e)throw new ye(i);return _i((function(){e.apply(void 0,n)}),t)}function Zn(e,t,n,r){var o=-1,i=ft,a=!0,l=e.length,c=[],u=t.length;if(!l)return c;n&&(t=dt(t,It(n))),r?(i=pt,a=!1):t.length>=200&&(i=zt,a=!1,t=new An(t));e:for(;++o-1},Mn.prototype.set=function(e,t){var n=this.__data__,r=Vn(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},Nn.prototype.clear=function(){this.size=0,this.__data__={hash:new Rn,map:new(dn||Mn),string:new Rn}},Nn.prototype.delete=function(e){var t=Jo(this,e).delete(e);return this.size-=t?1:0,t},Nn.prototype.get=function(e){return Jo(this,e).get(e)},Nn.prototype.has=function(e){return Jo(this,e).has(e)},Nn.prototype.set=function(e,t){var n=Jo(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},An.prototype.add=An.prototype.push=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this},An.prototype.has=function(e){return this.__data__.has(e)},Ln.prototype.clear=function(){this.__data__=new Mn,this.size=0},Ln.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},Ln.prototype.get=function(e){return this.__data__.get(e)},Ln.prototype.has=function(e){return this.__data__.has(e)},Ln.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Mn){var r=n.__data__;if(!dn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Nn(r)}return n.set(e,t),this.size=n.size,this};var er=xo(cr),tr=xo(ur,!0);function nr(e,t){var n=!0;return er(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function rr(e,t,n){for(var r=-1,o=e.length;++r0&&n(l)?t>1?ir(l,t-1,n,r,o):ht(o,l):r||(o[o.length]=l)}return o}var ar=So(),lr=So(!0);function cr(e,t){return e&&ar(e,t,_l)}function ur(e,t){return e&&lr(e,t,_l)}function sr(e,t){return st(t,(function(t){return Ha(e[t])}))}function fr(e,t){for(var n=0,r=(t=lo(t,e)).length;null!=e&&nt}function vr(e,t){return null!=e&&ke.call(e,t)}function gr(e,t){return null!=e&&t in ve(e)}function mr(e,t,n){for(var o=n?pt:ft,i=e[0].length,a=e.length,l=a,c=r(a),u=1/0,s=[];l--;){var f=e[l];l&&t&&(f=dt(f,It(t))),u=ln(f.length,u),c[l]=!n&&(t||i>=120&&f.length>=120)?new An(l&&f):void 0}f=e[0];var p=-1,d=c[0];e:for(;++p=l)return c;var u=n[r];return c*("desc"==u?-1:1)}}return e.index-t.index}(e,t,n)}))}function Rr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)l!==e&&Qe.call(l,c,1),Qe.call(e,c,1);return e}function Nr(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;li(o)?Qe.call(e,o,1):Zr(e,o)}}return e}function Ar(e,t){return e+Zt(sn()*(t-e+1))}function Lr(e,t){var n="";if(!e||t<1||t>9007199254740991)return n;do{t%2&&(n+=e),(t=Zt(t/2))&&(e+=e)}while(t);return n}function Fr(e,t){return wi(vi(e,t,Kl),e+"")}function Dr(e){return Dn(Pl(e))}function Hr(e,t){var n=Pl(e);return ki(n,Qn(t,0,n.length))}function Ur(e,t,n,r){if(!Ba(e))return e;for(var o=-1,i=(t=lo(t,e)).length,a=i-1,l=e;null!=l&&++oi?0:i+t),(n=n>i?i:n)<0&&(n+=i),i=t>n?0:n-t>>>0,t>>>=0;for(var a=r(i);++o>>1,a=e[i];null!==a&&!Xa(a)&&(n?a<=t:a=200){var u=t?null:Fo(e);if(u)return Bt(u);a=!1,o=zt,c=new An}else c=t?[]:l;e:for(;++r=r?e:Gr(e,t,n)}var so=Qt||function(e){return qe.clearTimeout(e)};function fo(e,t){if(t)return e.slice();var n=e.length,r=We?We(n):new e.constructor(n);return e.copy(r),r}function po(e){var t=new e.constructor(e.byteLength);return new Ae(t).set(new Ae(e)),t}function ho(e,t){var n=t?po(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function vo(e,t){if(e!==t){var n=void 0!==e,r=null===e,o=e==e,i=Xa(e),a=void 0!==t,l=null===t,c=t==t,u=Xa(t);if(!l&&!u&&!i&&e>t||i&&a&&c&&!l&&!u||r&&a&&c||!n&&c||!o)return 1;if(!r&&!i&&!u&&e1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(i=e.length>3&&"function"==typeof i?(o--,i):void 0,a&&ci(n[0],n[1],a)&&(i=o<3?void 0:i,o=1),t=ve(t);++r-1?o[i?t[a]:a]:void 0}}function Co(e){return Go((function(t){var n=t.length,r=n,o=jn.prototype.thru;for(e&&t.reverse();r--;){var a=t[r];if("function"!=typeof a)throw new ye(i);if(o&&!l&&"wrapper"==Qo(a))var l=new jn([],!0)}for(r=l?r:n;++r1&&b.reverse(),f&&ul))return!1;var u=i.get(e),s=i.get(t);if(u&&s)return u==t&&s==e;var f=-1,p=!0,d=2&n?new An:void 0;for(i.set(e,t),i.set(t,e);++f-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace(X,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return lt(l,(function(n){var r="_."+n[0];t&n[1]&&!ft(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(J);return t?t[1].split(Z):[]}(r),n)))}function Si(e){var t=0,n=0;return function(){var r=cn(),o=16-(r-n);if(n=r,o>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function ki(e,t){var n=-1,r=e.length,o=r-1;for(t=void 0===t?r:t;++n1?e[t-1]:void 0;return n="function"==typeof n?(e.pop(),n):void 0,$i(e,n)}));function ta(e){var t=Cn(e);return t.__chain__=!0,t}function na(e,t){return t(e)}var ra=Go((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,o=function(t){return $n(t,e)};return!(t>1||this.__actions__.length)&&r instanceof zn&&li(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:na,args:[o],thisArg:void 0}),new jn(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(void 0),e}))):this.thru(o)}));var oa=_o((function(e,t,n){ke.call(e,n)?++e[n]:qn(e,n,1)}));var ia=To(zi),aa=To(Ri);function la(e,t){return(Ra(e)?lt:er)(e,Xo(t,3))}function ca(e,t){return(Ra(e)?ct:tr)(e,Xo(t,3))}var ua=_o((function(e,t,n){ke.call(e,n)?e[n].push(t):qn(e,n,[t])}));var sa=Fr((function(e,t,n){var o=-1,i="function"==typeof t,a=Na(e)?r(e.length):[];return er(e,(function(e){a[++o]=i?it(t,e,n):yr(e,t,n)})),a})),fa=_o((function(e,t,n){qn(e,n,t)}));function pa(e,t){return(Ra(e)?dt:Tr)(e,Xo(t,3))}var da=_o((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var ha=Fr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&ci(e,t[0],t[1])?t=[]:n>2&&ci(t[0],t[1],t[2])&&(t=[t[0]]),zr(e,ir(t,1),[])})),va=Yt||function(){return qe.Date.now()};function ga(e,t,n){return t=n?void 0:t,Ho(e,128,void 0,void 0,void 0,void 0,t=e&&null==t?e.length:t)}function ma(e,t){var n;if("function"!=typeof t)throw new ye(i);return e=rl(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=void 0),n}}var ya=Fr((function(e,t,n){var r=1;if(n.length){var o=Wt(n,Yo(ya));r|=32}return Ho(e,r,t,n,o)})),ba=Fr((function(e,t,n){var r=3;if(n.length){var o=Wt(n,Yo(ba));r|=32}return Ho(t,r,e,n,o)}));function _a(e,t,n){var r,o,a,l,c,u,s=0,f=!1,p=!1,d=!0;if("function"!=typeof e)throw new ye(i);function h(t){var n=r,i=o;return r=o=void 0,s=t,l=e.apply(i,n)}function v(e){return s=e,c=_i(m,t),f?h(e):l}function g(e){var n=e-u;return void 0===u||n>=t||n<0||p&&e-s>=a}function m(){var e=va();if(g(e))return y(e);c=_i(m,function(e){var n=t-(e-u);return p?ln(n,a-(e-s)):n}(e))}function y(e){return c=void 0,d&&r?h(e):(r=o=void 0,l)}function b(){var e=va(),n=g(e);if(r=arguments,o=this,u=e,n){if(void 0===c)return v(u);if(p)return so(c),c=_i(m,t),h(u)}return void 0===c&&(c=_i(m,t)),l}return t=il(t)||0,Ba(n)&&(f=!!n.leading,a=(p="maxWait"in n)?an(il(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),b.cancel=function(){void 0!==c&&so(c),s=0,r=u=o=c=void 0},b.flush=function(){return void 0===c?l:y(va())},b}var wa=Fr((function(e,t){return Jn(e,1,t)})),xa=Fr((function(e,t,n){return Jn(e,il(t)||0,n)}));function Sa(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new ye(i);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(Sa.Cache||Nn),n}function ka(e){if("function"!=typeof e)throw new ye(i);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Sa.Cache=Nn;var Oa=co((function(e,t){var n=(t=1==t.length&&Ra(t[0])?dt(t[0],It(Xo())):dt(ir(t,1),It(Xo()))).length;return Fr((function(r){for(var o=-1,i=ln(r.length,n);++o=t})),za=br(function(){return arguments}())?br:function(e){return Va(e)&&ke.call(e,"callee")&&!$e.call(e,"callee")},Ra=r.isArray,Ma=Ze?It(Ze):function(e){return Va(e)&&dr(e)==S};function Na(e){return null!=e&&Wa(e.length)&&!Ha(e)}function Aa(e){return Va(e)&&Na(e)}var La=tn||ic,Fa=et?It(et):function(e){return Va(e)&&dr(e)==f};function Da(e){if(!Va(e))return!1;var t=dr(e);return t==p||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!qa(e)}function Ha(e){if(!Ba(e))return!1;var t=dr(e);return t==d||t==h||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Ua(e){return"number"==typeof e&&e==rl(e)}function Wa(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}function Ba(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function Va(e){return null!=e&&"object"==typeof e}var Ga=tt?It(tt):function(e){return Va(e)&&ri(e)==v};function Ka(e){return"number"==typeof e||Va(e)&&dr(e)==g}function qa(e){if(!Va(e)||dr(e)!=m)return!1;var t=Ge(e);if(null===t)return!0;var n=ke.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&Se.call(n)==Ce}var $a=nt?It(nt):function(e){return Va(e)&&dr(e)==y};var Qa=rt?It(rt):function(e){return Va(e)&&ri(e)==b};function Ya(e){return"string"==typeof e||!Ra(e)&&Va(e)&&dr(e)==_}function Xa(e){return"symbol"==typeof e||Va(e)&&dr(e)==w}var Ja=ot?It(ot):function(e){return Va(e)&&Wa(e.length)&&!!He[dr(e)]};var Za=No(Er),el=No((function(e,t){return e<=t}));function tl(e){if(!e)return[];if(Na(e))return Ya(e)?Kt(e):yo(e);if(Je&&e[Je])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[Je]());var t=ri(e);return(t==v?Ht:t==b?Bt:Pl)(e)}function nl(e){return e?(e=il(e))===1/0||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function rl(e){var t=nl(e),n=t%1;return t==t?n?t-n:t:0}function ol(e){return e?Qn(rl(e),0,4294967295):0}function il(e){if("number"==typeof e)return e;if(Xa(e))return NaN;if(Ba(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Ba(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace($,"");var n=ie.test(e);return n||le.test(e)?Ve(e.slice(2),n?2:8):oe.test(e)?NaN:+e}function al(e){return bo(e,wl(e))}function ll(e){return null==e?"":Xr(e)}var cl=wo((function(e,t){if(pi(t)||Na(t))bo(t,_l(t),e);else for(var n in t)ke.call(t,n)&&Bn(e,n,t[n])})),ul=wo((function(e,t){bo(t,wl(t),e)})),sl=wo((function(e,t,n,r){bo(t,wl(t),e,r)})),fl=wo((function(e,t,n,r){bo(t,_l(t),e,r)})),pl=Go($n);var dl=Fr((function(e,t){e=ve(e);var n=-1,r=t.length,o=r>2?t[2]:void 0;for(o&&ci(t[0],t[1],o)&&(r=1);++n1),t})),bo(e,qo(e),n),r&&(n=Yn(n,7,Bo));for(var o=t.length;o--;)Zr(n,t[o]);return n}));var Ol=Go((function(e,t){return null==e?{}:function(e,t){return Rr(e,t,(function(t,n){return gl(e,n)}))}(e,t)}));function El(e,t){if(null==e)return{};var n=dt(qo(e),(function(e){return[e]}));return t=Xo(t),Rr(e,n,(function(e,n){return t(e,n[0])}))}var Tl=Do(_l),Cl=Do(wl);function Pl(e){return null==e?[]:jt(e,_l(e))}var Il=Oo((function(e,t,n){return t=t.toLowerCase(),e+(n?jl(t):t)}));function jl(e){return Dl(ll(e).toLowerCase())}function zl(e){return(e=ll(e))&&e.replace(ue,At).replace(Re,"")}var Rl=Oo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ml=Oo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Nl=ko("toLowerCase");var Al=Oo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var Ll=Oo((function(e,t,n){return e+(n?" ":"")+Dl(t)}));var Fl=Oo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Dl=ko("toUpperCase");function Hl(e,t,n){return e=ll(e),void 0===(t=n?void 0:t)?function(e){return Le.test(e)}(e)?function(e){return e.match(Ne)||[]}(e):function(e){return e.match(ee)||[]}(e):e.match(t)||[]}var Ul=Fr((function(e,t){try{return it(e,void 0,t)}catch(e){return Da(e)?e:new pe(e)}})),Wl=Go((function(e,t){return lt(t,(function(t){t=Ei(t),qn(e,t,ya(e[t],e))})),e}));function Bl(e){return function(){return e}}var Vl=Co(),Gl=Co(!0);function Kl(e){return e}function ql(e){return Sr("function"==typeof e?e:Yn(e,1))}var $l=Fr((function(e,t){return function(n){return yr(n,e,t)}})),Ql=Fr((function(e,t){return function(n){return yr(e,n,t)}}));function Yl(e,t,n){var r=_l(t),o=sr(t,r);null!=n||Ba(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=sr(t,_l(t)));var i=!(Ba(n)&&"chain"in n&&!n.chain),a=Ha(e);return lt(o,(function(n){var r=t[n];e[n]=r,a&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=yo(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,ht([this.value()],arguments))})})),e}function Xl(){}var Jl=zo(dt),Zl=zo(ut),ec=zo(mt);function tc(e){return ui(e)?Ot(Ei(e)):function(e){return function(t){return fr(t,e)}}(e)}var nc=Mo(),rc=Mo(!0);function oc(){return[]}function ic(){return!1}var ac=jo((function(e,t){return e+t}),0),lc=Lo("ceil"),cc=jo((function(e,t){return e/t}),1),uc=Lo("floor");var sc,fc=jo((function(e,t){return e*t}),1),pc=Lo("round"),dc=jo((function(e,t){return e-t}),0);return Cn.after=function(e,t){if("function"!=typeof t)throw new ye(i);return e=rl(e),function(){if(--e<1)return t.apply(this,arguments)}},Cn.ary=ga,Cn.assign=cl,Cn.assignIn=ul,Cn.assignInWith=sl,Cn.assignWith=fl,Cn.at=pl,Cn.before=ma,Cn.bind=ya,Cn.bindAll=Wl,Cn.bindKey=ba,Cn.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return Ra(e)?e:[e]},Cn.chain=ta,Cn.chunk=function(e,t,n){t=(n?ci(e,t,n):void 0===t)?1:an(rl(t),0);var o=null==e?0:e.length;if(!o||t<1)return[];for(var i=0,a=0,l=r(Jt(o/t));io?0:o+n),(r=void 0===r||r>o?o:rl(r))<0&&(r+=o),r=n>r?0:ol(r);n>>0)?(e=ll(e))&&("string"==typeof t||null!=t&&!$a(t))&&!(t=Xr(t))&&Dt(e)?uo(Kt(e),0,n):e.split(t,n):[]},Cn.spread=function(e,t){if("function"!=typeof e)throw new ye(i);return t=null==t?0:an(rl(t),0),Fr((function(n){var r=n[t],o=uo(n,0,t);return r&&ht(o,r),it(e,this,o)}))},Cn.tail=function(e){var t=null==e?0:e.length;return t?Gr(e,1,t):[]},Cn.take=function(e,t,n){return e&&e.length?Gr(e,0,(t=n||void 0===t?1:rl(t))<0?0:t):[]},Cn.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?Gr(e,(t=r-(t=n||void 0===t?1:rl(t)))<0?0:t,r):[]},Cn.takeRightWhile=function(e,t){return e&&e.length?to(e,Xo(t,3),!1,!0):[]},Cn.takeWhile=function(e,t){return e&&e.length?to(e,Xo(t,3)):[]},Cn.tap=function(e,t){return t(e),e},Cn.throttle=function(e,t,n){var r=!0,o=!0;if("function"!=typeof e)throw new ye(i);return Ba(n)&&(r="leading"in n?!!n.leading:r,o="trailing"in n?!!n.trailing:o),_a(e,t,{leading:r,maxWait:t,trailing:o})},Cn.thru=na,Cn.toArray=tl,Cn.toPairs=Tl,Cn.toPairsIn=Cl,Cn.toPath=function(e){return Ra(e)?dt(e,Ei):Xa(e)?[e]:yo(Oi(ll(e)))},Cn.toPlainObject=al,Cn.transform=function(e,t,n){var r=Ra(e),o=r||La(e)||Ja(e);if(t=Xo(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:Ba(e)&&Ha(i)?Pn(Ge(e)):{}}return(o?lt:cr)(e,(function(e,r,o){return t(n,e,r,o)})),n},Cn.unary=function(e){return ga(e,1)},Cn.union=Vi,Cn.unionBy=Gi,Cn.unionWith=Ki,Cn.uniq=function(e){return e&&e.length?Jr(e):[]},Cn.uniqBy=function(e,t){return e&&e.length?Jr(e,Xo(t,2)):[]},Cn.uniqWith=function(e,t){return t="function"==typeof t?t:void 0,e&&e.length?Jr(e,void 0,t):[]},Cn.unset=function(e,t){return null==e||Zr(e,t)},Cn.unzip=qi,Cn.unzipWith=$i,Cn.update=function(e,t,n){return null==e?e:eo(e,t,ao(n))},Cn.updateWith=function(e,t,n,r){return r="function"==typeof r?r:void 0,null==e?e:eo(e,t,ao(n),r)},Cn.values=Pl,Cn.valuesIn=function(e){return null==e?[]:jt(e,wl(e))},Cn.without=Qi,Cn.words=Hl,Cn.wrap=function(e,t){return Ea(ao(t),e)},Cn.xor=Yi,Cn.xorBy=Xi,Cn.xorWith=Ji,Cn.zip=Zi,Cn.zipObject=function(e,t){return oo(e||[],t||[],Bn)},Cn.zipObjectDeep=function(e,t){return oo(e||[],t||[],Ur)},Cn.zipWith=ea,Cn.entries=Tl,Cn.entriesIn=Cl,Cn.extend=ul,Cn.extendWith=sl,Yl(Cn,Cn),Cn.add=ac,Cn.attempt=Ul,Cn.camelCase=Il,Cn.capitalize=jl,Cn.ceil=lc,Cn.clamp=function(e,t,n){return void 0===n&&(n=t,t=void 0),void 0!==n&&(n=(n=il(n))==n?n:0),void 0!==t&&(t=(t=il(t))==t?t:0),Qn(il(e),t,n)},Cn.clone=function(e){return Yn(e,4)},Cn.cloneDeep=function(e){return Yn(e,5)},Cn.cloneDeepWith=function(e,t){return Yn(e,5,t="function"==typeof t?t:void 0)},Cn.cloneWith=function(e,t){return Yn(e,4,t="function"==typeof t?t:void 0)},Cn.conformsTo=function(e,t){return null==t||Xn(e,t,_l(t))},Cn.deburr=zl,Cn.defaultTo=function(e,t){return null==e||e!=e?t:e},Cn.divide=cc,Cn.endsWith=function(e,t,n){e=ll(e),t=Xr(t);var r=e.length,o=n=void 0===n?r:Qn(rl(n),0,r);return(n-=t.length)>=0&&e.slice(n,o)==t},Cn.eq=Pa,Cn.escape=function(e){return(e=ll(e))&&D.test(e)?e.replace(L,Lt):e},Cn.escapeRegExp=function(e){return(e=ll(e))&&q.test(e)?e.replace(K,"\\$&"):e},Cn.every=function(e,t,n){var r=Ra(e)?ut:nr;return n&&ci(e,t,n)&&(t=void 0),r(e,Xo(t,3))},Cn.find=ia,Cn.findIndex=zi,Cn.findKey=function(e,t){return bt(e,Xo(t,3),cr)},Cn.findLast=aa,Cn.findLastIndex=Ri,Cn.findLastKey=function(e,t){return bt(e,Xo(t,3),ur)},Cn.floor=uc,Cn.forEach=la,Cn.forEachRight=ca,Cn.forIn=function(e,t){return null==e?e:ar(e,Xo(t,3),wl)},Cn.forInRight=function(e,t){return null==e?e:lr(e,Xo(t,3),wl)},Cn.forOwn=function(e,t){return e&&cr(e,Xo(t,3))},Cn.forOwnRight=function(e,t){return e&&ur(e,Xo(t,3))},Cn.get=vl,Cn.gt=Ia,Cn.gte=ja,Cn.has=function(e,t){return null!=e&&oi(e,t,vr)},Cn.hasIn=gl,Cn.head=Ni,Cn.identity=Kl,Cn.includes=function(e,t,n,r){e=Na(e)?e:Pl(e),n=n&&!r?rl(n):0;var o=e.length;return n<0&&(n=an(o+n,0)),Ya(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&wt(e,t,n)>-1},Cn.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:rl(n);return o<0&&(o=an(r+o,0)),wt(e,t,o)},Cn.inRange=function(e,t,n){return t=nl(t),void 0===n?(n=t,t=0):n=nl(n),function(e,t,n){return e>=ln(t,n)&&e=-9007199254740991&&e<=9007199254740991},Cn.isSet=Qa,Cn.isString=Ya,Cn.isSymbol=Xa,Cn.isTypedArray=Ja,Cn.isUndefined=function(e){return void 0===e},Cn.isWeakMap=function(e){return Va(e)&&ri(e)==x},Cn.isWeakSet=function(e){return Va(e)&&"[object WeakSet]"==dr(e)},Cn.join=function(e,t){return null==e?"":rn.call(e,t)},Cn.kebabCase=Rl,Cn.last=Di,Cn.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=r;return void 0!==n&&(o=(o=rl(n))<0?an(r+o,0):ln(o,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,o):_t(e,St,o,!0)},Cn.lowerCase=Ml,Cn.lowerFirst=Nl,Cn.lt=Za,Cn.lte=el,Cn.max=function(e){return e&&e.length?rr(e,Kl,hr):void 0},Cn.maxBy=function(e,t){return e&&e.length?rr(e,Xo(t,2),hr):void 0},Cn.mean=function(e){return kt(e,Kl)},Cn.meanBy=function(e,t){return kt(e,Xo(t,2))},Cn.min=function(e){return e&&e.length?rr(e,Kl,Er):void 0},Cn.minBy=function(e,t){return e&&e.length?rr(e,Xo(t,2),Er):void 0},Cn.stubArray=oc,Cn.stubFalse=ic,Cn.stubObject=function(){return{}},Cn.stubString=function(){return""},Cn.stubTrue=function(){return!0},Cn.multiply=fc,Cn.nth=function(e,t){return e&&e.length?jr(e,rl(t)):void 0},Cn.noConflict=function(){return qe._===this&&(qe._=Pe),this},Cn.noop=Xl,Cn.now=va,Cn.pad=function(e,t,n){e=ll(e);var r=(t=rl(t))?Gt(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return Ro(Zt(o),n)+e+Ro(Jt(o),n)},Cn.padEnd=function(e,t,n){e=ll(e);var r=(t=rl(t))?Gt(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var o=sn();return ln(e+o*(t-e+Be("1e-"+((o+"").length-1))),t)}return Ar(e,t)},Cn.reduce=function(e,t,n){var r=Ra(e)?vt:Tt,o=arguments.length<3;return r(e,Xo(t,4),n,o,er)},Cn.reduceRight=function(e,t,n){var r=Ra(e)?gt:Tt,o=arguments.length<3;return r(e,Xo(t,4),n,o,tr)},Cn.repeat=function(e,t,n){return t=(n?ci(e,t,n):void 0===t)?1:rl(t),Lr(ll(e),t)},Cn.replace=function(){var e=arguments,t=ll(e[0]);return e.length<3?t:t.replace(e[1],e[2])},Cn.result=function(e,t,n){var r=-1,o=(t=lo(t,e)).length;for(o||(o=1,e=void 0);++r9007199254740991)return[];var n=4294967295,r=ln(e,4294967295);e-=4294967295;for(var o=Pt(r,t=Xo(t));++n=i)return e;var l=n-Gt(r);if(l<1)return r;var c=a?uo(a,0,l).join(""):e.slice(0,l);if(void 0===o)return c+r;if(a&&(l+=c.length-l),$a(o)){if(e.slice(l).search(o)){var u,s=c;for(o.global||(o=ge(o.source,ll(re.exec(o))+"g")),o.lastIndex=0;u=o.exec(s);)var f=u.index;c=c.slice(0,void 0===f?l:f)}}else if(e.indexOf(Xr(o),l)!=l){var p=c.lastIndexOf(o);p>-1&&(c=c.slice(0,p))}return c+r},Cn.unescape=function(e){return(e=ll(e))&&F.test(e)?e.replace(A,qt):e},Cn.uniqueId=function(e){var t=++Oe;return ll(e)+t},Cn.upperCase=Fl,Cn.upperFirst=Dl,Cn.each=la,Cn.eachRight=ca,Cn.first=Ni,Yl(Cn,(sc={},cr(Cn,(function(e,t){ke.call(Cn.prototype,t)||(sc[t]=e)})),sc),{chain:!1}),Cn.VERSION="4.17.19",lt(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){Cn[e].placeholder=Cn})),lt(["drop","take"],(function(e,t){zn.prototype[e]=function(n){n=void 0===n?1:an(rl(n),0);var r=this.__filtered__&&!t?new zn(this):this.clone();return r.__filtered__?r.__takeCount__=ln(n,r.__takeCount__):r.__views__.push({size:ln(n,4294967295),type:e+(r.__dir__<0?"Right":"")}),r},zn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),lt(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;zn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:Xo(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),lt(["head","last"],(function(e,t){var n="take"+(t?"Right":"");zn.prototype[e]=function(){return this[n](1).value()[0]}})),lt(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");zn.prototype[e]=function(){return this.__filtered__?new zn(this):this[n](1)}})),zn.prototype.compact=function(){return this.filter(Kl)},zn.prototype.find=function(e){return this.filter(e).head()},zn.prototype.findLast=function(e){return this.reverse().find(e)},zn.prototype.invokeMap=Fr((function(e,t){return"function"==typeof e?new zn(this):this.map((function(n){return yr(n,e,t)}))})),zn.prototype.reject=function(e){return this.filter(ka(Xo(e)))},zn.prototype.slice=function(e,t){e=rl(e);var n=this;return n.__filtered__&&(e>0||t<0)?new zn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),void 0!==t&&(n=(t=rl(t))<0?n.dropRight(-t):n.take(t-e)),n)},zn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},zn.prototype.toArray=function(){return this.take(4294967295)},cr(zn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),o=Cn[r?"take"+("last"==t?"Right":""):t],i=r||/^find/.test(t);o&&(Cn.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,l=t instanceof zn,c=a[0],u=l||Ra(t),s=function(e){var t=o.apply(Cn,ht([e],a));return r&&f?t[0]:t};u&&n&&"function"==typeof c&&1!=c.length&&(l=u=!1);var f=this.__chain__,p=!!this.__actions__.length,d=i&&!f,h=l&&!p;if(!i&&u){t=h?t:new zn(this);var v=e.apply(t,a);return v.__actions__.push({func:na,args:[s],thisArg:void 0}),new jn(v,f)}return d&&h?e.apply(this,a):(v=this.thru(s),d?r?v.value()[0]:v.value():v)})})),lt(["pop","push","shift","sort","splice","unshift"],(function(e){var t=be[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);Cn.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(Ra(o)?o:[],e)}return this[n]((function(n){return t.apply(Ra(n)?n:[],e)}))}})),cr(zn.prototype,(function(e,t){var n=Cn[t];if(n){var r=n.name+"";ke.call(bn,r)||(bn[r]=[]),bn[r].push({name:t,func:n})}})),bn[Po(void 0,2).name]=[{name:"wrapper",func:void 0}],zn.prototype.clone=function(){var e=new zn(this.__wrapped__);return e.__actions__=yo(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=yo(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=yo(this.__views__),e},zn.prototype.reverse=function(){if(this.__filtered__){var e=new zn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},zn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=Ra(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?void 0:this.__values__[this.__index__++]}},Cn.prototype.plant=function(e){for(var t,n=this;n instanceof In;){var r=Ci(n);r.__index__=0,r.__values__=void 0,t?o.__wrapped__=r:t=r;var o=r;n=n.__wrapped__}return o.__wrapped__=e,t},Cn.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof zn){var t=e;return this.__actions__.length&&(t=new zn(this)),(t=t.reverse()).__actions__.push({func:na,args:[Bi],thisArg:void 0}),new jn(t,this.__chain__)}return this.thru(Bi)},Cn.prototype.toJSON=Cn.prototype.valueOf=Cn.prototype.value=function(){return no(this.__wrapped__,this.__actions__)},Cn.prototype.first=Cn.prototype.head,Je&&(Cn.prototype[Je]=function(){return this}),Cn}();qe._=$t,void 0===(o=function(){return $t}.call(t,n,t,r))||(r.exports=o)}).call(this)}).call(this,n(108),n(243)(e))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(108))},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperties:n(172)})},function(e,t){var n=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=n)},function(e,t,n){var r=n(81);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var r=n(10),o=n(249),i=n(60),a=n(94),l=n(174);r(r.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n,r=i(e),c=a.f,u=o(r),s={},f=0;u.length>f;)void 0!==(n=c(r,t=u[f++]))&&l(s,t,n);return s}})},function(e,t,n){var r=n(27),o=n(172),i=n(132),a=n(131)("IE_PROTO"),l=function(){},c=function(){var e,t=n(171)("iframe"),r=i.length;for(t.style.display="none",n(251).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write(" + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html new file mode 100644 index 00000000000..6b4e0780039 --- /dev/null +++ b/docs/-cont/arrow/-cont-effect/ensure.html @@ -0,0 +1,49 @@ + + + + ensure + + +
+
+ + +
+
+
+
+
+
+ +
+

ensure

+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> R)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html new file mode 100644 index 00000000000..55a5d818129 --- /dev/null +++ b/docs/-cont/arrow/-cont-effect/index.html @@ -0,0 +1,141 @@ + + + + ContEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

ContEffect

+
interface ContEffect<R>

Context of the Cont DSL.

+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> R)
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Inheritors

+
+
+
+
IorEffect +
Link copied to clipboard
+
+
+
+
+ +
+
+
OptionEffect +
Link copied to clipboard
+
+
+
+
+
+

Extensions

+
+
+
+
ensureNotNull +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html new file mode 100644 index 00000000000..fe9c2a65001 --- /dev/null +++ b/docs/-cont/arrow/-cont-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html new file mode 100644 index 00000000000..7821fbbb999 --- /dev/null +++ b/docs/-cont/arrow/-cont/attempt.html @@ -0,0 +1,49 @@ + + + + attempt + + +
+
+ + +
+
+
+
+
+
+ +
+

attempt

+
+
+ +
+
open fun attempt(): Cont<R, Result<A>>
+
+

Runs the Cont and captures any NonFatal exception into Result.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/flat-map.html b/docs/-cont/arrow/-cont/flat-map.html new file mode 100644 index 00000000000..cfdb33dc786 --- /dev/null +++ b/docs/-cont/arrow/-cont/flat-map.html @@ -0,0 +1,49 @@ + + + + flatMap + + +
+
+ + +
+
+
+
+
+
+ +
+

flatMap

+
+
+ +
+
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
+
+

Maps the values A with the transform function into another Cont effect.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/fold.html b/docs/-cont/arrow/-cont/fold.html new file mode 100644 index 00000000000..c7696b3f4b3 --- /dev/null +++ b/docs/-cont/arrow/-cont/fold.html @@ -0,0 +1,44 @@ + + + + fold + + +
+
+ + +
+
+
+
+
+
+ +
+

fold

+
+
+ +
+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
.let(::println)

cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
.let(::println)
}
Hello, World!
1000
+
+ +
+
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html new file mode 100644 index 00000000000..52fea6aef1b --- /dev/null +++ b/docs/-cont/arrow/-cont/handle-error-with.html @@ -0,0 +1,49 @@ + + + + handleErrorWith + + +
+
+ + +
+
+
+
+
+
+ +
+

handleErrorWith

+
+
+ +
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html new file mode 100644 index 00000000000..beae7780384 --- /dev/null +++ b/docs/-cont/arrow/-cont/handle-error.html @@ -0,0 +1,49 @@ + + + + handleError + + +
+
+ + +
+
+
+
+
+
+ +
+

handleError

+
+
+ +
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html new file mode 100644 index 00000000000..b68ee5ff349 --- /dev/null +++ b/docs/-cont/arrow/-cont/index.html @@ -0,0 +1,280 @@ + + + + Cont + + +
+
+ + +
+
+
+
+
+
+ +
+

Cont

+
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

+
+
+
+
+

Functions

+
+
+
+
attempt +
Link copied to clipboard
+
+
+
+ +
+
open fun attempt(): Cont<R, Result<A>>
+
+

Runs the Cont and captures any NonFatal exception into Result.

+
+
+
+
+ +
+
+
flatMap +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
+
+

Maps the values A with the transform function into another Cont effect.

+
+
+
+
+ +
+
+
fold +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

+
+ +
+
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
+
+

Like fold but also allows folding over any unexpected Throwable that might have occurred.

+
+
+
+
+ +
+
+
handleError +
Link copied to clipboard
+
+
+
+ +
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
+
+
+
+
+
+
+ +
+
+
handleErrorWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
+
+
+
+
+
+
+ +
+
+
map +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
+
+

Maps the values A with the transform function into B.

+
+
+
+
+ +
+
+
redeem +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
+
+
+
+
+
+
+ +
+
+
redeemWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
+
+
+
+
+
+
+ +
+
+
toEither +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toEither(): Either<R, A>
+
+

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+
+
+
+
+ +
+
+
toIor +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toIor(): Ior<R, A>
+
+

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+
+
+
+
+ +
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
+
+

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+
+
+
+
+ +
+
+
toValidated +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun toValidated(): Validated<R, A>
+
+

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+
+
+
+
+
+

Extensions

+
+
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/map.html b/docs/-cont/arrow/-cont/map.html new file mode 100644 index 00000000000..9ba377fa24f --- /dev/null +++ b/docs/-cont/arrow/-cont/map.html @@ -0,0 +1,49 @@ + + + + map + + +
+
+ + +
+
+
+
+
+
+ +
+

map

+
+
+ +
+
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
+
+

Maps the values A with the transform function into B.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html new file mode 100644 index 00000000000..0fbc415252b --- /dev/null +++ b/docs/-cont/arrow/-cont/redeem-with.html @@ -0,0 +1,49 @@ + + + + redeemWith + + +
+
+ + +
+
+
+
+
+
+ +
+

redeemWith

+
+
+ +
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html new file mode 100644 index 00000000000..2142bb5d9a2 --- /dev/null +++ b/docs/-cont/arrow/-cont/redeem.html @@ -0,0 +1,49 @@ + + + + redeem + + +
+
+ + +
+
+
+
+
+
+ +
+

redeem

+
+
+ +
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/to-either.html b/docs/-cont/arrow/-cont/to-either.html new file mode 100644 index 00000000000..7d78e2c89af --- /dev/null +++ b/docs/-cont/arrow/-cont/to-either.html @@ -0,0 +1,49 @@ + + + + toEither + + +
+
+ + +
+
+
+
+
+
+ +
+

toEither

+
+
+ +
+
open suspend fun toEither(): Either<R, A>
+
+

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/to-ior.html b/docs/-cont/arrow/-cont/to-ior.html new file mode 100644 index 00000000000..6b725f19a7b --- /dev/null +++ b/docs/-cont/arrow/-cont/to-ior.html @@ -0,0 +1,49 @@ + + + + toIor + + +
+
+ + +
+
+
+
+
+
+ +
+

toIor

+
+
+ +
+
open suspend fun toIor(): Ior<R, A>
+
+

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html new file mode 100644 index 00000000000..eed4b458f77 --- /dev/null +++ b/docs/-cont/arrow/-cont/to-option.html @@ -0,0 +1,49 @@ + + + + toOption + + +
+
+ + +
+
+
+
+
+
+ +
+

toOption

+
+
+ +
+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
+
+

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-cont/to-validated.html b/docs/-cont/arrow/-cont/to-validated.html new file mode 100644 index 00000000000..6688216eab9 --- /dev/null +++ b/docs/-cont/arrow/-cont/to-validated.html @@ -0,0 +1,49 @@ + + + + toValidated + + +
+
+ + +
+
+
+
+
+
+ +
+

toValidated

+
+
+ +
+
open suspend fun toValidated(): Validated<R, A>
+
+

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-ior-effect/-ior-effect.html b/docs/-cont/arrow/-ior-effect/-ior-effect.html new file mode 100644 index 00000000000..11312ffc4e7 --- /dev/null +++ b/docs/-cont/arrow/-ior-effect/-ior-effect.html @@ -0,0 +1,49 @@ + + + + IorEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

IorEffect

+
+
+ +
+
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html new file mode 100644 index 00000000000..3b4474f52a4 --- /dev/null +++ b/docs/-cont/arrow/-ior-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
suspend fun <B> Ior<E, B>.bind(): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-ior-effect/index.html b/docs/-cont/arrow/-ior-effect/index.html new file mode 100644 index 00000000000..3c843b41d8d --- /dev/null +++ b/docs/-cont/arrow/-ior-effect/index.html @@ -0,0 +1,153 @@ + + + + IorEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

IorEffect

+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<E, B>.bind(): B
open suspend fun <B> Either<E, B>.bind(): B
open suspend fun <B> Validated<E, B>.bind(): B
suspend fun <B> Ior<E, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> E): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
+
+
+
+
+
+
+ +
+
+
combine +
Link copied to clipboard
+
+
+
+ +
+
open override fun E.combine(b: E): E
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun ensure(value: Boolean, shift: () -> E)
+
+
+
+
+
+
+ +
+
+
maybeCombine +
Link copied to clipboard
+
+
+
+ +
+
open override fun E.maybeCombine(b: E?): E
+
+
+
+
+
+
+ +
+
+
plus +
Link copied to clipboard
+
+
+
+ +
+
open operator override fun E.plus(b: E): E
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
open suspend override fun <B> shift(r: E): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html new file mode 100644 index 00000000000..887058673a5 --- /dev/null +++ b/docs/-cont/arrow/-ior-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
open suspend override fun <B> shift(r: E): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-option-effect/-option-effect.html b/docs/-cont/arrow/-option-effect/-option-effect.html new file mode 100644 index 00000000000..0a2a3dbb6d1 --- /dev/null +++ b/docs/-cont/arrow/-option-effect/-option-effect.html @@ -0,0 +1,49 @@ + + + + OptionEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

OptionEffect

+
+
+ +
+
fun OptionEffect(cont: ContEffect<None>)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-option-effect/bind.html b/docs/-cont/arrow/-option-effect/bind.html new file mode 100644 index 00000000000..618b8e03723 --- /dev/null +++ b/docs/-cont/arrow/-option-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
suspend fun <B> Option<B>.bind(): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-option-effect/ensure.html b/docs/-cont/arrow/-option-effect/ensure.html new file mode 100644 index 00000000000..3ff95161a8a --- /dev/null +++ b/docs/-cont/arrow/-option-effect/ensure.html @@ -0,0 +1,49 @@ + + + + ensure + + +
+
+ + +
+
+
+
+
+
+ +
+

ensure

+
+
+ +
+
suspend fun ensure(value: Boolean)
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-option-effect/index.html b/docs/-cont/arrow/-option-effect/index.html new file mode 100644 index 00000000000..873c6d4d3cc --- /dev/null +++ b/docs/-cont/arrow/-option-effect/index.html @@ -0,0 +1,102 @@ + + + + OptionEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

OptionEffect

+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <B> Cont<None, B>.bind(): B
open suspend fun <B> Either<None, B>.bind(): B
open suspend fun <B> Validated<None, B>.bind(): B
suspend fun <B> Option<B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> None): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
+
+
+
+
+
+
+ +
+
+
ensure +
Link copied to clipboard
+
+
+
+ +
+
suspend fun ensure(value: Boolean)
open suspend fun ensure(value: Boolean, shift: () -> None)
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
open suspend override fun <B> shift(r: None): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-option-effect/shift.html b/docs/-cont/arrow/-option-effect/shift.html new file mode 100644 index 00000000000..60a62327ff2 --- /dev/null +++ b/docs/-cont/arrow/-option-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
open suspend override fun <B> shift(r: None): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont-effect/bind.html b/docs/-cont/arrow/-restricted-cont-effect/bind.html new file mode 100644 index 00000000000..8831c2192a0 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont-effect/bind.html @@ -0,0 +1,49 @@ + + + + bind + + +
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont-effect/index.html b/docs/-cont/arrow/-restricted-cont-effect/index.html new file mode 100644 index 00000000000..5c1647abba6 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont-effect/index.html @@ -0,0 +1,85 @@ + + + + RestrictedContEffect + + +
+
+ + +
+
+
+
+
+
+ +
+

RestrictedContEffect

+
interface RestrictedContEffect<R>
+
+
+
+
+

Functions

+
+
+
+
bind +
Link copied to clipboard
+
+
+
+ +
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A
+
+
+
+
+
+
+ +
+
+
shift +
Link copied to clipboard
+
+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont-effect/shift.html b/docs/-cont/arrow/-restricted-cont-effect/shift.html new file mode 100644 index 00000000000..75eeffb1dae --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont-effect/shift.html @@ -0,0 +1,49 @@ + + + + shift + + +
+
+ + +
+
+
+
+
+
+ +
+

shift

+
+
+ +
+
abstract suspend fun <B> shift(r: R): B
+
+

Short-circuit the Cont computation with value R.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/attempt.html b/docs/-cont/arrow/-restricted-cont/attempt.html new file mode 100644 index 00000000000..09b20bef86d --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/attempt.html @@ -0,0 +1,49 @@ + + + + attempt + + +
+
+ + +
+
+
+
+
+
+ +
+

attempt

+
+
+ +
+
open fun attempt(): RestrictedCont<R, Result<A>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/flat-map.html b/docs/-cont/arrow/-restricted-cont/flat-map.html new file mode 100644 index 00000000000..bdf27c33df8 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/flat-map.html @@ -0,0 +1,49 @@ + + + + flatMap + + +
+
+ + +
+
+
+
+
+
+ +
+

flatMap

+
+
+ +
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/fold.html b/docs/-cont/arrow/-restricted-cont/fold.html new file mode 100644 index 00000000000..e3e9bdca520 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/fold.html @@ -0,0 +1,49 @@ + + + + fold + + +
+
+ + +
+
+
+
+
+
+ +
+

fold

+
+
+ +
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/handle-error-with.html b/docs/-cont/arrow/-restricted-cont/handle-error-with.html new file mode 100644 index 00000000000..c2906fb5382 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/handle-error-with.html @@ -0,0 +1,49 @@ + + + + handleErrorWith + + +
+
+ + +
+
+
+
+
+
+ +
+

handleErrorWith

+
+
+ +
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/handle-error.html b/docs/-cont/arrow/-restricted-cont/handle-error.html new file mode 100644 index 00000000000..bdc6cc9cf1c --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/handle-error.html @@ -0,0 +1,49 @@ + + + + handleError + + +
+
+ + +
+
+
+
+
+
+ +
+

handleError

+
+
+ +
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/index.html b/docs/-cont/arrow/-restricted-cont/index.html new file mode 100644 index 00000000000..dfe8327124a --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/index.html @@ -0,0 +1,221 @@ + + + + RestrictedCont + + +
+
+ + +
+
+
+
+
+
+ +
+

RestrictedCont

+
interface RestrictedCont<R, A>
+
+
+
+
+

Functions

+
+
+
+
attempt +
Link copied to clipboard
+
+
+
+ +
+
open fun attempt(): RestrictedCont<R, Result<A>>
+
+
+
+
+
+
+ +
+
+
flatMap +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
+
+
+
+
+
+
+ +
+
+
fold +
Link copied to clipboard
+
+
+
+ +
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
+
+
+
+
+
+
+ +
+
+
handleError +
Link copied to clipboard
+
+
+
+ +
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
+
+
+
+
+
+
+ +
+
+
handleErrorWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
+
+
+
+
+
+
+ +
+
+
map +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
+
+
+
+
+
+
+ +
+
+
redeem +
Link copied to clipboard
+
+
+
+ +
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
+
+
+
+
+
+
+ +
+
+
redeemWith +
Link copied to clipboard
+
+
+
+ +
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
+
+
+
+
+
+
+ +
+
+
toEither +
Link copied to clipboard
+
+
+
+ +
+
open fun toEither(): Either<R, A>
+
+
+
+
+
+
+ +
+
+
toValidated +
Link copied to clipboard
+
+
+
+ +
+
open fun toValidated(): Validated<R, A>
+
+
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/map.html b/docs/-cont/arrow/-restricted-cont/map.html new file mode 100644 index 00000000000..3230133d155 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/map.html @@ -0,0 +1,49 @@ + + + + map + + +
+
+ + +
+
+
+
+
+
+ +
+

map

+
+
+ +
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/redeem-with.html b/docs/-cont/arrow/-restricted-cont/redeem-with.html new file mode 100644 index 00000000000..158bb93b814 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/redeem-with.html @@ -0,0 +1,49 @@ + + + + redeemWith + + +
+
+ + +
+
+
+
+
+
+ +
+

redeemWith

+
+
+ +
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/redeem.html b/docs/-cont/arrow/-restricted-cont/redeem.html new file mode 100644 index 00000000000..1f69dfcc9ff --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/redeem.html @@ -0,0 +1,49 @@ + + + + redeem + + +
+
+ + +
+
+
+
+
+
+ +
+

redeem

+
+
+ +
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/to-either.html b/docs/-cont/arrow/-restricted-cont/to-either.html new file mode 100644 index 00000000000..3186b9a0dd2 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/to-either.html @@ -0,0 +1,49 @@ + + + + toEither + + +
+
+ + +
+
+
+
+
+
+ +
+

toEither

+
+
+ +
+
open fun toEither(): Either<R, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-restricted-cont/to-validated.html b/docs/-cont/arrow/-restricted-cont/to-validated.html new file mode 100644 index 00000000000..8ad1731f236 --- /dev/null +++ b/docs/-cont/arrow/-restricted-cont/to-validated.html @@ -0,0 +1,49 @@ + + + + toValidated + + +
+
+ + +
+
+
+
+
+
+ +
+

toValidated

+
+
+ +
+
open fun toValidated(): Validated<R, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html new file mode 100644 index 00000000000..f7eb45a16ca --- /dev/null +++ b/docs/-cont/arrow/-shift-cancellation-exception/index.html @@ -0,0 +1,77 @@ + + + + ShiftCancellationException + + +
+
+ + +
+
+
+
+
+
+ +
+

ShiftCancellationException

+
sealed class ShiftCancellationException : CancellationException
+
+
+
+
+

Properties

+
+
+
+
cause +
Link copied to clipboard
+
+
+
+
open val cause: Throwable?
+
+
+
+
+ +
+
+
message +
Link copied to clipboard
+
+
+
+
open val message: String?
+
+
+
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/cont.html b/docs/-cont/arrow/cont.html new file mode 100644 index 00000000000..7139a759339 --- /dev/null +++ b/docs/-cont/arrow/cont.html @@ -0,0 +1,49 @@ + + + + cont + + +
+
+ + +
+
+
+
+
+
+ +
+

cont

+
+
+ +
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
+
+

DSL for constructing Cont values

import arrow.core.*
import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)
}
6
Option was empty
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/either.html b/docs/-cont/arrow/either.html new file mode 100644 index 00000000000..6dadabc5592 --- /dev/null +++ b/docs/-cont/arrow/either.html @@ -0,0 +1,49 @@ + + + + either + + +
+
+ + +
+
+
+
+
+
+ +
+

either

+
+
+ +
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/ensure-not-null.html b/docs/-cont/arrow/ensure-not-null.html new file mode 100644 index 00000000000..511bbbb022d --- /dev/null +++ b/docs/-cont/arrow/ensure-not-null.html @@ -0,0 +1,38 @@ + + + + ensureNotNull + + +
+
+ + +
+
+
+
+
+
+ +
+

ensureNotNull

+
+
+ +
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/index.html b/docs/-cont/arrow/index.html new file mode 100644 index 00000000000..bb47ee15bf0 --- /dev/null +++ b/docs/-cont/arrow/index.html @@ -0,0 +1,313 @@ + + + + arrow + + +
+
+ + +
+
+
+
+
+
+ +
+

Package arrow

+
+
+
+
+

Types

+
+
+
+
Cont +
Link copied to clipboard
+
+
+
+ +
+
interface Cont<R, A>
+
+

Cont represents a suspending computation that runs will either

+
+
+
+
+ +
+
+
ContEffect +
Link copied to clipboard
+
+
+
+ +
+
interface ContEffect<R>
+
+

Context of the Cont DSL.

+
+
+
+
+ +
+
+
IorEffect +
Link copied to clipboard
+
+
+
+ +
+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
+
+
+
+
+
+ +
+
+
OptionEffect +
Link copied to clipboard
+
+
+
+ +
+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
+
+
+
+
+
+ +
+
+
RestrictedCont +
Link copied to clipboard
+
+
+
+ +
+
interface RestrictedCont<R, A>
+
+
+
+
+
+
+ +
+
+
RestrictedContEffect +
Link copied to clipboard
+
+
+
+ +
+
interface RestrictedContEffect<R>
+
+
+
+
+
+
+ +
+
+
ShiftCancellationException +
Link copied to clipboard
+
+
+
+ +
+
sealed class ShiftCancellationException : CancellationException
+
+
+
+
+
+
+
+

Functions

+
+
+
+
cont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
+
+

DSL for constructing Cont values

+
+
+
+
+ +
+
+
either +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
+
+
+
+
+
+
+ +
+
+
ensureNotNull +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
+
+
+
+
+
+ +
+
+
ior +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
+
+
+
+
+
+
+ +
+
+
option +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
+
+
+
+
+
+
+ +
+
+
restrictedCont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
+
+

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+
+
+
+
+ +
+
+
sequence +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
+
+
+
+
+
+
+ +
+
+
toOption +
Link copied to clipboard
+
+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+
+
+
+
+ +
+
+
traverseCont +
Link copied to clipboard
+
+
+
+ +
+
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
+
+
+
+
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/ior.html b/docs/-cont/arrow/ior.html new file mode 100644 index 00000000000..ccfe54a3ed6 --- /dev/null +++ b/docs/-cont/arrow/ior.html @@ -0,0 +1,49 @@ + + + + ior + + +
+
+ + +
+
+
+
+
+
+ +
+

ior

+
+
+ +
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/option.html b/docs/-cont/arrow/option.html new file mode 100644 index 00000000000..e71079f52bf --- /dev/null +++ b/docs/-cont/arrow/option.html @@ -0,0 +1,49 @@ + + + + option + + +
+
+ + +
+
+
+
+
+
+ +
+

option

+
+
+ +
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/restricted-cont.html b/docs/-cont/arrow/restricted-cont.html new file mode 100644 index 00000000000..78f3e4ed309 --- /dev/null +++ b/docs/-cont/arrow/restricted-cont.html @@ -0,0 +1,49 @@ + + + + restrictedCont + + +
+
+ + +
+
+
+
+
+
+ +
+

restrictedCont

+
+
+ +
+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
+
+

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/sequence.html b/docs/-cont/arrow/sequence.html new file mode 100644 index 00000000000..0d16ca00359 --- /dev/null +++ b/docs/-cont/arrow/sequence.html @@ -0,0 +1,49 @@ + + + + sequence + + +
+
+ + +
+
+
+
+
+
+ +
+

sequence

+
+
+ +
+
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/to-option.html b/docs/-cont/arrow/to-option.html new file mode 100644 index 00000000000..d1758476010 --- /dev/null +++ b/docs/-cont/arrow/to-option.html @@ -0,0 +1,49 @@ + + + + toOption + + +
+
+ + +
+
+
+
+
+
+ +
+

toOption

+
+
+ +
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/arrow/traverse-cont.html b/docs/-cont/arrow/traverse-cont.html new file mode 100644 index 00000000000..ea68ee2a4cd --- /dev/null +++ b/docs/-cont/arrow/traverse-cont.html @@ -0,0 +1,49 @@ + + + + traverseCont + + +
+
+ + +
+
+
+
+
+
+ +
+

traverseCont

+
+
+ +
+
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
+
+
+

Sources

+
+
+
+
common source +
Link copied to clipboard
+
+
+
+
+
+
+ +
+
+ + + diff --git a/docs/-cont/package-list b/docs/-cont/package-list new file mode 100644 index 00000000000..0a3e95aedb1 --- /dev/null +++ b/docs/-cont/package-list @@ -0,0 +1,61 @@ +$dokka.format:html-v1 +$dokka.linkExtension:html +$dokka.location:arrow////PointingToDeclaration/-cont/arrow/index.html +$dokka.location:arrow//cont/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/cont.html +$dokka.location:arrow//either/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/either.html +$dokka.location:arrow//ensureNotNull/arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]#TypeParam(bounds=[kotlin.Any])?#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/ensure-not-null.html +$dokka.location:arrow//ensureNotNull/arrow.ContEffect[arrow.core.None]#TypeParam(bounds=[kotlin.Any])?/PointingToDeclaration/-cont/arrow/ensure-not-null.html +$dokka.location:arrow//ior/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[arrow.IorEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/ior.html +$dokka.location:arrow//option/#kotlin.Function1[arrow.OptionEffect,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/option.html +$dokka.location:arrow//restrictedCont/#kotlin.coroutines.SuspendFunction1[arrow.RestrictedContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/restricted-cont.html +$dokka.location:arrow//sequence/kotlin.collections.Iterable[arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#/PointingToDeclaration/-cont/arrow/sequence.html +$dokka.location:arrow//toOption/arrow.Cont[arrow.core.None,TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/to-option.html +$dokka.location:arrow//traverseCont/kotlin.collections.Iterable[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/traverse-cont.html +$dokka.location:arrow/Cont///PointingToDeclaration/-cont/arrow/-cont/index.html +$dokka.location:arrow/Cont/attempt/#/PointingToDeclaration/-cont/arrow/-cont/attempt.html +$dokka.location:arrow/Cont/flatMap/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/flat-map.html +$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html +$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html +$dokka.location:arrow/Cont/handleError/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/handle-error.html +$dokka.location:arrow/Cont/handleErrorWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/handle-error-with.html +$dokka.location:arrow/Cont/map/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/map.html +$dokka.location:arrow/Cont/redeem/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/redeem.html +$dokka.location:arrow/Cont/redeemWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/redeem-with.html +$dokka.location:arrow/Cont/toEither/#/PointingToDeclaration/-cont/arrow/-cont/to-either.html +$dokka.location:arrow/Cont/toIor/#/PointingToDeclaration/-cont/arrow/-cont/to-ior.html +$dokka.location:arrow/Cont/toOption/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/to-option.html +$dokka.location:arrow/Cont/toValidated/#/PointingToDeclaration/-cont/arrow/-cont/to-validated.html +$dokka.location:arrow/ContEffect///PointingToDeclaration/-cont/arrow/-cont-effect/index.html +$dokka.location:arrow/ContEffect/bind/arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Either[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/arrow.core.Validated[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/bind/kotlin.Result[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html +$dokka.location:arrow/ContEffect/ensure/#kotlin.Boolean#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/ensure.html +$dokka.location:arrow/ContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-cont-effect/shift.html +$dokka.location:arrow/IorEffect///PointingToDeclaration/-cont/arrow/-ior-effect/index.html +$dokka.location:arrow/IorEffect/IorEffect/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-ior-effect/-ior-effect.html +$dokka.location:arrow/IorEffect/bind/arrow.core.Ior[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-ior-effect/bind.html +$dokka.location:arrow/IorEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-ior-effect/shift.html +$dokka.location:arrow/OptionEffect///PointingToDeclaration/-cont/arrow/-option-effect/index.html +$dokka.location:arrow/OptionEffect/OptionEffect/#arrow.ContEffect[arrow.core.None]/PointingToDeclaration/-cont/arrow/-option-effect/-option-effect.html +$dokka.location:arrow/OptionEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-option-effect/bind.html +$dokka.location:arrow/OptionEffect/ensure/#kotlin.Boolean/PointingToDeclaration/-cont/arrow/-option-effect/ensure.html +$dokka.location:arrow/OptionEffect/shift/#arrow.core.None/PointingToDeclaration/-cont/arrow/-option-effect/shift.html +$dokka.location:arrow/RestrictedCont///PointingToDeclaration/-cont/arrow/-restricted-cont/index.html +$dokka.location:arrow/RestrictedCont/attempt/#/PointingToDeclaration/-cont/arrow/-restricted-cont/attempt.html +$dokka.location:arrow/RestrictedCont/flatMap/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/flat-map.html +$dokka.location:arrow/RestrictedCont/fold/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/fold.html +$dokka.location:arrow/RestrictedCont/handleError/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/handle-error.html +$dokka.location:arrow/RestrictedCont/handleErrorWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/handle-error-with.html +$dokka.location:arrow/RestrictedCont/map/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/map.html +$dokka.location:arrow/RestrictedCont/redeem/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/redeem.html +$dokka.location:arrow/RestrictedCont/redeemWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/redeem-with.html +$dokka.location:arrow/RestrictedCont/toEither/#/PointingToDeclaration/-cont/arrow/-restricted-cont/to-either.html +$dokka.location:arrow/RestrictedCont/toValidated/#/PointingToDeclaration/-cont/arrow/-restricted-cont/to-validated.html +$dokka.location:arrow/RestrictedContEffect///PointingToDeclaration/-cont/arrow/-restricted-cont-effect/index.html +$dokka.location:arrow/RestrictedContEffect/bind/arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-restricted-cont-effect/bind.html +$dokka.location:arrow/RestrictedContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-restricted-cont-effect/shift.html +$dokka.location:arrow/ShiftCancellationException///PointingToDeclaration/-cont/arrow/-shift-cancellation-exception/index.html +arrow + diff --git a/docs/index.html b/docs/index.html index 5474bc43139..6b733854438 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,7 +1,7 @@ - Continuation + Cont
@@ -13,22 +13,34 @@
-
+
-

Continuation

+

Cont

+
  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensure(!path.isNullOrBlank()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

Packages

-
arrow +
arrow
Link copied to clipboard
diff --git a/docs/navigation.html b/docs/navigation.html index aaad0d5ee9e..337b751d7f5 100644 --- a/docs/navigation.html +++ b/docs/navigation.html @@ -1,54 +1,54 @@ -
- -
- -
- +
+ +
+ +
+
-
- +
+
-
- + -
- + -
- + -
- +
+
-
- + -
- + -
- + -
- + -
- + -
- + -
- + -
- + - diff --git a/docs/scripts/navigation-pane.json b/docs/scripts/navigation-pane.json index eb8af5b55c4..f734e4e721f 100644 --- a/docs/scripts/navigation-pane.json +++ b/docs/scripts/navigation-pane.json @@ -1 +1 @@ -[{"name":"Continuation","description":null,"location":"index.html","searchKeys":["Continuation"]},{"name":"arrow","description":null,"location":"-continuation/arrow/index.html","searchKeys":["arrow"]},{"name":"Cont","description":null,"location":"-continuation/arrow/-cont/index.html","searchKeys":["Cont"]},{"name":"cont()","description":null,"location":"-continuation/arrow/cont.html","searchKeys":["cont()"]},{"name":"ContEffect","description":null,"location":"-continuation/arrow/-cont-effect/index.html","searchKeys":["ContEffect"]},{"name":"either()","description":null,"location":"-continuation/arrow/either.html","searchKeys":["either()"]},{"name":"ensureNotNull()","description":null,"location":"-continuation/arrow/ensure-not-null.html","searchKeys":["ensureNotNull()"]},{"name":"ior()","description":null,"location":"-continuation/arrow/ior.html","searchKeys":["ior()"]},{"name":"IorEffect","description":null,"location":"-continuation/arrow/-ior-effect/index.html","searchKeys":["IorEffect"]},{"name":"option()","description":null,"location":"-continuation/arrow/option.html","searchKeys":["option()"]},{"name":"OptionEffect","description":null,"location":"-continuation/arrow/-option-effect/index.html","searchKeys":["OptionEffect"]},{"name":"RestrictedCont","description":null,"location":"-continuation/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont"]},{"name":"restrictedCont()","description":null,"location":"-continuation/arrow/restricted-cont.html","searchKeys":["restrictedCont()"]},{"name":"RestrictedContEffect","description":null,"location":"-continuation/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect"]},{"name":"sequence()","description":null,"location":"-continuation/arrow/sequence.html","searchKeys":["sequence()"]},{"name":"ShiftCancellationException","description":null,"location":"-continuation/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException"]},{"name":"toOption()","description":null,"location":"-continuation/arrow/to-option.html","searchKeys":["toOption()"]},{"name":"traverseCont()","description":null,"location":"-continuation/arrow/traverse-cont.html","searchKeys":["traverseCont()"]}] +[{"name":"Cont","description":null,"location":"index.html","searchKeys":["Cont"]},{"name":"arrow","description":null,"location":"-cont/arrow/index.html","searchKeys":["arrow"]},{"name":"Cont","description":null,"location":"-cont/arrow/-cont/index.html","searchKeys":["Cont"]},{"name":"cont()","description":null,"location":"-cont/arrow/cont.html","searchKeys":["cont()"]},{"name":"ContEffect","description":null,"location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect"]},{"name":"either()","description":null,"location":"-cont/arrow/either.html","searchKeys":["either()"]},{"name":"ensureNotNull()","description":null,"location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull()"]},{"name":"ior()","description":null,"location":"-cont/arrow/ior.html","searchKeys":["ior()"]},{"name":"IorEffect","description":null,"location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect"]},{"name":"option()","description":null,"location":"-cont/arrow/option.html","searchKeys":["option()"]},{"name":"OptionEffect","description":null,"location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect"]},{"name":"RestrictedCont","description":null,"location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont"]},{"name":"restrictedCont()","description":null,"location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont()"]},{"name":"RestrictedContEffect","description":null,"location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect"]},{"name":"sequence()","description":null,"location":"-cont/arrow/sequence.html","searchKeys":["sequence()"]},{"name":"ShiftCancellationException","description":null,"location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException"]},{"name":"toOption()","description":null,"location":"-cont/arrow/to-option.html","searchKeys":["toOption()"]},{"name":"traverseCont()","description":null,"location":"-cont/arrow/traverse-cont.html","searchKeys":["traverseCont()"]}] diff --git a/docs/scripts/pages.json b/docs/scripts/pages.json index 3c49d722411..446780cce5e 100644 --- a/docs/scripts/pages.json +++ b/docs/scripts/pages.json @@ -1 +1 @@ -[{"name":"abstract fun fold(f: (R) -> B, g: (A) -> B): B","description":"arrow.RestrictedCont.fold","location":"-continuation/arrow/-restricted-cont/fold.html","searchKeys":["fold","abstract fun fold(f: (R) -> B, g: (A) -> B): B","arrow.RestrictedCont.fold"]},{"name":"abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-continuation/arrow/-cont/fold.html","searchKeys":["fold","abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.ContEffect.shift","location":"-continuation/arrow/-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.ContEffect.shift"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.RestrictedContEffect.shift","location":"-continuation/arrow/-restricted-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.RestrictedContEffect.shift"]},{"name":"class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","description":"arrow.IorEffect","location":"-continuation/arrow/-ior-effect/index.html","searchKeys":["IorEffect","class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","arrow.IorEffect"]},{"name":"fun IorEffect(semigroup: Semigroup, cont: ContEffect)","description":"arrow.IorEffect.IorEffect","location":"-continuation/arrow/-ior-effect/-ior-effect.html","searchKeys":["IorEffect","fun IorEffect(semigroup: Semigroup, cont: ContEffect)","arrow.IorEffect.IorEffect"]},{"name":"fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","description":"arrow.traverseCont","location":"-continuation/arrow/traverse-cont.html","searchKeys":["traverseCont","fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","arrow.traverseCont"]},{"name":"fun Iterable>.sequence(): Cont>","description":"arrow.sequence","location":"-continuation/arrow/sequence.html","searchKeys":["sequence","fun Iterable>.sequence(): Cont>","arrow.sequence"]},{"name":"fun cont(f: suspend ContEffect.() -> A): Cont","description":"arrow.cont","location":"-continuation/arrow/cont.html","searchKeys":["cont","fun cont(f: suspend ContEffect.() -> A): Cont","arrow.cont"]},{"name":"fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","description":"arrow.restrictedCont","location":"-continuation/arrow/restricted-cont.html","searchKeys":["restrictedCont","fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","arrow.restrictedCont"]},{"name":"fun OptionEffect(cont: ContEffect)","description":"arrow.OptionEffect.OptionEffect","location":"-continuation/arrow/-option-effect/-option-effect.html","searchKeys":["OptionEffect","fun OptionEffect(cont: ContEffect)","arrow.OptionEffect.OptionEffect"]},{"name":"interface Cont","description":"arrow.Cont","location":"-continuation/arrow/-cont/index.html","searchKeys":["Cont","interface Cont","arrow.Cont"]},{"name":"interface ContEffect","description":"arrow.ContEffect","location":"-continuation/arrow/-cont-effect/index.html","searchKeys":["ContEffect","interface ContEffect","arrow.ContEffect"]},{"name":"interface RestrictedCont","description":"arrow.RestrictedCont","location":"-continuation/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont","interface RestrictedCont","arrow.RestrictedCont"]},{"name":"interface RestrictedContEffect","description":"arrow.RestrictedContEffect","location":"-continuation/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect","interface RestrictedContEffect","arrow.RestrictedContEffect"]},{"name":"open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.flatMap","location":"-continuation/arrow/-restricted-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.flatMap"]},{"name":"open fun flatMap(transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.flatMap","location":"-continuation/arrow/-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(transform: suspend (A) -> Cont): Cont","arrow.Cont.flatMap"]},{"name":"open fun map(f: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.map","location":"-continuation/arrow/-restricted-cont/map.html","searchKeys":["map","open fun map(f: (A) -> B): RestrictedCont","arrow.RestrictedCont.map"]},{"name":"open fun map(transform: suspend (A) -> B): Cont","description":"arrow.Cont.map","location":"-continuation/arrow/-cont/map.html","searchKeys":["map","open fun map(transform: suspend (A) -> B): Cont","arrow.Cont.map"]},{"name":"open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.redeem","location":"-continuation/arrow/-restricted-cont/redeem.html","searchKeys":["redeem","open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","arrow.RestrictedCont.redeem"]},{"name":"open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","description":"arrow.Cont.redeem","location":"-continuation/arrow/-cont/redeem.html","searchKeys":["redeem","open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","arrow.Cont.redeem"]},{"name":"open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.redeemWith","location":"-continuation/arrow/-restricted-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.redeemWith"]},{"name":"open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.redeemWith","location":"-continuation/arrow/-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","arrow.Cont.redeemWith"]},{"name":"open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.handleErrorWith","location":"-continuation/arrow/-restricted-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.handleErrorWith"]},{"name":"open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","description":"arrow.Cont.handleErrorWith","location":"-continuation/arrow/-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","arrow.Cont.handleErrorWith"]},{"name":"open fun attempt(): Cont>","description":"arrow.Cont.attempt","location":"-continuation/arrow/-cont/attempt.html","searchKeys":["attempt","open fun attempt(): Cont>","arrow.Cont.attempt"]},{"name":"open fun attempt(): RestrictedCont>","description":"arrow.RestrictedCont.attempt","location":"-continuation/arrow/-restricted-cont/attempt.html","searchKeys":["attempt","open fun attempt(): RestrictedCont>","arrow.RestrictedCont.attempt"]},{"name":"open fun handleError(f: (R) -> A): RestrictedCont","description":"arrow.RestrictedCont.handleError","location":"-continuation/arrow/-restricted-cont/handle-error.html","searchKeys":["handleError","open fun handleError(f: (R) -> A): RestrictedCont","arrow.RestrictedCont.handleError"]},{"name":"open fun handleError(recover: suspend (R) -> A): Cont","description":"arrow.Cont.handleError","location":"-continuation/arrow/-cont/handle-error.html","searchKeys":["handleError","open fun handleError(recover: suspend (R) -> A): Cont","arrow.Cont.handleError"]},{"name":"open fun toEither(): Either","description":"arrow.RestrictedCont.toEither","location":"-continuation/arrow/-restricted-cont/to-either.html","searchKeys":["toEither","open fun toEither(): Either","arrow.RestrictedCont.toEither"]},{"name":"open fun toValidated(): Validated","description":"arrow.RestrictedCont.toValidated","location":"-continuation/arrow/-restricted-cont/to-validated.html","searchKeys":["toValidated","open fun toValidated(): Validated","arrow.RestrictedCont.toValidated"]},{"name":"open suspend fun RestrictedCont.bind(): A","description":"arrow.RestrictedContEffect.bind","location":"-continuation/arrow/-restricted-cont-effect/bind.html","searchKeys":["bind","open suspend fun RestrictedCont.bind(): A","arrow.RestrictedContEffect.bind"]},{"name":"open suspend fun Cont.bind(): B","description":"arrow.ContEffect.bind","location":"-continuation/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Cont.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Either.bind(): B","description":"arrow.ContEffect.bind","location":"-continuation/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Either.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Option.bind(shift: () -> R): B","description":"arrow.ContEffect.bind","location":"-continuation/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Option.bind(shift: () -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Result.bind(transform: (Throwable) -> R): B","description":"arrow.ContEffect.bind","location":"-continuation/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Result.bind(transform: (Throwable) -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Validated.bind(): B","description":"arrow.ContEffect.bind","location":"-continuation/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Validated.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-continuation/arrow/-cont/fold.html","searchKeys":["fold","open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"open suspend fun ensure(value: Boolean, shift: () -> R)","description":"arrow.ContEffect.ensure","location":"-continuation/arrow/-cont-effect/ensure.html","searchKeys":["ensure","open suspend fun ensure(value: Boolean, shift: () -> R)","arrow.ContEffect.ensure"]},{"name":"open suspend fun toEither(): Either","description":"arrow.Cont.toEither","location":"-continuation/arrow/-cont/to-either.html","searchKeys":["toEither","open suspend fun toEither(): Either","arrow.Cont.toEither"]},{"name":"open suspend fun toIor(): Ior","description":"arrow.Cont.toIor","location":"-continuation/arrow/-cont/to-ior.html","searchKeys":["toIor","open suspend fun toIor(): Ior","arrow.Cont.toIor"]},{"name":"open suspend fun toOption(orElse: suspend (R) -> Option): Option","description":"arrow.Cont.toOption","location":"-continuation/arrow/-cont/to-option.html","searchKeys":["toOption","open suspend fun toOption(orElse: suspend (R) -> Option): Option","arrow.Cont.toOption"]},{"name":"open suspend fun toValidated(): Validated","description":"arrow.Cont.toValidated","location":"-continuation/arrow/-cont/to-validated.html","searchKeys":["toValidated","open suspend fun toValidated(): Validated","arrow.Cont.toValidated"]},{"name":"open suspend override fun shift(r: E): B","description":"arrow.IorEffect.shift","location":"-continuation/arrow/-ior-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: E): B","arrow.IorEffect.shift"]},{"name":"open suspend override fun shift(r: None): B","description":"arrow.OptionEffect.shift","location":"-continuation/arrow/-option-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: None): B","arrow.OptionEffect.shift"]},{"name":"sealed class ShiftCancellationException : CancellationException","description":"arrow.ShiftCancellationException","location":"-continuation/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException","sealed class ShiftCancellationException : CancellationException","arrow.ShiftCancellationException"]},{"name":"suspend fun Cont.toOption(): Option","description":"arrow.toOption","location":"-continuation/arrow/to-option.html","searchKeys":["toOption","suspend fun Cont.toOption(): Option","arrow.toOption"]},{"name":"suspend fun option(f: OptionEffect.() -> A): Option","description":"arrow.option","location":"-continuation/arrow/option.html","searchKeys":["option","suspend fun option(f: OptionEffect.() -> A): Option","arrow.option"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?): B","description":"arrow.ensureNotNull","location":"-continuation/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?): B","arrow.ensureNotNull"]},{"name":"suspend fun Ior.bind(): B","description":"arrow.IorEffect.bind","location":"-continuation/arrow/-ior-effect/bind.html","searchKeys":["bind","suspend fun Ior.bind(): B","arrow.IorEffect.bind"]},{"name":"suspend fun Option.bind(): B","description":"arrow.OptionEffect.bind","location":"-continuation/arrow/-option-effect/bind.html","searchKeys":["bind","suspend fun Option.bind(): B","arrow.OptionEffect.bind"]},{"name":"suspend fun either(f: suspend ContEffect.() -> A): Either","description":"arrow.either","location":"-continuation/arrow/either.html","searchKeys":["either","suspend fun either(f: suspend ContEffect.() -> A): Either","arrow.either"]},{"name":"suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","description":"arrow.ior","location":"-continuation/arrow/ior.html","searchKeys":["ior","suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","arrow.ior"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","description":"arrow.ensureNotNull","location":"-continuation/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","arrow.ensureNotNull"]},{"name":"suspend fun ensure(value: Boolean)","description":"arrow.OptionEffect.ensure","location":"-continuation/arrow/-option-effect/ensure.html","searchKeys":["ensure","suspend fun ensure(value: Boolean)","arrow.OptionEffect.ensure"]},{"name":"value class OptionEffect(cont: ContEffect) : ContEffect ","description":"arrow.OptionEffect","location":"-continuation/arrow/-option-effect/index.html","searchKeys":["OptionEffect","value class OptionEffect(cont: ContEffect) : ContEffect ","arrow.OptionEffect"]}] +[{"name":"abstract fun fold(f: (R) -> B, g: (A) -> B): B","description":"arrow.RestrictedCont.fold","location":"-cont/arrow/-restricted-cont/fold.html","searchKeys":["fold","abstract fun fold(f: (R) -> B, g: (A) -> B): B","arrow.RestrictedCont.fold"]},{"name":"abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.ContEffect.shift","location":"-cont/arrow/-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.ContEffect.shift"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.RestrictedContEffect.shift","location":"-cont/arrow/-restricted-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.RestrictedContEffect.shift"]},{"name":"class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","description":"arrow.IorEffect","location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect","class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","arrow.IorEffect"]},{"name":"fun IorEffect(semigroup: Semigroup, cont: ContEffect)","description":"arrow.IorEffect.IorEffect","location":"-cont/arrow/-ior-effect/-ior-effect.html","searchKeys":["IorEffect","fun IorEffect(semigroup: Semigroup, cont: ContEffect)","arrow.IorEffect.IorEffect"]},{"name":"fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","description":"arrow.traverseCont","location":"-cont/arrow/traverse-cont.html","searchKeys":["traverseCont","fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","arrow.traverseCont"]},{"name":"fun Iterable>.sequence(): Cont>","description":"arrow.sequence","location":"-cont/arrow/sequence.html","searchKeys":["sequence","fun Iterable>.sequence(): Cont>","arrow.sequence"]},{"name":"fun cont(f: suspend ContEffect.() -> A): Cont","description":"arrow.cont","location":"-cont/arrow/cont.html","searchKeys":["cont","fun cont(f: suspend ContEffect.() -> A): Cont","arrow.cont"]},{"name":"fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","description":"arrow.restrictedCont","location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont","fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","arrow.restrictedCont"]},{"name":"fun OptionEffect(cont: ContEffect)","description":"arrow.OptionEffect.OptionEffect","location":"-cont/arrow/-option-effect/-option-effect.html","searchKeys":["OptionEffect","fun OptionEffect(cont: ContEffect)","arrow.OptionEffect.OptionEffect"]},{"name":"interface Cont","description":"arrow.Cont","location":"-cont/arrow/-cont/index.html","searchKeys":["Cont","interface Cont","arrow.Cont"]},{"name":"interface ContEffect","description":"arrow.ContEffect","location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect","interface ContEffect","arrow.ContEffect"]},{"name":"interface RestrictedCont","description":"arrow.RestrictedCont","location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont","interface RestrictedCont","arrow.RestrictedCont"]},{"name":"interface RestrictedContEffect","description":"arrow.RestrictedContEffect","location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect","interface RestrictedContEffect","arrow.RestrictedContEffect"]},{"name":"open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.flatMap","location":"-cont/arrow/-restricted-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.flatMap"]},{"name":"open fun flatMap(transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.flatMap","location":"-cont/arrow/-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(transform: suspend (A) -> Cont): Cont","arrow.Cont.flatMap"]},{"name":"open fun map(f: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.map","location":"-cont/arrow/-restricted-cont/map.html","searchKeys":["map","open fun map(f: (A) -> B): RestrictedCont","arrow.RestrictedCont.map"]},{"name":"open fun map(transform: suspend (A) -> B): Cont","description":"arrow.Cont.map","location":"-cont/arrow/-cont/map.html","searchKeys":["map","open fun map(transform: suspend (A) -> B): Cont","arrow.Cont.map"]},{"name":"open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.redeem","location":"-cont/arrow/-restricted-cont/redeem.html","searchKeys":["redeem","open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","arrow.RestrictedCont.redeem"]},{"name":"open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","description":"arrow.Cont.redeem","location":"-cont/arrow/-cont/redeem.html","searchKeys":["redeem","open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","arrow.Cont.redeem"]},{"name":"open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.redeemWith","location":"-cont/arrow/-restricted-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.redeemWith"]},{"name":"open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.redeemWith","location":"-cont/arrow/-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","arrow.Cont.redeemWith"]},{"name":"open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.handleErrorWith","location":"-cont/arrow/-restricted-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.handleErrorWith"]},{"name":"open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","description":"arrow.Cont.handleErrorWith","location":"-cont/arrow/-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","arrow.Cont.handleErrorWith"]},{"name":"open fun attempt(): Cont>","description":"arrow.Cont.attempt","location":"-cont/arrow/-cont/attempt.html","searchKeys":["attempt","open fun attempt(): Cont>","arrow.Cont.attempt"]},{"name":"open fun attempt(): RestrictedCont>","description":"arrow.RestrictedCont.attempt","location":"-cont/arrow/-restricted-cont/attempt.html","searchKeys":["attempt","open fun attempt(): RestrictedCont>","arrow.RestrictedCont.attempt"]},{"name":"open fun handleError(f: (R) -> A): RestrictedCont","description":"arrow.RestrictedCont.handleError","location":"-cont/arrow/-restricted-cont/handle-error.html","searchKeys":["handleError","open fun handleError(f: (R) -> A): RestrictedCont","arrow.RestrictedCont.handleError"]},{"name":"open fun handleError(recover: suspend (R) -> A): Cont","description":"arrow.Cont.handleError","location":"-cont/arrow/-cont/handle-error.html","searchKeys":["handleError","open fun handleError(recover: suspend (R) -> A): Cont","arrow.Cont.handleError"]},{"name":"open fun toEither(): Either","description":"arrow.RestrictedCont.toEither","location":"-cont/arrow/-restricted-cont/to-either.html","searchKeys":["toEither","open fun toEither(): Either","arrow.RestrictedCont.toEither"]},{"name":"open fun toValidated(): Validated","description":"arrow.RestrictedCont.toValidated","location":"-cont/arrow/-restricted-cont/to-validated.html","searchKeys":["toValidated","open fun toValidated(): Validated","arrow.RestrictedCont.toValidated"]},{"name":"open suspend fun RestrictedCont.bind(): A","description":"arrow.RestrictedContEffect.bind","location":"-cont/arrow/-restricted-cont-effect/bind.html","searchKeys":["bind","open suspend fun RestrictedCont.bind(): A","arrow.RestrictedContEffect.bind"]},{"name":"open suspend fun Cont.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Cont.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Either.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Either.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Option.bind(shift: () -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Option.bind(shift: () -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Result.bind(transform: (Throwable) -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Result.bind(transform: (Throwable) -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Validated.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Validated.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"open suspend fun ensure(value: Boolean, shift: () -> R)","description":"arrow.ContEffect.ensure","location":"-cont/arrow/-cont-effect/ensure.html","searchKeys":["ensure","open suspend fun ensure(value: Boolean, shift: () -> R)","arrow.ContEffect.ensure"]},{"name":"open suspend fun toEither(): Either","description":"arrow.Cont.toEither","location":"-cont/arrow/-cont/to-either.html","searchKeys":["toEither","open suspend fun toEither(): Either","arrow.Cont.toEither"]},{"name":"open suspend fun toIor(): Ior","description":"arrow.Cont.toIor","location":"-cont/arrow/-cont/to-ior.html","searchKeys":["toIor","open suspend fun toIor(): Ior","arrow.Cont.toIor"]},{"name":"open suspend fun toOption(orElse: suspend (R) -> Option): Option","description":"arrow.Cont.toOption","location":"-cont/arrow/-cont/to-option.html","searchKeys":["toOption","open suspend fun toOption(orElse: suspend (R) -> Option): Option","arrow.Cont.toOption"]},{"name":"open suspend fun toValidated(): Validated","description":"arrow.Cont.toValidated","location":"-cont/arrow/-cont/to-validated.html","searchKeys":["toValidated","open suspend fun toValidated(): Validated","arrow.Cont.toValidated"]},{"name":"open suspend override fun shift(r: E): B","description":"arrow.IorEffect.shift","location":"-cont/arrow/-ior-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: E): B","arrow.IorEffect.shift"]},{"name":"open suspend override fun shift(r: None): B","description":"arrow.OptionEffect.shift","location":"-cont/arrow/-option-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: None): B","arrow.OptionEffect.shift"]},{"name":"sealed class ShiftCancellationException : CancellationException","description":"arrow.ShiftCancellationException","location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException","sealed class ShiftCancellationException : CancellationException","arrow.ShiftCancellationException"]},{"name":"suspend fun Cont.toOption(): Option","description":"arrow.toOption","location":"-cont/arrow/to-option.html","searchKeys":["toOption","suspend fun Cont.toOption(): Option","arrow.toOption"]},{"name":"suspend fun option(f: OptionEffect.() -> A): Option","description":"arrow.option","location":"-cont/arrow/option.html","searchKeys":["option","suspend fun option(f: OptionEffect.() -> A): Option","arrow.option"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?): B","arrow.ensureNotNull"]},{"name":"suspend fun Ior.bind(): B","description":"arrow.IorEffect.bind","location":"-cont/arrow/-ior-effect/bind.html","searchKeys":["bind","suspend fun Ior.bind(): B","arrow.IorEffect.bind"]},{"name":"suspend fun Option.bind(): B","description":"arrow.OptionEffect.bind","location":"-cont/arrow/-option-effect/bind.html","searchKeys":["bind","suspend fun Option.bind(): B","arrow.OptionEffect.bind"]},{"name":"suspend fun either(f: suspend ContEffect.() -> A): Either","description":"arrow.either","location":"-cont/arrow/either.html","searchKeys":["either","suspend fun either(f: suspend ContEffect.() -> A): Either","arrow.either"]},{"name":"suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","description":"arrow.ior","location":"-cont/arrow/ior.html","searchKeys":["ior","suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","arrow.ior"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","arrow.ensureNotNull"]},{"name":"suspend fun ensure(value: Boolean)","description":"arrow.OptionEffect.ensure","location":"-cont/arrow/-option-effect/ensure.html","searchKeys":["ensure","suspend fun ensure(value: Boolean)","arrow.OptionEffect.ensure"]},{"name":"value class OptionEffect(cont: ContEffect) : ContEffect ","description":"arrow.OptionEffect","location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect","value class OptionEffect(cont: ContEffect) : ContEffect ","arrow.OptionEffect"]}] From b8abf3b3524719354f1152508625c7c384b423e1 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 22:39:08 +0100 Subject: [PATCH 030/108] Update build to MPP --- .github/workflows/build.yaml | 75 ++-- .github/workflows/pr.yaml | 2 +- libs.versions.toml | 40 ++ src/commonMain/kotlin/arrow/Cont.kt | 204 +++++----- src/commonMain/kotlin/arrow/RestrictedCont.kt | 81 ++-- src/commonMain/kotlin/arrow/either.kt | 4 +- .../kotlin/arrow/internal/EmptyValue.kt | 3 +- src/commonMain/kotlin/arrow/ior.kt | 31 +- src/commonMain/kotlin/arrow/option.kt | 20 +- src/jvmTest/kotlin/arrow/ContSpec.kt | 336 ++++++++-------- src/jvmTest/kotlin/arrow/IorSpec.kt | 48 +-- .../kotlin/arrow/StructuredConcurrencySpec.kt | 367 +++++++++--------- src/jvmTest/kotlin/arrow/predef.kt | 6 +- 13 files changed, 602 insertions(+), 615 deletions(-) create mode 100644 libs.versions.toml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 53c37586c1c..0cd458fae0e 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -15,15 +15,15 @@ env: GRADLE_OPTS: "-Dorg.gradle.daemon=false -Dorg.gradle.configureondemand=true -Dorg.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8" jobs: - - linux_jvm_and_js: - runs-on: ubuntu-latest - timeout-minutes: 25 - + check: + strategy: + matrix: + os: [ windows-latest, ubuntu-latest ] + runs-on: ${{matrix.os}} + timeout-minutes: 20 steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 + - name: Checkout the repo + uses: actions/checkout@v2 - name: Restore Gradle cache id: cache @@ -32,48 +32,27 @@ jobs: path: | ~/.gradle/caches ~/.gradle/wrapper + ~/.gradle/yarn + ~/.gradle/nodejs ~/.konan - key: linux-step-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - linux-step-gradle- + key: ${{ runner.os }}-check-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-check- - - name: Build + - name: Run Ubuntu tests + if: matrix.os == 'ubuntu-latest' run: ./gradlew check - - name: "Prepare test reports" - if: ${{ always() }} - run: | - mkdir test-reports - for report in `ls -d build/reports/tests`; do - module=$(echo $report | cut -d/ -f3) - cp -r $report test-reports/$module - done - - name: "Make test reports available to download" - if: ${{ always() }} - uses: actions/upload-artifact@v2 - with: - name: test-reports - path: test-reports + - name: Run Windows tests + if: matrix.os == 'windows-latest' + run: ./gradlew mingwX64Test + + - name: Bundle the build report + if: failure() + run: find . -type d -name 'reports' | zip -@ -r build-reports.zip -# windows: -# runs-on: windows-latest -# timeout-minutes: 20 -# -# steps: -# - uses: actions/checkout@v2 -# with: -# fetch-depth: 0 -# -# - name: Restore Gradle cache -# id: cache -# uses: actions/cache@v2.1.6 -# with: -# path: | -# ~/.gradle/caches -# ~/.gradle/wrapper -# ~/.konan -# key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} -# restore-keys: | -# ${{ runner.os }}-gradle- -# - name: Build -# run: ./gradlew mingwX64Test + - name: Upload the build report + if: failure() + uses: actions/upload-artifact@master + with: + name: error-report + path: build-reports.zip \ No newline at end of file diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index b52a5cb4709..3c1a06fe770 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -14,7 +14,7 @@ jobs: check: strategy: matrix: - os: [ ubuntu-latest ] + os: [ windows-latest, ubuntu-latest ] runs-on: ${{matrix.os}} timeout-minutes: 20 steps: diff --git a/libs.versions.toml b/libs.versions.toml new file mode 100644 index 00000000000..3a31f768c21 --- /dev/null +++ b/libs.versions.toml @@ -0,0 +1,40 @@ +[versions] +arrow = "1.0.1" +arrowGradleConfig = "0.5.1" +coroutines = "1.5.2" +dokka = "1.5.31" +kotest = "5.0.0.M3" +kotestGradle = "5.0.0.5" +kotlin = "1.5.31" +kotlinBinaryCompatibilityValidator = "0.8.0" +githooks = "0.0.2" +knit = "0.2.3" + +[libraries] +arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } +arrow-optics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } +arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" } +coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } +coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } +dokka-core = { module = "org.jetbrains.dokka:dokka-core", version.ref = "dokka" } +kotest-assertionsCore = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" } +kotest-frameworkEngine = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" } +kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" } +kotest-runnerJUnit5 = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" } +kotlin-stdlibCommon = { module = "org.jetbrains.kotlin:kotlin-stdlib-common" } +kotlin-stdlibJDK8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } +kotlin-stdlibJS = { module = "org.jetbrains.kotlin:kotlin-stdlib-js" } +kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit" } +knit-test = { module = "org.jetbrains.kotlinx:kotlinx-knit-test", version.ref = "knit" } + +[plugins] +arrowGradleConfig-formatter = { id = "io.arrow-kt.arrow-gradle-config-formatter", version.ref = "arrowGradleConfig" } +arrowGradleConfig-multiplatform = { id = "io.arrow-kt.arrow-gradle-config-multiplatform", version.ref = "arrowGradleConfig" } +arrowGradleConfig-nexus = { id = "io.arrow-kt.arrow-gradle-config-nexus", version.ref = "arrowGradleConfig" } +arrowGradleConfig-publishMultiplatform = { id = "io.arrow-kt.arrow-gradle-config-publish-multiplatform", version.ref = "arrowGradleConfig" } +dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } +kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotestGradle" } +kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +kotlin-binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "kotlinBinaryCompatibilityValidator" } +githooks = { id = "com.github.jakemarsden.git-hooks", version.ref = "githooks" } +knit = { id = "org.jetbrains.kotlinx:kotlinx-knit", version.ref = "knit" } \ No newline at end of file diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index 988295873d2..579028804e3 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -1,15 +1,15 @@ package arrow import arrow.core.Either -import arrow.core.NonFatal -import kotlin.Result import arrow.core.Ior +import arrow.core.NonFatal import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.Validated import arrow.core.identity import arrow.core.nonFatalOrThrow +import kotlin.Result import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation @@ -53,23 +53,22 @@ import kotlin.jvm.JvmInline * ``` * */ -public fun cont(f: suspend ContEffect.() -> A): Cont = - ContImpl(f) +public fun cont(f: suspend ContEffect.() -> A): Cont = ContImpl(f) /** * [Cont] represents a suspending computation that runs will either - * - Complete with a value of [A]. - * - Short-circuit with a value of [R]. + * - Complete with a value of [A]. + * - Short-circuit with a value of [R]. * * So [Cont] is defined by [fold], to map both values of [R] and [A] to a value of `B`. */ public interface Cont { /** - * Runs the suspending computation by creating a [Continuation], - * and running the `fold` function over the computation. + * Runs the suspending computation by creating a [Continuation], and running the `fold` function + * over the computation. * - * When the [Cont] has shifted with [R] it will [recover] the shifted value to [B], - * and when it ran the computation to completion it will [transform] the value [A] to [B]. + * When the [Cont] has shifted with [R] it will [recover] the shifted value to [B], and when it + * ran the computation to completion it will [transform] the value [A] to [B]. * * ```kotlin * import arrow.cont @@ -94,100 +93,102 @@ public interface Cont { * ``` * */ - suspend fun fold(recover: suspend (shifted: R) -> B, transform: suspend (value: A) -> B): B + public suspend fun fold( + recover: suspend (shifted: R) -> B, + transform: suspend (value: A) -> B + ): B /** * Like `fold` but also allows folding over any unexpected [Throwable] that might have occurred. * @see fold */ - suspend fun fold( + public suspend fun fold( error: suspend (error: Throwable) -> B, recover: suspend (shifted: R) -> B, transform: suspend (value: A) -> B - ): B = try { - fold(recover, transform) - } catch (e: Throwable) { - error(e.nonFatalOrThrow()) - } + ): B = + try { + fold(recover, transform) + } catch (e: Throwable) { + error(e.nonFatalOrThrow()) + } /** - * [fold] the [Cont] into an [Either]. - * Where the shifted value [R] is mapped to [Either.Left], - * and result value [A] is mapped to [Either.Right]. + * [fold] the [Cont] into an [Either]. Where the shifted value [R] is mapped to [Either.Left], and + * result value [A] is mapped to [Either.Right]. */ - suspend fun toEither(): Either = - fold({ Either.Left(it) }) { Either.Right(it) } + public suspend fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } /** - * [fold] the [Cont] into an [Ior]. - * Where the shifted value [R] is mapped to [Ior.Left], - * and result value [A] is mapped to [Ior.Right]. + * [fold] the [Cont] into an [Ior]. Where the shifted value [R] is mapped to [Ior.Left], and + * result value [A] is mapped to [Ior.Right]. */ - suspend fun toIor(): Ior = - fold({ Ior.Left(it) }) { Ior.Right(it) } + public suspend fun toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } /** - * [fold] the [Cont] into an [Validated]. - * Where the shifted value [R] is mapped to [Validated.Invalid], - * and result value [A] is mapped to [Validated.Valid]. + * [fold] the [Cont] into an [Validated]. Where the shifted value [R] is mapped to + * [Validated.Invalid], and result value [A] is mapped to [Validated.Valid]. */ - suspend fun toValidated(): Validated = + public suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } /** - * [fold] the [Cont] into an [Option]. - * Where the shifted value [R] is mapped to [Option] by the provided function [orElse], - * and result value [A] is mapped to [Some]. + * [fold] the [Cont] into an [Option]. Where the shifted value [R] is mapped to [Option] by the + * provided function [orElse], and result value [A] is mapped to [Some]. */ - suspend fun toOption(orElse: suspend (R) -> Option): Option = - fold(orElse, ::Some) + public suspend fun toOption(orElse: suspend (R) -> Option): Option = fold(orElse, ::Some) /** Runs the [Cont] and captures any [NonFatal] exception into [Result]. */ - fun attempt(): Cont> = - cont { - try { - Result.success(bind()) - } catch (e: Throwable) { - Result.failure(e.nonFatalOrThrow()) - } + public fun attempt(): Cont> = cont { + try { + Result.success(bind()) + } catch (e: Throwable) { + Result.failure(e.nonFatalOrThrow()) } + } /** Maps the values [A] with the [transform] function into [B]. */ - fun map(transform: suspend (A) -> B): Cont = - cont { fold(this::shift, transform) } + public fun map(transform: suspend (A) -> B): Cont = cont { + fold(this::shift, transform) + } /** Maps the values [A] with the [transform] function into another [Cont] effect. */ - fun flatMap(transform: suspend (A) -> Cont): Cont = - cont { fold(this::shift, transform).bind() } + public fun flatMap(transform: suspend (A) -> Cont): Cont = cont { + fold(this::shift, transform).bind() + } - fun handleError(recover: suspend (R) -> A): Cont = - cont { fold(recover, ::identity) } + public fun handleError(recover: suspend (R) -> A): Cont = cont { + fold(recover, ::identity) + } - fun handleErrorWith(recover: suspend (R) -> Cont): Cont = - cont { fold({ recover(it).bind() }, ::identity) } + public fun handleErrorWith(recover: suspend (R) -> Cont): Cont = cont { + fold({ recover(it).bind() }, ::identity) + } - fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont = - cont { fold(recover, transform) } + public fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont = + cont { + fold(recover, transform) + } - fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont = - cont { fold(recover, transform).bind() } + public fun redeemWith( + recover: suspend (R) -> Cont, + transform: suspend (A) -> Cont + ): Cont = cont { fold(recover, transform).bind() } } -fun Iterable.traverseCont(transform: (A) -> Cont): Cont> = - cont { map { transform(it).bind() } } +public fun Iterable.traverseCont(transform: (A) -> Cont): Cont> = + cont { + map { transform(it).bind() } +} -fun Iterable>.sequence(): Cont> = - traverseCont(::identity) +public fun Iterable>.sequence(): Cont> = traverseCont(::identity) /** Context of the [Cont] DSL. */ -interface ContEffect { - /** - * Short-circuit the [Cont] computation with value [R]. - */ +public interface ContEffect { + /** Short-circuit the [Cont] computation with value [R]. */ public suspend fun shift(r: R): B - public suspend fun Cont.bind(): B = - fold(this@ContEffect::shift, ::identity) + public suspend fun Cont.bind(): B = fold(this@ContEffect::shift, ::identity) public suspend fun Either.bind(): B = when (this) { @@ -202,9 +203,7 @@ interface ContEffect { } public suspend fun Result.bind(transform: (Throwable) -> R): B = - fold(::identity) { throwable -> - shift(transform(throwable)) - } + fold(::identity) { throwable -> shift(transform(throwable)) } public suspend fun Option.bind(shift: () -> R): B = when (this) { @@ -217,7 +216,6 @@ interface ContEffect { if (value) Unit else shift(shift()) } - // Monadic version of kotlin.requireNotNull @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so top-level. public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { @@ -225,12 +223,10 @@ public suspend fun ContEffect.ensureNotNull(value: B?, shift: () return value ?: shift(shift()) } -sealed class ShiftCancellationException : CancellationException("Shifted Continuation") -private class Internal( - val token: Token, - val shifted: Any?, - val fold: suspend (Any?) -> Any? -): ShiftCancellationException() { +public sealed class ShiftCancellationException : CancellationException("Shifted Continuation") + +private class Internal(val token: Token, val shifted: Any?, val fold: suspend (Any?) -> Any?) : + ShiftCancellationException() { override fun toString(): String = "ShiftCancellationException($message)" } @@ -243,45 +239,51 @@ private class Token { private value class ContImpl(private val f: suspend ContEffect.() -> A) : Cont { override fun attempt(): Cont> = ContImpl { - try { - Result.success(f()) - } catch (e: Throwable) { - Result.failure(e.nonFatalOrThrow()) - } + try { + Result.success(f()) + } catch (e: Throwable) { + Result.failure(e.nonFatalOrThrow()) } + } - override fun map(transform: suspend (A) -> B): Cont = - ContImpl { transform(f()) } + override fun map(transform: suspend (A) -> B): Cont = ContImpl { transform(f()) } - override fun flatMap(transform: suspend (A) -> Cont): Cont = - ContImpl { transform(f()).bind() } + override fun flatMap(transform: suspend (A) -> Cont): Cont = ContImpl { + transform(f()).bind() + } - // We create a `Token` for fold Continuation, so we can properly differentiate between nested folds + // We create a `Token` for fold Continuation, so we can properly differentiate between nested + // folds override suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B = - suspendCoroutineUninterceptedOrReturn { cont -> - val token = Token() - val effect = object : ContEffect { - // Shift away from this Continuation by intercepting it, and completing it with ShiftCancellationException + suspendCoroutineUninterceptedOrReturn { cont -> + val token = Token() + val effect = + object : ContEffect { + // Shift away from this Continuation by intercepting it, and completing it with + // ShiftCancellationException // This is needed because this function will never yield a result, // so it needs to be cancelled to properly support coroutine cancellation override suspend fun shift(r: R): B = - // Some interesting consequences of how Continuation Cancellation works in Kotlin. - // We have to throw CancellationException to signal the Continuation was cancelled, and we shifted away. - // This however also means that the user can try/catch shift and recover from the CancellationException and thus effectively recovering from the cancellation/shift. - // This means try/catch is also capable of recovering from monadic errors. + // Some interesting consequences of how Continuation Cancellation works in Kotlin. + // We have to throw CancellationException to signal the Continuation was cancelled, and we + // shifted away. + // This however also means that the user can try/catch shift and recover from the + // CancellationException and thus effectively recovering from the cancellation/shift. + // This means try/catch is also capable of recovering from monadic errors. // See: ContSpec - try/catch tests throw Internal(token, r, recover as suspend (Any?) -> Any?) } - try { - suspend { transform(f(effect)) }.startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) - } catch (e: Internal) { - if (token == e.token) { - val f: suspend () -> B = { e.fold(e.shifted) as B } - f.startCoroutineUninterceptedOrReturn(cont) - } else throw e - } + try { + suspend { transform(f(effect)) } + .startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) + } catch (e: Internal) { + if (token == e.token) { + val f: suspend () -> B = { e.fold(e.shifted) as B } + f.startCoroutineUninterceptedOrReturn(cont) + } else throw e } + } } private class FoldContinuation( diff --git a/src/commonMain/kotlin/arrow/RestrictedCont.kt b/src/commonMain/kotlin/arrow/RestrictedCont.kt index 45731050e87..0b6dc6f27b3 100644 --- a/src/commonMain/kotlin/arrow/RestrictedCont.kt +++ b/src/commonMain/kotlin/arrow/RestrictedCont.kt @@ -13,8 +13,8 @@ import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.jvm.JvmInline /** - * `RestrictsSuspension` version of `Cont`. - * This version runs eagerly, can can be used in non-suspending code. + * `RestrictsSuspension` version of `Cont`. This version runs eagerly, can can be used in + * non-suspending code. */ public fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont = RestrictedContDsl(f) @@ -22,80 +22,75 @@ public fun restrictedCont(f: suspend RestrictedContEffect.() -> A): Re @RestrictsSuspension public interface RestrictedContEffect { - /** - * Short-circuit the [Cont] computation with value [R]. - */ + /** Short-circuit the [Cont] computation with value [R]. */ public suspend fun shift(r: R): B public suspend fun RestrictedCont.bind(): A { var left: Any? = EmptyValue var right: Any? = EmptyValue - fold({ r -> - left = r - }, { a -> - right = a - }) - return if (left === EmptyValue) EmptyValue.unbox(right) - else shift(EmptyValue.unbox(left)) + fold({ r -> left = r }, { a -> right = a }) + return if (left === EmptyValue) EmptyValue.unbox(right) else shift(EmptyValue.unbox(left)) } } public interface RestrictedCont { public fun fold(f: (R) -> B, g: (A) -> B): B - public fun toEither(): Either = - fold({ Either.Left(it) }) { Either.Right(it) } + public fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } public fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } - public fun map(f: (A) -> B): RestrictedCont = - flatMap { a -> - restrictedCont { f(a) } - } + public fun map(f: (A) -> B): RestrictedCont = flatMap { a -> restrictedCont { f(a) } } - public fun flatMap(f: (A) -> RestrictedCont): RestrictedCont = - restrictedCont { f(bind()).bind() } + public fun flatMap(f: (A) -> RestrictedCont): RestrictedCont = restrictedCont { + f(bind()).bind() + } - public fun attempt(): RestrictedCont> = - restrictedCont { kotlin.runCatching { bind() } } + public fun attempt(): RestrictedCont> = restrictedCont { + kotlin.runCatching { bind() } + } - public fun handleError(f: (R) -> A): RestrictedCont = - restrictedCont { fold(f, ::identity) } + public fun handleError(f: (R) -> A): RestrictedCont = restrictedCont { + fold(f, ::identity) + } public fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont = - restrictedCont { - toEither().fold({ r -> - f(r).bind() - }, ::identity) - } + restrictedCont { + toEither().fold({ r -> f(r).bind() }, ::identity) + } - public fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont = - restrictedCont { fold(f, g) } + public fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont = restrictedCont { + fold(f, g) + } public fun redeemWith( f: (R) -> RestrictedCont, g: (A) -> RestrictedCont - ): RestrictedCont = - restrictedCont { fold(f, g).bind() } + ): RestrictedCont = restrictedCont { fold(f, g).bind() } } @JvmInline -private value class RestrictedContDsl(private val cont: suspend RestrictedContEffect.() -> A) : - RestrictedCont { +private value class RestrictedContDsl( + private val cont: suspend RestrictedContEffect.() -> A +) : RestrictedCont { override fun fold(f: (R) -> B, g: (A) -> B): B { var reset: Any? = EmptyValue - val effect = object : RestrictedContEffect { - override suspend fun shift(r: R): B = - suspendCoroutineUninterceptedOrReturn { cont -> + val effect = + object : RestrictedContEffect { + override suspend fun shift(r: R): B = suspendCoroutineUninterceptedOrReturn { cont -> reset = f(r) COROUTINE_SUSPENDED } - } - val a: Any? = cont.startCoroutineUninterceptedOrReturn(effect, Continuation(EmptyCoroutineContext) { shifted -> - // If we reach here, then it means we shifted. - shifted.getOrThrow() - }) + } + val a: Any? = + cont.startCoroutineUninterceptedOrReturn( + effect, + Continuation(EmptyCoroutineContext) { shifted -> + // If we reach here, then it means we shifted. + shifted.getOrThrow() + } + ) return if (a === COROUTINE_SUSPENDED && reset !== EmptyValue) EmptyValue.unbox(reset) else g(a as A) } diff --git a/src/commonMain/kotlin/arrow/either.kt b/src/commonMain/kotlin/arrow/either.kt index 820effdfdb4..53264ce949e 100644 --- a/src/commonMain/kotlin/arrow/either.kt +++ b/src/commonMain/kotlin/arrow/either.kt @@ -2,5 +2,5 @@ package arrow import arrow.core.Either -suspend fun either(f: suspend ContEffect.() -> A): Either = - cont(f).toEither() +public suspend fun either(f: suspend ContEffect.() -> A): Either = + cont(f).toEither() diff --git a/src/commonMain/kotlin/arrow/internal/EmptyValue.kt b/src/commonMain/kotlin/arrow/internal/EmptyValue.kt index 452af289c90..d77d54f335c 100644 --- a/src/commonMain/kotlin/arrow/internal/EmptyValue.kt +++ b/src/commonMain/kotlin/arrow/internal/EmptyValue.kt @@ -3,6 +3,5 @@ package arrow.internal @PublishedApi internal object EmptyValue { @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") - public inline fun unbox(value: Any?): A = - if (value === this) null as A else value as A + public inline fun unbox(value: Any?): A = if (value === this) null as A else value as A } diff --git a/src/commonMain/kotlin/arrow/ior.kt b/src/commonMain/kotlin/arrow/ior.kt index 35108033aad..9a356cc3b76 100644 --- a/src/commonMain/kotlin/arrow/ior.kt +++ b/src/commonMain/kotlin/arrow/ior.kt @@ -7,29 +7,27 @@ import arrow.core.identity import arrow.internal.EmptyValue import arrow.typeclasses.Semigroup -suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior = +public suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior = cont> { - val effect = IorEffect(semigroup, this) - val res = f(effect) - val leftState = effect.leftState.get() - if (leftState === EmptyValue) Ior.Right(res) - else Ior.Both(EmptyValue.unbox(leftState), res) - }.fold({ Ior.Left(it) }, ::identity) + val effect = IorEffect(semigroup, this) + val res = f(effect) + val leftState = effect.leftState.get() + if (leftState === EmptyValue) Ior.Right(res) else Ior.Both(EmptyValue.unbox(leftState), res) + } + .fold({ Ior.Left(it) }, ::identity) -class IorEffect( - semigroup: Semigroup, - private val cont: ContEffect -) : ContEffect, Semigroup by semigroup { +public class IorEffect(semigroup: Semigroup, private val cont: ContEffect) : + ContEffect, Semigroup by semigroup { internal var leftState: AtomicRef = AtomicRef(EmptyValue) private fun combine(other: E): E = leftState.updateAndGet { state -> - if (state === EmptyValue) other - else EmptyValue.unbox(state).combine(other) - } as E + if (state === EmptyValue) other else EmptyValue.unbox(state).combine(other) + } as + E - suspend fun Ior.bind(): B = + public suspend fun Ior.bind(): B = when (this) { is Ior.Left -> shift(value) is Ior.Right -> value @@ -39,6 +37,5 @@ class IorEffect( } } - override suspend fun shift(r: E): B = - cont.shift(combine(r)) + override suspend fun shift(r: E): B = cont.shift(combine(r)) } diff --git a/src/commonMain/kotlin/arrow/option.kt b/src/commonMain/kotlin/arrow/option.kt index 2946f08cadc..b5cee29a249 100644 --- a/src/commonMain/kotlin/arrow/option.kt +++ b/src/commonMain/kotlin/arrow/option.kt @@ -8,25 +8,23 @@ import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.jvm.JvmInline -suspend fun option(f: OptionEffect.() -> A): Option = +public suspend fun option(f: OptionEffect.() -> A): Option = cont { f(OptionEffect(this)) }.toOption() -suspend fun Cont.toOption(): Option = - fold(::identity) { Some(it) } +public suspend fun Cont.toOption(): Option = fold(::identity) { Some(it) } @JvmInline -value class OptionEffect(private val cont: ContEffect) : ContEffect { - suspend fun Option.bind(): B = - bind { None } +public value class OptionEffect(private val cont: ContEffect) : ContEffect { + public suspend fun Option.bind(): B = bind { None } - public suspend fun ensure(value: Boolean): Unit = - if (value) Unit else shift(None) + public suspend fun ensure(value: Boolean): Unit = if (value) Unit else shift(None) - override suspend fun shift(r: None): B = - cont.shift(r) + override suspend fun shift(r: None): B = cont.shift(r) } -@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. +@OptIn( + ExperimentalContracts::class +) // Contracts not available on open functions, so made it top-level. public suspend fun ContEffect.ensureNotNull(value: B?): B { contract { returns() implies (value != null) } return value ?: shift(None) diff --git a/src/jvmTest/kotlin/arrow/ContSpec.kt b/src/jvmTest/kotlin/arrow/ContSpec.kt index 56b47d3fe1d..c8f44168806 100644 --- a/src/jvmTest/kotlin/arrow/ContSpec.kt +++ b/src/jvmTest/kotlin/arrow/ContSpec.kt @@ -28,223 +28,205 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.suspendCancellableCoroutine @OptIn(ExperimentalTime::class) -class ContSpec : StringSpec({ - "try/catch - can recover from shift" { - checkAll(Arb.int(), Arb.string()) { i, s -> - cont { - try { - shift(s) - } catch (e: Throwable) { - i - } - }.fold({ fail("Should never come here") }, ::identity) shouldBe i +class ContSpec : + StringSpec({ + "try/catch - can recover from shift" { + checkAll(Arb.int(), Arb.string()) { i, s -> + cont { + try { + shift(s) + } catch (e: Throwable) { + i + } + } + .fold({ fail("Should never come here") }, ::identity) shouldBe i + } } - } - "try/catch - can recover from shift suspended" { - checkAll(Arb.int(), Arb.string()) { i, s -> - cont { - try { - shift(s.suspend()) - } catch (e: Throwable) { - i - } - }.fold({ fail("Should never come here") }, ::identity) shouldBe i + "try/catch - can recover from shift suspended" { + checkAll(Arb.int(), Arb.string()) { i, s -> + cont { + try { + shift(s.suspend()) + } catch (e: Throwable) { + i + } + } + .fold({ fail("Should never come here") }, ::identity) shouldBe i + } } - } - "try/catch - finally works" { - checkAll(Arb.string(), Arb.int()) { s, i -> - val promise = CompletableDeferred() - cont { - try { - shift(s) - } finally { - require(promise.complete(i)) + "try/catch - finally works" { + checkAll(Arb.string(), Arb.int()) { s, i -> + val promise = CompletableDeferred() + cont { + try { + shift(s) + } finally { + require(promise.complete(i)) + } } - }.fold(::identity) { fail("Should never come here") } shouldBe s - promise.await() shouldBe i + .fold(::identity) { fail("Should never come here") } shouldBe s + promise.await() shouldBe i + } } - } - "try/catch - finally works suspended" { - checkAll(Arb.string(), Arb.int()) { s, i -> - val promise = CompletableDeferred() - cont { - try { - shift(s.suspend()) - } finally { - require(promise.complete(i)) + "try/catch - finally works suspended" { + checkAll(Arb.string(), Arb.int()) { s, i -> + val promise = CompletableDeferred() + cont { + try { + shift(s.suspend()) + } finally { + require(promise.complete(i)) + } } - }.fold(::identity) { fail("Should never come here") } shouldBe s - promise.await() shouldBe i + .fold(::identity) { fail("Should never come here") } shouldBe s + promise.await() shouldBe i + } } - } - "try/catch - First shift is ignored and second is returned" { - checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> - cont { - val x: Int = try { - shift(s) - } catch (e: Throwable) { - i + "try/catch - First shift is ignored and second is returned" { + checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + cont { + val x: Int = + try { + shift(s) + } catch (e: Throwable) { + i + } + shift(s2) } - shift(s2) - }.fold(::identity) { fail("Should never come here") } shouldBe s2 + .fold(::identity) { fail("Should never come here") } shouldBe s2 + } } - } - suspend fun test() { - val leakedAsync = coroutineScope Deferred> { - suspend { - async { - println("I am never going to run, until I get called invoked from outside") + suspend fun test() { + val leakedAsync = + coroutineScope Deferred> { + suspend { + async { println("I am never going to run, until I get called invoked from outside") } + } } - } + leakedAsync.invoke().await() } - leakedAsync.invoke().await() - } - "try/catch - First shift is ignored and second is returned suspended" { - checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> - cont { - val x: Int = try { - shift(s.suspend()) - } catch (e: Throwable) { - i + "try/catch - First shift is ignored and second is returned suspended" { + checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> + cont { + val x: Int = + try { + shift(s.suspend()) + } catch (e: Throwable) { + i + } + shift(s2.suspend()) } - shift(s2.suspend()) - }.fold(::identity) { fail("Should never come here") } shouldBe s2 + .fold(::identity) { fail("Should never come here") } shouldBe s2 + } } - } - "immediate values" { - cont { - 1 - }.value() shouldBe 1 - } + "immediate values" { cont { 1 }.value() shouldBe 1 } - "suspended value" { - cont { - 1.suspend() - }.value() shouldBe 1 - } + "suspended value" { cont { 1.suspend() }.value() shouldBe 1 } - "immediate short-circuit" { - cont { - shift("hello") - }.runCont() shouldBe "hello" - } - - "suspended short-circuit" { - cont { - shift("hello".suspend()) - }.runCont() shouldBe "hello" - } + "immediate short-circuit" { + cont { shift("hello") }.runCont() shouldBe "hello" + } - "Rethrows immediate exceptions" { - val e = RuntimeException("test") - Either.catch { - cont { - throw e - }.runCont() - } shouldBe Either.Left(e) - } + "suspended short-circuit" { + cont { shift("hello".suspend()) }.runCont() shouldBe "hello" + } - "Rethrows suspended exceptions" { - val e = RuntimeException("test") - Either.catch { - cont { - e.suspend() - }.runCont() - } shouldBe Either.Left(e) - } + "Rethrows immediate exceptions" { + val e = RuntimeException("test") + Either.catch { cont { throw e }.runCont() } shouldBe Either.Left(e) + } - "Can short-circuit immediately from nested blocks" { - cont { - cont { shift("test") }.runCont() - fail("Should never reach this point") - }.runCont() shouldBe "test" - } + "Rethrows suspended exceptions" { + val e = RuntimeException("test") + Either.catch { cont { e.suspend() }.runCont() } shouldBe Either.Left(e) + } - "Can short-circuit suspended from nested blocks" { - cont { - cont { shift("test".suspend()) }.runCont() - fail("Should never reach this point") - }.runCont() shouldBe "test" - } + "Can short-circuit immediately from nested blocks" { + cont { + cont { shift("test") }.runCont() + fail("Should never reach this point") + } + .runCont() shouldBe "test" + } - "Can short-circuit immediately after suspending from nested blocks" { - cont { - cont { - 1L.suspend() - shift("test".suspend()) - }.runCont() - fail("Should never reach this point") - }.runCont() shouldBe "test" - } + "Can short-circuit suspended from nested blocks" { + cont { + cont { shift("test".suspend()) }.runCont() + fail("Should never reach this point") + } + .runCont() shouldBe "test" + } - // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 - "ensure null in either computation" { - checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> - either { - ensure(predicate) { shift } - success - } shouldBe if (predicate) success.right() else shift.left() + "Can short-circuit immediately after suspending from nested blocks" { + cont { + cont { + 1L.suspend() + shift("test".suspend()) + } + .runCont() + fail("Should never reach this point") + } + .runCont() shouldBe "test" } - } - // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 - "ensureNotNull in either computation" { - fun square(i: Int): Int = i * i + // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 + "ensure null in either computation" { + checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> + either { + ensure(predicate) { shift } + success + } shouldBe if (predicate) success.right() else shift.left() + } + } - checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, shift: String -> - val res = either { - val ii = i - ensureNotNull(ii) { shift } - square(ii) // Smart-cast by contract + // Fails https://github.com/Kotlin/kotlinx.coroutines/issues/3005 + "ensureNotNull in either computation" { + fun square(i: Int): Int = i * i + + checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, shift: String -> + val res = + either { + val ii = i + ensureNotNull(ii) { shift } + square(ii) // Smart-cast by contract + } + val expected = i?.let(::square)?.right() ?: shift.left() + res shouldBe expected } - val expected = i?.let(::square)?.right() ?: shift.left() - res shouldBe expected } - } -}) + }) -suspend fun currentContext(): CoroutineContext = - kotlin.coroutines.coroutineContext +suspend fun currentContext(): CoroutineContext = kotlin.coroutines.coroutineContext -internal suspend fun Throwable.suspend(): Nothing = - suspendCoroutineUninterceptedOrReturn { cont -> - suspend { throw this }.startCoroutine( - Continuation(Dispatchers.Default) { - cont.intercepted().resumeWith(it) - } - ) +internal suspend fun Throwable.suspend(): Nothing = suspendCoroutineUninterceptedOrReturn { cont -> + suspend { throw this } + .startCoroutine(Continuation(Dispatchers.Default) { cont.intercepted().resumeWith(it) }) - COROUTINE_SUSPENDED - } + COROUTINE_SUSPENDED +} -internal suspend fun A.suspend(): A = - suspendCoroutineUninterceptedOrReturn { cont -> - suspend { this }.startCoroutine( - Continuation(Dispatchers.Default) { - cont.intercepted().resumeWith(it) - } - ) +internal suspend fun A.suspend(): A = suspendCoroutineUninterceptedOrReturn { cont -> + suspend { this } + .startCoroutine(Continuation(Dispatchers.Default) { cont.intercepted().resumeWith(it) }) - COROUTINE_SUSPENDED - } + COROUTINE_SUSPENDED +} suspend fun completeOnCancellation( latch: CompletableDeferred, cancelled: CompletableDeferred -): A = - suspendCancellableCoroutine { cont -> - cont.invokeOnCancellation { cause -> - if (!cancelled.complete(cause)) throw AssertionError("cancelled latch was completed twice") - else Unit - } - - if (!latch.complete(Unit)) throw AssertionError("latch was completed twice") +): A = suspendCancellableCoroutine { cont -> + cont.invokeOnCancellation { cause -> + if (!cancelled.complete(cause)) throw AssertionError("cancelled latch was completed twice") else Unit } + + if (!latch.complete(Unit)) throw AssertionError("latch was completed twice") else Unit +} diff --git a/src/jvmTest/kotlin/arrow/IorSpec.kt b/src/jvmTest/kotlin/arrow/IorSpec.kt index 5d9eacb06c9..03ce326387c 100644 --- a/src/jvmTest/kotlin/arrow/IorSpec.kt +++ b/src/jvmTest/kotlin/arrow/IorSpec.kt @@ -13,30 +13,30 @@ import io.kotest.property.checkAll import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll -class IorSpec : StringSpec({ - "Accumulates" { - ior(Semigroup.string()) { - val one = Ior.Both("Hello", 1).bind() - val two = Ior.Both(", World!", 2).bind() - one + two - } shouldBe Ior.Both("Hello, World!", 3) - } +class IorSpec : + StringSpec({ + "Accumulates" { + ior(Semigroup.string()) { + val one = Ior.Both("Hello", 1).bind() + val two = Ior.Both(", World!", 2).bind() + one + two + } shouldBe Ior.Both("Hello, World!", 3) + } - "Accumulates with Either" { - ior(Semigroup.string()) { - val one = Ior.Both("Hello", 1).bind() - val two: Int = Either.Left(", World!").bind() - one + two - } shouldBe Ior.Left("Hello, World!") - } + "Accumulates with Either" { + ior(Semigroup.string()) { + val one = Ior.Both("Hello", 1).bind() + val two: Int = Either.Left(", World!").bind() + one + two + } shouldBe Ior.Left("Hello, World!") + } - "Concurrent - arrow.ior bind" { - checkAll(Arb.list(Arb.string()).filter(List::isNotEmpty)) { strs -> - ior(Semigroup.list()) { - strs.mapIndexed { index, s -> - async { Ior.Both(listOf(s), index).bind() } - }.awaitAll() - }.mapLeft { it.toSet() } shouldBe Ior.Both(strs.toSet(), strs.indices.toList()) + "Concurrent - arrow.ior bind" { + checkAll(Arb.list(Arb.string()).filter(List::isNotEmpty)) { strs -> + ior(Semigroup.list()) { + strs.mapIndexed { index, s -> async { Ior.Both(listOf(s), index).bind() } }.awaitAll() + } + .mapLeft { it.toSet() } shouldBe Ior.Both(strs.toSet(), strs.indices.toList()) + } } - } -}) + }) diff --git a/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt b/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt index b8f6d6d267b..881538bb122 100644 --- a/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt +++ b/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt @@ -29,219 +29,216 @@ import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeout @OptIn(ExperimentalTime::class) -class StructuredConcurrencySpec : StringSpec({ - - "async - suspendCancellableCoroutine.invokeOnCancellation is called with Shifted Continuation" { - val started = CompletableDeferred() - val cancelled = CompletableDeferred() - - cont { - coroutineScope { - val never = async { - suspendCancellableCoroutine { cont -> - cont.invokeOnCancellation { cause -> - require(cancelled.complete(cause)) { "cancelled latch was completed twice" } +class StructuredConcurrencySpec : + StringSpec({ + "async - suspendCancellableCoroutine.invokeOnCancellation is called with Shifted Continuation" { + val started = CompletableDeferred() + val cancelled = CompletableDeferred() + + cont { + coroutineScope { + val never = async { + suspendCancellableCoroutine { cont -> + cont.invokeOnCancellation { cause -> + require(cancelled.complete(cause)) { "cancelled latch was completed twice" } + } + require(started.complete(Unit)) + } } - require(started.complete(Unit)) + async { + started.await() + shift("hello") + } + .await() + never.await() } } - async { - started.await() - shift("hello") - }.await() - never.await() + .runCont() shouldBe "hello" + + withTimeout(Duration.seconds(2)) { + cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" } - }.runCont() shouldBe "hello" + } - withTimeout(Duration.seconds(2)) { - cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" + "Computation blocks run on parent context" { + val parentCtx = currentContext() + cont { currentContext() shouldBe parentCtx }.runCont() } - } - - "Computation blocks run on parent context" { - val parentCtx = currentContext() - cont { - currentContext() shouldBe parentCtx - }.runCont() - } - - "Concurrent shift - async await" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } - fa.await() + fb.await() - } - }.runCont() shouldBeIn listOf(a, b) + + "Concurrent shift - async await" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + fa.await() + fb.await() + } + } + .runCont() shouldBeIn listOf(a, b) + } } - } - - "Concurrent shift - async await exit results" { - checkAll(Arb.int()) { a -> - val scopeExit = CompletableDeferred() - val fbExit = CompletableDeferred() - val startLatches = (0..11).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.asyncTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Deferred = async { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) + + "Concurrent shift - async await exit results" { + checkAll(Arb.int()) { a -> + val scopeExit = CompletableDeferred() + val fbExit = CompletableDeferred() + val startLatches = (0..11).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> require(exit.complete(case)) } } - } - cont { - guaranteeCase({ - coroutineScope { - val fa = async { - startLatches.drop(1).zip(nestedExits) { start, promise -> - asyncTask(start, promise) + cont { + guaranteeCase({ + coroutineScope { + val fa = + async { + startLatches.drop(1).zip(nestedExits) { start, promise -> + asyncTask(start, promise) + } + startLatches.awaitAll() + shift(a) + } + val fb = asyncTask(startLatches.first(), fbExit) + fa.await() + fb.await() } - startLatches.awaitAll() - shift(a) - } - val fb = asyncTask(startLatches.first(), fbExit) - fa.await() - fb.await() + }) { case -> require(scopeExit.complete(case)) } + fail("Should never come here") } - }) { case -> - require(scopeExit.complete(case)) + .runCont() shouldBe a + withTimeout(2.seconds) { + scopeExit.await().shouldBeTypeOf() + fbExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } } - fail("Should never come here") - }.runCont() shouldBe a - withTimeout(2.seconds) { - scopeExit.await().shouldBeTypeOf() - fbExit.await().shouldBeTypeOf() - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } } } - } - - "Concurrent shift - async" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - val fa = async { shift(a) } - val fb = async { shift(b) } + + "Concurrent shift - async" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + val fa = async { shift(a) } + val fb = async { shift(b) } + "I will be overwritten by shift - coroutineScope waits until all async are finished" + } + } + .fold({ fail("Async is never awaited, and thus ignored.") }, ::identity) shouldBe "I will be overwritten by shift - coroutineScope waits until all async are finished" - } - }.fold({ - fail("Async is never awaited, and thus ignored.") - }, ::identity) shouldBe "I will be overwritten by shift - coroutineScope waits until all async are finished" + } } - } - - "Concurrent shift - async exit results" { - checkAll(Arb.int(), Arb.string()) { a, str -> - val exitScope = CompletableDeferred() - val startLatches = (0..10).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.asyncTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Deferred = async { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) + + "Concurrent shift - async exit results" { + checkAll(Arb.int(), Arb.string()) { a, str -> + val exitScope = CompletableDeferred() + val startLatches = (0..10).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.asyncTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Deferred = async { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> require(exit.complete(case)) } } - } - cont { - guaranteeCase({ - coroutineScope { - val fa = async { - startLatches.zip(nestedExits) { start, promise -> - asyncTask(start, promise) + cont { + guaranteeCase({ + coroutineScope { + val fa = + async { + startLatches.zip(nestedExits) { start, promise -> asyncTask(start, promise) } + startLatches.awaitAll() + shift(a) + } + str } - startLatches.awaitAll() - shift(a) - } - str + }) { case -> require(exitScope.complete(case)) } } - }) { case -> require(exitScope.complete(case)) } - }.runCont() shouldBe str + .runCont() shouldBe str - withTimeout(2.seconds) { - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + withTimeout(2.seconds) { + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + } } } - } - - "Concurrent shift - launch" { - checkAll(Arb.int(), Arb.int()) { a, b -> - cont { - coroutineScope { - launch { shift(a) } - launch { shift(b) } - "shift does not escape `launch`" - } - }.runCont() shouldBe "shift does not escape `launch`" + + "Concurrent shift - launch" { + checkAll(Arb.int(), Arb.int()) { a, b -> + cont { + coroutineScope { + launch { shift(a) } + launch { shift(b) } + "shift does not escape `launch`" + } + } + .runCont() shouldBe "shift does not escape `launch`" + } } - } - - "Concurrent shift - launch exit results" { - checkAll(Arb.int(), Arb.string()) { a, str -> - val scopeExit = CompletableDeferred() - val startLatches = (0..10).map { CompletableDeferred() } - val nestedExits = (0..10).map { CompletableDeferred() } - - fun CoroutineScope.launchTask( - start: CompletableDeferred, - exit: CompletableDeferred - ): Job = launch { - guaranteeCase({ - start.complete(Unit) - never() - }) { case -> - require(exit.complete(case)) + + "Concurrent shift - launch exit results" { + checkAll(Arb.int(), Arb.string()) { a, str -> + val scopeExit = CompletableDeferred() + val startLatches = (0..10).map { CompletableDeferred() } + val nestedExits = (0..10).map { CompletableDeferred() } + + fun CoroutineScope.launchTask( + start: CompletableDeferred, + exit: CompletableDeferred + ): Job = launch { + guaranteeCase({ + start.complete(Unit) + never() + }) { case -> require(exit.complete(case)) } } - } - cont { - guaranteeCase({ - coroutineScope { - val fa = launch { - startLatches.zip(nestedExits) { start, promise -> - launchTask(start, promise) + cont { + guaranteeCase({ + coroutineScope { + val fa = launch { + startLatches.zip(nestedExits) { start, promise -> launchTask(start, promise) } + startLatches.awaitAll() + shift(a) + } + str } - startLatches.awaitAll() - shift(a) - } - str + }) { case -> require(scopeExit.complete(case)) } } - }) { case -> require(scopeExit.complete(case)) } - }.runCont() shouldBe str - withTimeout(2.seconds) { - scopeExit.await().shouldBeTypeOf() - nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + .runCont() shouldBe str + withTimeout(2.seconds) { + scopeExit.await().shouldBeTypeOf() + nestedExits.awaitAll().forEach { it.shouldBeTypeOf() } + } } } - } - - // `shift` escapes `cont` block, and gets rethrown inside `coroutineScope`. - // Effectively awaiting/executing DSL code, outside of the DSL... - "async funky scenario #1 - Extract `shift` from `cont` through `async`" { - checkAll(Arb.int(), Arb.int()) { a, b -> - runCatching { - coroutineScope { - val shiftedAsync = cont> { - val fa = async { shift(a) } - async { shift(b) } - }.fold({ - fail("shift was never awaited, so it never took effect") - }, ::identity) - shiftedAsync.await() - } - }.exceptionOrNull()?.message shouldBe "Shifted Continuation" + + // `shift` escapes `cont` block, and gets rethrown inside `coroutineScope`. + // Effectively awaiting/executing DSL code, outside of the DSL... + "async funky scenario #1 - Extract `shift` from `cont` through `async`" { + checkAll(Arb.int(), Arb.int()) { a, b -> + runCatching { + coroutineScope { + val shiftedAsync = + cont> { + val fa = async { shift(a) } + async { shift(b) } + } + .fold({ fail("shift was never awaited, so it never took effect") }, ::identity) + shiftedAsync.await() + } + } + .exceptionOrNull() + ?.message shouldBe "Shifted Continuation" + } } - } -}) + }) diff --git a/src/jvmTest/kotlin/arrow/predef.kt b/src/jvmTest/kotlin/arrow/predef.kt index 3fabb2352f3..cc6a88ca588 100644 --- a/src/jvmTest/kotlin/arrow/predef.kt +++ b/src/jvmTest/kotlin/arrow/predef.kt @@ -2,8 +2,6 @@ package arrow import arrow.core.identity -suspend fun Cont.value(): A = - fold(::identity, ::identity) +suspend fun Cont.value(): A = fold(::identity, ::identity) -suspend fun Cont<*, *>.runCont(): Any? = - fold(::identity, ::identity) +suspend fun Cont<*, *>.runCont(): Any? = fold(::identity, ::identity) From b26645c966eaae4bcdcebd9add473b71795deff2 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 22:40:21 +0100 Subject: [PATCH 031/108] Move test to common --- src/{jvmTest => commonTest}/kotlin/arrow/ContSpec.kt | 0 src/{jvmTest => commonTest}/kotlin/arrow/IorSpec.kt | 0 .../kotlin/arrow/StructuredConcurrencySpec.kt | 0 src/{jvmTest => commonTest}/kotlin/arrow/predef.kt | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/{jvmTest => commonTest}/kotlin/arrow/ContSpec.kt (100%) rename src/{jvmTest => commonTest}/kotlin/arrow/IorSpec.kt (100%) rename src/{jvmTest => commonTest}/kotlin/arrow/StructuredConcurrencySpec.kt (100%) rename src/{jvmTest => commonTest}/kotlin/arrow/predef.kt (100%) diff --git a/src/jvmTest/kotlin/arrow/ContSpec.kt b/src/commonTest/kotlin/arrow/ContSpec.kt similarity index 100% rename from src/jvmTest/kotlin/arrow/ContSpec.kt rename to src/commonTest/kotlin/arrow/ContSpec.kt diff --git a/src/jvmTest/kotlin/arrow/IorSpec.kt b/src/commonTest/kotlin/arrow/IorSpec.kt similarity index 100% rename from src/jvmTest/kotlin/arrow/IorSpec.kt rename to src/commonTest/kotlin/arrow/IorSpec.kt diff --git a/src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt b/src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt similarity index 100% rename from src/jvmTest/kotlin/arrow/StructuredConcurrencySpec.kt rename to src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt diff --git a/src/jvmTest/kotlin/arrow/predef.kt b/src/commonTest/kotlin/arrow/predef.kt similarity index 100% rename from src/jvmTest/kotlin/arrow/predef.kt rename to src/commonTest/kotlin/arrow/predef.kt From 0258182f72cb7d0552a498e8a43b8bca8aeb7ca5 Mon Sep 17 00:00:00 2001 From: nomisRev Date: Tue, 9 Nov 2021 21:42:04 +0000 Subject: [PATCH 032/108] Auto update docs --- docs/-cont/arrow/-cont-effect/ensure.html | 4 ++-- docs/-cont/arrow/-cont-effect/index.html | 4 ++-- docs/-cont/arrow/-cont-effect/shift.html | 4 ++-- docs/-cont/arrow/-cont/attempt.html | 4 ++-- docs/-cont/arrow/-cont/flat-map.html | 4 ++-- docs/-cont/arrow/-cont/handle-error-with.html | 4 ++-- docs/-cont/arrow/-cont/handle-error.html | 4 ++-- docs/-cont/arrow/-cont/index.html | 4 ++-- docs/-cont/arrow/-cont/map.html | 4 ++-- docs/-cont/arrow/-cont/redeem-with.html | 4 ++-- docs/-cont/arrow/-cont/redeem.html | 4 ++-- docs/-cont/arrow/-cont/to-either.html | 4 ++-- docs/-cont/arrow/-cont/to-ior.html | 4 ++-- docs/-cont/arrow/-cont/to-option.html | 4 ++-- docs/-cont/arrow/-cont/to-validated.html | 4 ++-- docs/-cont/arrow/-ior-effect/bind.html | 4 ++-- docs/-cont/arrow/-ior-effect/shift.html | 4 ++-- docs/-cont/arrow/-option-effect/-option-effect.html | 4 ++-- docs/-cont/arrow/-option-effect/bind.html | 4 ++-- docs/-cont/arrow/-option-effect/ensure.html | 4 ++-- docs/-cont/arrow/-option-effect/index.html | 4 ++-- docs/-cont/arrow/-option-effect/shift.html | 4 ++-- docs/-cont/arrow/-restricted-cont-effect/bind.html | 4 ++-- docs/-cont/arrow/-restricted-cont/attempt.html | 4 ++-- docs/-cont/arrow/-restricted-cont/flat-map.html | 4 ++-- docs/-cont/arrow/-restricted-cont/fold.html | 4 ++-- docs/-cont/arrow/-restricted-cont/handle-error-with.html | 4 ++-- docs/-cont/arrow/-restricted-cont/handle-error.html | 4 ++-- docs/-cont/arrow/-restricted-cont/index.html | 4 ++-- docs/-cont/arrow/-restricted-cont/map.html | 4 ++-- docs/-cont/arrow/-restricted-cont/redeem-with.html | 4 ++-- docs/-cont/arrow/-restricted-cont/redeem.html | 4 ++-- docs/-cont/arrow/-restricted-cont/to-either.html | 4 ++-- docs/-cont/arrow/-restricted-cont/to-validated.html | 4 ++-- docs/-cont/arrow/-shift-cancellation-exception/index.html | 4 ++-- docs/-cont/arrow/sequence.html | 4 ++-- docs/-cont/arrow/traverse-cont.html | 4 ++-- docs/scripts/sourceset_dependencies.js | 2 +- 38 files changed, 75 insertions(+), 75 deletions(-) diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html index 6b4e0780039..a8b38ed7ccb 100644 --- a/docs/-cont/arrow/-cont-effect/ensure.html +++ b/docs/-cont/arrow/-cont-effect/ensure.html @@ -30,10 +30,10 @@

ensure

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html index 55a5d818129..f9818a0f99a 100644 --- a/docs/-cont/arrow/-cont-effect/index.html +++ b/docs/-cont/arrow/-cont-effect/index.html @@ -120,10 +120,10 @@

Extensions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html index fe9c2a65001..e37fed492f3 100644 --- a/docs/-cont/arrow/-cont-effect/shift.html +++ b/docs/-cont/arrow/-cont-effect/shift.html @@ -30,10 +30,10 @@

shift

Short-circuit the Cont computation with value R.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html index 7821fbbb999..dbc130e2c8d 100644 --- a/docs/-cont/arrow/-cont/attempt.html +++ b/docs/-cont/arrow/-cont/attempt.html @@ -30,10 +30,10 @@

attempt

Runs the Cont and captures any NonFatal exception into Result.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/flat-map.html b/docs/-cont/arrow/-cont/flat-map.html index cfdb33dc786..0bf7522ee34 100644 --- a/docs/-cont/arrow/-cont/flat-map.html +++ b/docs/-cont/arrow/-cont/flat-map.html @@ -30,10 +30,10 @@

flatMap

Maps the values A with the transform function into another Cont effect.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html index 52fea6aef1b..64c432c917f 100644 --- a/docs/-cont/arrow/-cont/handle-error-with.html +++ b/docs/-cont/arrow/-cont/handle-error-with.html @@ -30,10 +30,10 @@

handleError

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html index beae7780384..035a6246e7e 100644 --- a/docs/-cont/arrow/-cont/handle-error.html +++ b/docs/-cont/arrow/-cont/handle-error.html @@ -30,10 +30,10 @@

handleError<

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html index b68ee5ff349..715322fc7ad 100644 --- a/docs/-cont/arrow/-cont/index.html +++ b/docs/-cont/arrow/-cont/index.html @@ -259,10 +259,10 @@

Extensions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/map.html b/docs/-cont/arrow/-cont/map.html index 9ba377fa24f..4e3ee894322 100644 --- a/docs/-cont/arrow/-cont/map.html +++ b/docs/-cont/arrow/-cont/map.html @@ -30,10 +30,10 @@

map

Maps the values A with the transform function into B.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html index 0fbc415252b..f78188d45a8 100644 --- a/docs/-cont/arrow/-cont/redeem-with.html +++ b/docs/-cont/arrow/-cont/redeem-with.html @@ -30,10 +30,10 @@

redeemWith

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html index 2142bb5d9a2..6bef5b31371 100644 --- a/docs/-cont/arrow/-cont/redeem.html +++ b/docs/-cont/arrow/-cont/redeem.html @@ -30,10 +30,10 @@

redeem

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-either.html b/docs/-cont/arrow/-cont/to-either.html index 7d78e2c89af..2247d802115 100644 --- a/docs/-cont/arrow/-cont/to-either.html +++ b/docs/-cont/arrow/-cont/to-either.html @@ -30,10 +30,10 @@

toEither

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-ior.html b/docs/-cont/arrow/-cont/to-ior.html index 6b725f19a7b..4b486f18ab0 100644 --- a/docs/-cont/arrow/-cont/to-ior.html +++ b/docs/-cont/arrow/-cont/to-ior.html @@ -30,10 +30,10 @@

toIor

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html index eed4b458f77..4b33d9157a0 100644 --- a/docs/-cont/arrow/-cont/to-option.html +++ b/docs/-cont/arrow/-cont/to-option.html @@ -30,10 +30,10 @@

toOption

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-validated.html b/docs/-cont/arrow/-cont/to-validated.html index 6688216eab9..6d52dd61b70 100644 --- a/docs/-cont/arrow/-cont/to-validated.html +++ b/docs/-cont/arrow/-cont/to-validated.html @@ -30,10 +30,10 @@

toValidated<

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html index 3b4474f52a4..35186b2813c 100644 --- a/docs/-cont/arrow/-ior-effect/bind.html +++ b/docs/-cont/arrow/-ior-effect/bind.html @@ -30,10 +30,10 @@

bind

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html index 887058673a5..cb2995a33f1 100644 --- a/docs/-cont/arrow/-ior-effect/shift.html +++ b/docs/-cont/arrow/-ior-effect/shift.html @@ -30,10 +30,10 @@

shift

Short-circuit the Cont computation with value R.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/-option-effect.html b/docs/-cont/arrow/-option-effect/-option-effect.html index 0a2a3dbb6d1..8e9a6203294 100644 --- a/docs/-cont/arrow/-option-effect/-option-effect.html +++ b/docs/-cont/arrow/-option-effect/-option-effect.html @@ -30,10 +30,10 @@

OptionEffect

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/bind.html b/docs/-cont/arrow/-option-effect/bind.html index 618b8e03723..3a0a59a1b65 100644 --- a/docs/-cont/arrow/-option-effect/bind.html +++ b/docs/-cont/arrow/-option-effect/bind.html @@ -30,10 +30,10 @@

bind

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/ensure.html b/docs/-cont/arrow/-option-effect/ensure.html index 3ff95161a8a..4adf7508de6 100644 --- a/docs/-cont/arrow/-option-effect/ensure.html +++ b/docs/-cont/arrow/-option-effect/ensure.html @@ -30,10 +30,10 @@

ensure

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/index.html b/docs/-cont/arrow/-option-effect/index.html index 873c6d4d3cc..af5616b2587 100644 --- a/docs/-cont/arrow/-option-effect/index.html +++ b/docs/-cont/arrow/-option-effect/index.html @@ -81,10 +81,10 @@

Functions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/shift.html b/docs/-cont/arrow/-option-effect/shift.html index 60a62327ff2..43dd27b480c 100644 --- a/docs/-cont/arrow/-option-effect/shift.html +++ b/docs/-cont/arrow/-option-effect/shift.html @@ -30,10 +30,10 @@

shift

Short-circuit the Cont computation with value R.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont-effect/bind.html b/docs/-cont/arrow/-restricted-cont-effect/bind.html index 8831c2192a0..3ae1cf2e9c5 100644 --- a/docs/-cont/arrow/-restricted-cont-effect/bind.html +++ b/docs/-cont/arrow/-restricted-cont-effect/bind.html @@ -30,10 +30,10 @@

bind

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/attempt.html b/docs/-cont/arrow/-restricted-cont/attempt.html index 09b20bef86d..f499e255dbd 100644 --- a/docs/-cont/arrow/-restricted-cont/attempt.html +++ b/docs/-cont/arrow/-restricted-cont/attempt.html @@ -30,10 +30,10 @@

attempt

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/flat-map.html b/docs/-cont/arrow/-restricted-cont/flat-map.html index bdf27c33df8..e4f1bc634c0 100644 --- a/docs/-cont/arrow/-restricted-cont/flat-map.html +++ b/docs/-cont/arrow/-restricted-cont/flat-map.html @@ -30,10 +30,10 @@

flatMap

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/fold.html b/docs/-cont/arrow/-restricted-cont/fold.html index e3e9bdca520..920f16ab631 100644 --- a/docs/-cont/arrow/-restricted-cont/fold.html +++ b/docs/-cont/arrow/-restricted-cont/fold.html @@ -30,10 +30,10 @@

fold

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/handle-error-with.html b/docs/-cont/arrow/-restricted-cont/handle-error-with.html index c2906fb5382..47d096e6f61 100644 --- a/docs/-cont/arrow/-restricted-cont/handle-error-with.html +++ b/docs/-cont/arrow/-restricted-cont/handle-error-with.html @@ -30,10 +30,10 @@

handleError

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/handle-error.html b/docs/-cont/arrow/-restricted-cont/handle-error.html index bdc6cc9cf1c..eb5cfbd5ab1 100644 --- a/docs/-cont/arrow/-restricted-cont/handle-error.html +++ b/docs/-cont/arrow/-restricted-cont/handle-error.html @@ -30,10 +30,10 @@

handleError<

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/index.html b/docs/-cont/arrow/-restricted-cont/index.html index dfe8327124a..7f6eedfe507 100644 --- a/docs/-cont/arrow/-restricted-cont/index.html +++ b/docs/-cont/arrow/-restricted-cont/index.html @@ -200,10 +200,10 @@

Functions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/map.html b/docs/-cont/arrow/-restricted-cont/map.html index 3230133d155..09ae5442552 100644 --- a/docs/-cont/arrow/-restricted-cont/map.html +++ b/docs/-cont/arrow/-restricted-cont/map.html @@ -30,10 +30,10 @@

map

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/redeem-with.html b/docs/-cont/arrow/-restricted-cont/redeem-with.html index 158bb93b814..6dec0257d9b 100644 --- a/docs/-cont/arrow/-restricted-cont/redeem-with.html +++ b/docs/-cont/arrow/-restricted-cont/redeem-with.html @@ -30,10 +30,10 @@

redeemWith

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/redeem.html b/docs/-cont/arrow/-restricted-cont/redeem.html index 1f69dfcc9ff..7d03b87ed1d 100644 --- a/docs/-cont/arrow/-restricted-cont/redeem.html +++ b/docs/-cont/arrow/-restricted-cont/redeem.html @@ -30,10 +30,10 @@

redeem

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/to-either.html b/docs/-cont/arrow/-restricted-cont/to-either.html index 3186b9a0dd2..36647dcaeb9 100644 --- a/docs/-cont/arrow/-restricted-cont/to-either.html +++ b/docs/-cont/arrow/-restricted-cont/to-either.html @@ -30,10 +30,10 @@

toEither

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-restricted-cont/to-validated.html b/docs/-cont/arrow/-restricted-cont/to-validated.html index 8ad1731f236..2d8c48e2be6 100644 --- a/docs/-cont/arrow/-restricted-cont/to-validated.html +++ b/docs/-cont/arrow/-restricted-cont/to-validated.html @@ -30,10 +30,10 @@

toValidated<

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html index f7eb45a16ca..03434b19668 100644 --- a/docs/-cont/arrow/-shift-cancellation-exception/index.html +++ b/docs/-cont/arrow/-shift-cancellation-exception/index.html @@ -56,10 +56,10 @@

Properties

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/sequence.html b/docs/-cont/arrow/sequence.html index 0d16ca00359..9ce0d2ea699 100644 --- a/docs/-cont/arrow/sequence.html +++ b/docs/-cont/arrow/sequence.html @@ -30,10 +30,10 @@

sequence

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/traverse-cont.html b/docs/-cont/arrow/traverse-cont.html index ea68ee2a4cd..d575d37d131 100644 --- a/docs/-cont/arrow/traverse-cont.html +++ b/docs/-cont/arrow/traverse-cont.html @@ -30,10 +30,10 @@

traverseCont

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/scripts/sourceset_dependencies.js b/docs/scripts/sourceset_dependencies.js index 07691e8b454..9ff9a55fc0b 100644 --- a/docs/scripts/sourceset_dependencies.js +++ b/docs/scripts/sourceset_dependencies.js @@ -1 +1 @@ -sourceset_dependencies='{":dokkaHtml/commonMain":[],":dokkaHtml/jvmMain":[":dokkaHtml/commonMain"]}' +sourceset_dependencies='{":dokkaHtml/commonMain":[],":dokkaHtml/iosArm32Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/iosArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/iosSimulatorArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/iosX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/jsMain":[":dokkaHtml/commonMain"],":dokkaHtml/jvmMain":[":dokkaHtml/commonMain"],":dokkaHtml/linuxX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/macosArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/macosX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/mingwX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/nativeMain":[":dokkaHtml/commonMain"],":dokkaHtml/tvosArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/tvosSimulatorArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/tvosX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/watchosArm32Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/watchosArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/watchosSimulatorArm64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/watchosX64Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"],":dokkaHtml/watchosX86Main":[":dokkaHtml/commonMain",":dokkaHtml/nativeMain"]}' From 19ab95ac7dbf768563de858047869b1a2365a242 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 22:42:47 +0100 Subject: [PATCH 033/108] Reemove upload test reports --- .github/workflows/build.yaml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 0cd458fae0e..9a3478e690b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -45,14 +45,3 @@ jobs: - name: Run Windows tests if: matrix.os == 'windows-latest' run: ./gradlew mingwX64Test - - - name: Bundle the build report - if: failure() - run: find . -type d -name 'reports' | zip -@ -r build-reports.zip - - - name: Upload the build report - if: failure() - uses: actions/upload-artifact@master - with: - name: error-report - path: build-reports.zip \ No newline at end of file From dda5dcc9f93d96e45ece2ceccb0461cac5872045 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 9 Nov 2021 23:15:16 +0100 Subject: [PATCH 034/108] Try Kotest M2 --- libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs.versions.toml b/libs.versions.toml index 3a31f768c21..ad2a5801923 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -3,7 +3,7 @@ arrow = "1.0.1" arrowGradleConfig = "0.5.1" coroutines = "1.5.2" dokka = "1.5.31" -kotest = "5.0.0.M3" +kotest = "5.0.0.M2" kotestGradle = "5.0.0.5" kotlin = "1.5.31" kotlinBinaryCompatibilityValidator = "0.8.0" From ef7978f678d4a12a1937d6a3052dd90b597aad6d Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 10 Nov 2021 17:16:52 +0100 Subject: [PATCH 035/108] Use Kotest knit template, and use Kotest assertion inside examples --- docs/knit.code.include | 12 ++++ docs/knit.test.template | 16 ++++++ guide/example/example-cont-01.kt | 16 ++++-- guide/example/example-cont-02.kt | 21 ++++--- guide/example/example-readme-01.kt | 11 +++- guide/example/example-readme-02.kt | 30 +++++----- guide/example/example-readme-03.kt | 15 +++-- guide/example/example-readme-04.kt | 27 +++++---- guide/example/example-readme-05.kt | 12 +++- guide/example/example-readme-06.kt | 26 +++++---- guide/example/example-readme-07.kt | 23 +++++--- guide/example/example-readme-08.kt | 18 +++--- guide/example/example-readme-09.kt | 33 ++++++----- guide/example/example-readme-10.kt | 17 +++--- guide/test/ContTest.kt | 27 ++++----- guide/test/ReadmeSpec.kt | 34 +++++++++++ guide/test/ReadmeTest.kt | 64 --------------------- knit.properties | 5 +- src/commonMain/kotlin/arrow/Cont.kt | 88 ++++++++++++----------------- src/commonMain/kotlin/arrow/ior.kt | 3 +- 20 files changed, 265 insertions(+), 233 deletions(-) create mode 100644 docs/knit.code.include create mode 100644 docs/knit.test.template create mode 100644 guide/test/ReadmeSpec.kt delete mode 100644 guide/test/ReadmeTest.kt diff --git a/docs/knit.code.include b/docs/knit.code.include new file mode 100644 index 00000000000..d809cd1f24b --- /dev/null +++ b/docs/knit.code.include @@ -0,0 +1,12 @@ +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${knit.package}.${knit.name} + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException diff --git a/docs/knit.test.template b/docs/knit.test.template new file mode 100644 index 00000000000..d7c46cfb236 --- /dev/null +++ b/docs/knit.test.template @@ -0,0 +1,16 @@ +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${test.package} + +import io.kotest.core.spec.style.StringSpec +import kotlin.time.Duration +import kotlin.time.ExperimentalTime + +@OptIn(ExperimentalTime::class) +class ${test.name} : StringSpec({ +<#list cases as case> + "${case.name}".config(timeout= Duration.seconds(1)) { + ${case.knit.package}.${case.knit.name}.test() + } + + +}) \ No newline at end of file diff --git a/guide/example/example-cont-01.kt b/guide/example/example-cont-01.kt index 8e4a95aad48..97431fe9ae5 100644 --- a/guide/example/example-cont-01.kt +++ b/guide/example/example-cont-01.kt @@ -1,22 +1,28 @@ // This file was automatically generated from Cont.kt by Knit tool. Do not edit. package example.exampleCont01 +import arrow.* import arrow.core.* -import arrow.cont -import kotlinx.coroutines.runBlocking +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException -fun main() = runBlocking { +suspend fun test() { cont { val x = Either.Right(1).bind() val y = Validated.Valid(2).bind() val z = Option(3).bind { "Option was empty" } x + y + z - }.fold(::println, ::println) + }.fold({ fail("Shift can never be the result") }, { it shouldBe 6 }) cont { val x = Either.Right(1).bind() val y = Validated.Valid(2).bind() val z: Int = None.bind { "Option was empty" } x + y + z - }.fold(::println, ::println) + }.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") }) } diff --git a/guide/example/example-cont-02.kt b/guide/example/example-cont-02.kt index 8eaa912c481..09f2fbb5e25 100644 --- a/guide/example/example-cont-02.kt +++ b/guide/example/example-cont-02.kt @@ -1,17 +1,24 @@ // This file was automatically generated from Cont.kt by Knit tool. Do not edit. package example.exampleCont02 -import arrow.cont -import kotlinx.coroutines.runBlocking +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException -fun main() = runBlocking { - cont { +suspend fun test() { + val shift = cont { shift("Hello, World!") }.fold({ str: String -> str }, { int -> int.toString() }) - .let(::println) + shift shouldBe "Hello, World!" - cont { + val res = cont { 1000 }.fold({ str: String -> str.length }, { int -> int }) - .let(::println) + res shouldBe 1000 } diff --git a/guide/example/example-readme-01.kt b/guide/example/example-readme-01.kt index ae5448ca915..19aa895ee1e 100644 --- a/guide/example/example-readme-01.kt +++ b/guide/example/example-readme-01.kt @@ -1,8 +1,15 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme01 -import arrow.Cont -import arrow.cont +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException object EmptyPath diff --git a/guide/example/example-readme-02.kt b/guide/example/example-readme-02.kt index a5aecc0792d..957192196e4 100644 --- a/guide/example/example-readme-02.kt +++ b/guide/example/example-readme-02.kt @@ -1,13 +1,17 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme02 -import arrow.Cont -import arrow.cont -import arrow.ensureNotNull -import arrow.core.None -import java.io.File -import java.io.FileNotFoundException -import kotlinx.coroutines.runBlocking +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException + +import java.io.* @JvmInline value class Content(val body: List) @@ -32,10 +36,10 @@ fun readFile(path: String?): Cont = cont { } } -fun main() = runBlocking { - readFile("").toEither().also(::println) - readFile("not-found").toValidated().also(::println) - readFile("gradle.properties").toIor().also(::println) - readFile("not-found").toOption { None }.also(::println) - readFile("nullable").fold({ _: FileError -> null }, { it }).also(::println) +suspend fun test() { + readFile("").toEither() shouldBe Either.Left(EmptyPath) + readFile("not-found").toValidated() shouldBe Validated.Invalid(FileNotFound("not-found")) + readFile("gradle.properties").toIor() shouldBe Ior.Left(FileNotFound("gradle.properties")) + readFile("not-found").toOption { None } shouldBe None + readFile("nullable").fold({ _: FileError -> null }, { it }) shouldBe null } diff --git a/guide/example/example-readme-03.kt b/guide/example/example-readme-03.kt index 33b02b57355..ddb95522905 100644 --- a/guide/example/example-readme-03.kt +++ b/guide/example/example-readme-03.kt @@ -1,12 +1,15 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme03 -import arrow.Cont -import arrow.core.identity -import arrow.core.Either -import arrow.core.Option -import arrow.core.None -import arrow.core.Some +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException suspend fun Cont.toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } diff --git a/guide/example/example-readme-04.kt b/guide/example/example-readme-04.kt index 1b4ddf2021a..255794efa5e 100644 --- a/guide/example/example-readme-04.kt +++ b/guide/example/example-readme-04.kt @@ -1,10 +1,15 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme04 -import arrow.Cont -import arrow.cont -import arrow.core.identity -import kotlinx.coroutines.runBlocking +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException val failed: Cont = cont { shift("failed") } @@ -21,13 +26,13 @@ val redeemed: Cont = failed.redeem({ str -> str.length }, ::identity) val captured: Cont> = cont { - throw RuntimeException("Boom") + 1 }.attempt() -fun main() = runBlocking { - println(failed.toEither()) - println(resolved.toEither()) - println(newError.toEither()) - println(redeemed.toEither()) - println(captured.toEither()) +suspend fun test() { + failed.toEither() shouldBe Either.Left("failed") + resolved.toEither() shouldBe Either.Right(6) + newError.toEither() shouldBe Either.Left(listOf('d', 'e', 'l', 'i', 'a', 'f')) + redeemed.toEither() shouldBe Either.Right(6) + captured.toEither() shouldBe Either.Right(Result.success(1)) } diff --git a/guide/example/example-readme-05.kt b/guide/example/example-readme-05.kt index 372e324358c..3fbea223a1e 100644 --- a/guide/example/example-readme-05.kt +++ b/guide/example/example-readme-05.kt @@ -1,9 +1,15 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme05 -import arrow.cont -import arrow.fx.coroutines.parZip -import kotlinx.coroutines.delay +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException suspend fun parZip(): Unit = cont { parZip({ diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt index 5a11b949feb..fd0521cd323 100644 --- a/guide/example/example-readme-06.kt +++ b/guide/example/example-readme-06.kt @@ -1,17 +1,23 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme06 -import arrow.cont -import arrow.fx.coroutines.onCancel -import arrow.fx.coroutines.parTraverse -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException -fun main() = runBlocking { +suspend fun test() { + val exits = (0..3).map { CompletableDeferred() } cont> { - (1..5).parTraverse { index -> - if (index == 5) shift("error") - else onCancel({ delay(1_000_000) }) { println("I got cancelled") } + (0..4).parTraverse { index -> + if (index == 4) shift("error") + else guaranteeCase({ delay(1_000_000) }) { exitCase -> require(exits[index].complete(exitCase)) } } - }.fold(::println, ::println) + }.fold({ msg -> msg shouldBe "error" }, { fail("Int can never be the result") }) + exits.awaitAll().forEach { it.shouldBeTypeOf() } } diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt index c0641d88ba5..2ed36dbc47c 100644 --- a/guide/example/example-readme-07.kt +++ b/guide/example/example-readme-07.kt @@ -1,19 +1,24 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme07 -import arrow.cont -import arrow.core.merge -import arrow.fx.coroutines.onCancel -import arrow.fx.coroutines.raceN -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException -fun main() = runBlocking { +suspend fun test() { + val exit = CompletableDeferred() cont { raceN({ - onCancel({ delay(1_000_000) }) { println("I lost the race...") } + guaranteeCase({ delay(1_000_000) }) { exitCase -> require(exit.complete(exitCase)) } 5 }) { shift("error") } .merge() // Flatten Either result from race into Int - }.fold(::println, ::println) + }.fold({ msg -> msg shouldBe "error" }, { fail("Int can never be the result") }) + exit.await().shouldBeTypeOf() } diff --git a/guide/example/example-readme-08.kt b/guide/example/example-readme-08.kt index 18d5e43399f..a387444e26f 100644 --- a/guide/example/example-readme-08.kt +++ b/guide/example/example-readme-08.kt @@ -1,13 +1,17 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme08 -import arrow.cont -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.bracketCase -import arrow.fx.coroutines.Resource -import arrow.fx.coroutines.fromAutoCloseable -import java.io.BufferedReader -import java.io.File +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException + +import java.io.* suspend fun bracketCase() = cont { bracketCase( diff --git a/guide/example/example-readme-09.kt b/guide/example/example-readme-09.kt index 3dac0160762..91f4e756313 100644 --- a/guide/example/example-readme-09.kt +++ b/guide/example/example-readme-09.kt @@ -1,19 +1,17 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme09 -import arrow.cont -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import arrow.Cont -import arrow.ensureNotNull -import java.io.File -import java.io.FileNotFoundException +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException -import kotlinx.coroutines.Job -import kotlinx.coroutines.runBlocking + +import java.io.* @JvmInline value class Content(val body: List) @@ -44,14 +42,15 @@ fun A.onCancel(f: (CancellationException) -> Unit): A = also { } } -fun main() = runBlocking { +suspend fun test() { + val exit = CompletableDeferred() cont { withContext(Dispatchers.IO) { - launch { delay(1_000_000) }.onCancel { println("Cancelled due to shift: $it") } - val sleeper = async { delay(1_000_000) }.onCancel { println("Cancelled due to shift: $it") } + val job = launch { delay(1_000_000) }.onCancel { ce -> require(exit.complete(ce)) } val content = readFile("failure").bind() - sleeper.await() + job.join() content.body.size } - }.fold(::println, ::println) + }.fold({ e -> e shouldBe FileNotFound("failure") }, { fail("Int can never be the result") }) + exit.await().shouldBeInstanceOf() } diff --git a/guide/example/example-readme-10.kt b/guide/example/example-readme-10.kt index 8569201a7e7..3ed2fe57934 100644 --- a/guide/example/example-readme-10.kt +++ b/guide/example/example-readme-10.kt @@ -1,14 +1,17 @@ // This file was automatically generated from README.md by Knit tool. Do not edit. package example.exampleReadme10 -import arrow.cont -import arrow.core.identity -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.runBlocking -import io.kotest.matchers.collections.shouldBeIn +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException -fun main() = runBlocking { +suspend fun test() { coroutineScope { cont { val fa = async { shift(1) } diff --git a/guide/test/ContTest.kt b/guide/test/ContTest.kt index ecb36e05805..6d1ceaf71f5 100644 --- a/guide/test/ContTest.kt +++ b/guide/test/ContTest.kt @@ -1,23 +1,18 @@ // This file was automatically generated from Cont.kt by Knit tool. Do not edit. package example.test -import org.junit.Test -import kotlinx.knit.test.* +import io.kotest.core.spec.style.StringSpec +import kotlin.time.Duration +import kotlin.time.ExperimentalTime -class ContTest { - @Test - fun testExampleCont01() { - captureOutput("ExampleCont01") { example.exampleCont01.main() }.verifyOutputLines( - "6", - "Option was empty" - ) +@OptIn(ExperimentalTime::class) +class ContTest : StringSpec({ + "ExampleCont01".config(timeout= Duration.seconds(1)) { + example.exampleCont01.test() } - @Test - fun testExampleCont02() { - captureOutput("ExampleCont02") { example.exampleCont02.main() }.verifyOutputLines( - "Hello, World!", - "1000" - ) + "ExampleCont02".config(timeout= Duration.seconds(1)) { + example.exampleCont02.test() } -} + +}) diff --git a/guide/test/ReadmeSpec.kt b/guide/test/ReadmeSpec.kt new file mode 100644 index 00000000000..2ab19ece3fc --- /dev/null +++ b/guide/test/ReadmeSpec.kt @@ -0,0 +1,34 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.test + +import io.kotest.core.spec.style.StringSpec +import kotlin.time.Duration +import kotlin.time.ExperimentalTime + +@OptIn(ExperimentalTime::class) +class ReadmeSpec : StringSpec({ + "ExampleReadme02".config(timeout= Duration.seconds(1)) { + example.exampleReadme02.test() + } + + "ExampleReadme04".config(timeout= Duration.seconds(1)) { + example.exampleReadme04.test() + } + + "ExampleReadme06".config(timeout= Duration.seconds(1)) { + example.exampleReadme06.test() + } + + "ExampleReadme07".config(timeout= Duration.seconds(1)) { + example.exampleReadme07.test() + } + + "ExampleReadme09".config(timeout= Duration.seconds(1)) { + example.exampleReadme09.test() + } + + "ExampleReadme10".config(timeout= Duration.seconds(1)) { + example.exampleReadme10.test() + } + +}) diff --git a/guide/test/ReadmeTest.kt b/guide/test/ReadmeTest.kt deleted file mode 100644 index 6e61107dadc..00000000000 --- a/guide/test/ReadmeTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -// This file was automatically generated from README.md by Knit tool. Do not edit. -package example.test - -import org.junit.Test -import kotlinx.knit.test.* - -class ReadmeTest { - @Test - fun testExampleReadme02() { - captureOutput("ExampleReadme02") { example.exampleReadme02.main() }.verifyOutputLines( - "Either.Left(EmptyPath)", - "Validated.Invalid(FileNotFound(path=not-found))", - "Ior.Left(FileNotFound(path=gradle.properties))", - "Option.None", - "null" - ) - } - - @Test - fun testExampleReadme04() { - captureOutput("ExampleReadme04") { example.exampleReadme04.main() }.verifyOutputLines( - "Either.Left(failed)", - "Either.Right(6)", - "Either.Left([d, e, l, i, a, f])", - "Either.Right(6)", - "Either.Right(Failure(java.lang.RuntimeException: Boom))" - ) - } - - @Test - fun testExampleReadme06() { - captureOutput("ExampleReadme06") { example.exampleReadme06.main() }.verifyOutputLines( - "I got cancelled", - "I got cancelled", - "I got cancelled", - "I got cancelled", - "error" - ) - } - - @Test - fun testExampleReadme07() { - captureOutput("ExampleReadme07") { example.exampleReadme07.main() }.verifyOutputLines( - "I lost the race...", - "error" - ) - } - - @Test - fun testExampleReadme09() { - captureOutput("ExampleReadme09") { example.exampleReadme09.main() }.verifyOutputLines( - "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", - "Cancelled due to shift: ShiftCancellationException(Shifted Continuation)", - "FileNotFound(path=failure)" - ) - } - - @Test - fun testExampleReadme10() { - captureOutput("ExampleReadme10") { example.exampleReadme10.main() }.also { lines -> - check(lines.isEmpty()) - } - } -} diff --git a/knit.properties b/knit.properties index a267d497a18..a93b94a1dc3 100644 --- a/knit.properties +++ b/knit.properties @@ -2,4 +2,7 @@ knit.dir=guide/example/ knit.package=example test.dir=guide/test/ -test.package=example.test \ No newline at end of file +test.package=example.test + +test.template=docs/knit.test.template +knit.include=docs/knit.code.include diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index 579028804e3..dfea0a1c76b 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -9,7 +9,6 @@ import arrow.core.Some import arrow.core.Validated import arrow.core.identity import arrow.core.nonFatalOrThrow -import kotlin.Result import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract import kotlin.coroutines.Continuation @@ -26,32 +25,24 @@ import kotlin.jvm.JvmInline * * * ```kotlin - * import arrow.core.* - * import arrow.cont - * import kotlinx.coroutines.runBlocking - * - * fun main() = runBlocking { + * suspend fun test() { * cont { * val x = Either.Right(1).bind() * val y = Validated.Valid(2).bind() * val z = Option(3).bind { "Option was empty" } * x + y + z - * }.fold(::println, ::println) + * }.fold({ fail("Shift can never be the result") }, { it shouldBe 6 }) * * cont { * val x = Either.Right(1).bind() * val y = Validated.Valid(2).bind() * val z: Int = None.bind { "Option was empty" } * x + y + z - * }.fold(::println, ::println) + * }.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") }) * } * ``` * - * ```text - * 6 - * Option was empty - * ``` - * + * */ public fun cont(f: suspend ContEffect.() -> A): Cont = ContImpl(f) @@ -71,27 +62,20 @@ public interface Cont { * ran the computation to completion it will [transform] the value [A] to [B]. * * ```kotlin - * import arrow.cont - * import kotlinx.coroutines.runBlocking - * - * fun main() = runBlocking { - * cont { + * suspend fun test() { + * val shift = cont { * shift("Hello, World!") * }.fold({ str: String -> str }, { int -> int.toString() }) - * .let(::println) + * shift shouldBe "Hello, World!" * - * cont { + * val res = cont { * 1000 * }.fold({ str: String -> str.length }, { int -> int }) - * .let(::println) + * res shouldBe 1000 * } * ``` * - * ```text - * Hello, World! - * 1000 - * ``` - * + * */ public suspend fun fold( recover: suspend (shifted: R) -> B, @@ -166,9 +150,7 @@ public interface Cont { } public fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont = - cont { - fold(recover, transform) - } + cont { fold(recover, transform) } public fun redeemWith( recover: suspend (R) -> Cont, @@ -177,9 +159,9 @@ public interface Cont { } public fun Iterable.traverseCont(transform: (A) -> Cont): Cont> = - cont { - map { transform(it).bind() } -} + cont { + map { transform(it).bind() } + } public fun Iterable>.sequence(): Cont> = traverseCont(::identity) @@ -255,35 +237,35 @@ private value class ContImpl(private val f: suspend ContEffect.() -> A) // We create a `Token` for fold Continuation, so we can properly differentiate between nested // folds override suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B = - suspendCoroutineUninterceptedOrReturn { cont -> - val token = Token() - val effect = - object : ContEffect { - // Shift away from this Continuation by intercepting it, and completing it with - // ShiftCancellationException - // This is needed because this function will never yield a result, - // so it needs to be cancelled to properly support coroutine cancellation - override suspend fun shift(r: R): B = + suspendCoroutineUninterceptedOrReturn { cont -> + val token = Token() + val effect = + object : ContEffect { + // Shift away from this Continuation by intercepting it, and completing it with + // ShiftCancellationException + // This is needed because this function will never yield a result, + // so it needs to be cancelled to properly support coroutine cancellation + override suspend fun shift(r: R): B = // Some interesting consequences of how Continuation Cancellation works in Kotlin. // We have to throw CancellationException to signal the Continuation was cancelled, and we // shifted away. // This however also means that the user can try/catch shift and recover from the // CancellationException and thus effectively recovering from the cancellation/shift. // This means try/catch is also capable of recovering from monadic errors. - // See: ContSpec - try/catch tests - throw Internal(token, r, recover as suspend (Any?) -> Any?) - } + // See: ContSpec - try/catch tests + throw Internal(token, r, recover as suspend (Any?) -> Any?) + } - try { - suspend { transform(f(effect)) } - .startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) - } catch (e: Internal) { - if (token == e.token) { - val f: suspend () -> B = { e.fold(e.shifted) as B } - f.startCoroutineUninterceptedOrReturn(cont) - } else throw e + try { + suspend { transform(f(effect)) } + .startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) + } catch (e: Internal) { + if (token == e.token) { + val f: suspend () -> B = { e.fold(e.shifted) as B } + f.startCoroutineUninterceptedOrReturn(cont) + } else throw e + } } - } } private class FoldContinuation( diff --git a/src/commonMain/kotlin/arrow/ior.kt b/src/commonMain/kotlin/arrow/ior.kt index 9a356cc3b76..61a7690cecc 100644 --- a/src/commonMain/kotlin/arrow/ior.kt +++ b/src/commonMain/kotlin/arrow/ior.kt @@ -24,8 +24,7 @@ public class IorEffect(semigroup: Semigroup, private val cont: ContEffect< private fun combine(other: E): E = leftState.updateAndGet { state -> if (state === EmptyValue) other else EmptyValue.unbox(state).combine(other) - } as - E + } as E public suspend fun Ior.bind(): B = when (this) { From e340f55168eaf7912d6653659ea742ef64020941 Mon Sep 17 00:00:00 2001 From: nomisRev Date: Wed, 10 Nov 2021 16:19:44 +0000 Subject: [PATCH 036/108] Auto update docs --- docs/-cont/arrow/-cont-effect/ensure.html | 4 ++-- docs/-cont/arrow/-cont-effect/index.html | 4 ++-- docs/-cont/arrow/-cont-effect/shift.html | 4 ++-- docs/-cont/arrow/-cont/attempt.html | 4 ++-- docs/-cont/arrow/-cont/flat-map.html | 4 ++-- docs/-cont/arrow/-cont/fold.html | 2 +- docs/-cont/arrow/-cont/handle-error-with.html | 4 ++-- docs/-cont/arrow/-cont/handle-error.html | 4 ++-- docs/-cont/arrow/-cont/index.html | 4 ++-- docs/-cont/arrow/-cont/map.html | 4 ++-- docs/-cont/arrow/-cont/redeem-with.html | 4 ++-- docs/-cont/arrow/-cont/redeem.html | 4 ++-- docs/-cont/arrow/-cont/to-either.html | 4 ++-- docs/-cont/arrow/-cont/to-ior.html | 4 ++-- docs/-cont/arrow/-cont/to-option.html | 4 ++-- docs/-cont/arrow/-cont/to-validated.html | 4 ++-- docs/-cont/arrow/-ior-effect/bind.html | 4 ++-- docs/-cont/arrow/-ior-effect/shift.html | 4 ++-- .../arrow/-shift-cancellation-exception/index.html | 4 ++-- docs/-cont/arrow/cont.html | 6 +++--- docs/-cont/arrow/sequence.html | 4 ++-- docs/-cont/arrow/traverse-cont.html | 4 ++-- docs/index.html | 13 ++----------- 23 files changed, 46 insertions(+), 55 deletions(-) diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html index a8b38ed7ccb..524480ca168 100644 --- a/docs/-cont/arrow/-cont-effect/ensure.html +++ b/docs/-cont/arrow/-cont-effect/ensure.html @@ -30,10 +30,10 @@

ensure

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html index f9818a0f99a..a59386971f7 100644 --- a/docs/-cont/arrow/-cont-effect/index.html +++ b/docs/-cont/arrow/-cont-effect/index.html @@ -120,10 +120,10 @@

Extensions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html index e37fed492f3..e3b480847b6 100644 --- a/docs/-cont/arrow/-cont-effect/shift.html +++ b/docs/-cont/arrow/-cont-effect/shift.html @@ -30,10 +30,10 @@

shift

Short-circuit the Cont computation with value R.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html index dbc130e2c8d..dd349d40d75 100644 --- a/docs/-cont/arrow/-cont/attempt.html +++ b/docs/-cont/arrow/-cont/attempt.html @@ -30,10 +30,10 @@

attempt

Runs the Cont and captures any NonFatal exception into Result.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/flat-map.html b/docs/-cont/arrow/-cont/flat-map.html index 0bf7522ee34..8d77d603941 100644 --- a/docs/-cont/arrow/-cont/flat-map.html +++ b/docs/-cont/arrow/-cont/flat-map.html @@ -30,10 +30,10 @@

flatMap

Maps the values A with the transform function into another Cont effect.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/fold.html b/docs/-cont/arrow/-cont/fold.html index c7696b3f4b3..f9745e94be5 100644 --- a/docs/-cont/arrow/-cont/fold.html +++ b/docs/-cont/arrow/-cont/fold.html @@ -28,7 +28,7 @@

fold

abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
-

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
.let(::println)

cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
.let(::println)
}
Hello, World!
1000
+

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

suspend fun test() {
val shift = cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
shift shouldBe "Hello, World!"

val res = cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
res shouldBe 1000
}
diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html index 64c432c917f..c24d525da89 100644 --- a/docs/-cont/arrow/-cont/handle-error-with.html +++ b/docs/-cont/arrow/-cont/handle-error-with.html @@ -30,10 +30,10 @@

handleError

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html index 035a6246e7e..22afdccfcc5 100644 --- a/docs/-cont/arrow/-cont/handle-error.html +++ b/docs/-cont/arrow/-cont/handle-error.html @@ -30,10 +30,10 @@

handleError<

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html index 715322fc7ad..b6de9e096e2 100644 --- a/docs/-cont/arrow/-cont/index.html +++ b/docs/-cont/arrow/-cont/index.html @@ -259,10 +259,10 @@

Extensions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/map.html b/docs/-cont/arrow/-cont/map.html index 4e3ee894322..d126007c562 100644 --- a/docs/-cont/arrow/-cont/map.html +++ b/docs/-cont/arrow/-cont/map.html @@ -30,10 +30,10 @@

map

Maps the values A with the transform function into B.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html index f78188d45a8..c8e16add54d 100644 --- a/docs/-cont/arrow/-cont/redeem-with.html +++ b/docs/-cont/arrow/-cont/redeem-with.html @@ -30,10 +30,10 @@

redeemWith

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html index 6bef5b31371..4d68af9fbb6 100644 --- a/docs/-cont/arrow/-cont/redeem.html +++ b/docs/-cont/arrow/-cont/redeem.html @@ -30,10 +30,10 @@

redeem

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-either.html b/docs/-cont/arrow/-cont/to-either.html index 2247d802115..6d9560f5926 100644 --- a/docs/-cont/arrow/-cont/to-either.html +++ b/docs/-cont/arrow/-cont/to-either.html @@ -30,10 +30,10 @@

toEither

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-ior.html b/docs/-cont/arrow/-cont/to-ior.html index 4b486f18ab0..bb36145b5e2 100644 --- a/docs/-cont/arrow/-cont/to-ior.html +++ b/docs/-cont/arrow/-cont/to-ior.html @@ -30,10 +30,10 @@

toIor

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html index 4b33d9157a0..6f2c36452ad 100644 --- a/docs/-cont/arrow/-cont/to-option.html +++ b/docs/-cont/arrow/-cont/to-option.html @@ -30,10 +30,10 @@

toOption

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-validated.html b/docs/-cont/arrow/-cont/to-validated.html index 6d52dd61b70..794a850a02e 100644 --- a/docs/-cont/arrow/-cont/to-validated.html +++ b/docs/-cont/arrow/-cont/to-validated.html @@ -30,10 +30,10 @@

toValidated<

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html index 35186b2813c..df44eaf5d2b 100644 --- a/docs/-cont/arrow/-ior-effect/bind.html +++ b/docs/-cont/arrow/-ior-effect/bind.html @@ -30,10 +30,10 @@

bind

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html index cb2995a33f1..4893e7c465b 100644 --- a/docs/-cont/arrow/-ior-effect/shift.html +++ b/docs/-cont/arrow/-ior-effect/shift.html @@ -30,10 +30,10 @@

shift

Short-circuit the Cont computation with value R.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html index 03434b19668..55b3735a20b 100644 --- a/docs/-cont/arrow/-shift-cancellation-exception/index.html +++ b/docs/-cont/arrow/-shift-cancellation-exception/index.html @@ -56,10 +56,10 @@

Properties

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/cont.html b/docs/-cont/arrow/cont.html index 7139a759339..7dccae53842 100644 --- a/docs/-cont/arrow/cont.html +++ b/docs/-cont/arrow/cont.html @@ -28,12 +28,12 @@

cont

fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
-

DSL for constructing Cont values

import arrow.core.*
import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)
}
6
Option was empty
+

DSL for constructing Cont values

suspend fun test() {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold({ fail("Shift can never be the result") }, { it shouldBe 6 })

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") })
}

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/sequence.html b/docs/-cont/arrow/sequence.html index 9ce0d2ea699..af6f9147118 100644 --- a/docs/-cont/arrow/sequence.html +++ b/docs/-cont/arrow/sequence.html @@ -30,10 +30,10 @@

sequence

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/traverse-cont.html b/docs/-cont/arrow/traverse-cont.html index d575d37d131..f4b34f139a3 100644 --- a/docs/-cont/arrow/traverse-cont.html +++ b/docs/-cont/arrow/traverse-cont.html @@ -30,10 +30,10 @@

traverseCont

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/index.html b/docs/index.html index 6b733854438..479e6fd1dd7 100644 --- a/docs/index.html +++ b/docs/index.html @@ -22,17 +22,8 @@

Cont

-
  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensure(!path.isNullOrBlank()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensure(!path.isNullOrBlank()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

Packages

From a11ae4c9a77522e1dc86a99519a3af787c40daae Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 10 Nov 2021 17:50:00 +0100 Subject: [PATCH 037/108] Property based doc testing --- docs/knit.code.include | 2 ++ guide/example/example-cont-01.kt | 2 ++ guide/example/example-cont-02.kt | 2 ++ guide/example/example-cont-03.kt | 20 ++++++++++++++++++++ guide/example/example-readme-01.kt | 2 ++ guide/example/example-readme-02.kt | 2 ++ guide/example/example-readme-03.kt | 2 ++ guide/example/example-readme-04.kt | 2 ++ guide/example/example-readme-05.kt | 2 ++ guide/example/example-readme-06.kt | 2 ++ guide/example/example-readme-07.kt | 2 ++ guide/example/example-readme-08.kt | 2 ++ guide/example/example-readme-09.kt | 2 ++ guide/example/example-readme-10.kt | 2 ++ guide/test/ContTest.kt | 4 ++++ src/commonMain/kotlin/arrow/Cont.kt | 13 ++++++++++++- 16 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 guide/example/example-cont-03.kt diff --git a/docs/knit.code.include b/docs/knit.code.include index d809cd1f24b..6f0ce786939 100644 --- a/docs/knit.code.include +++ b/docs/knit.code.include @@ -10,3 +10,5 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* diff --git a/guide/example/example-cont-01.kt b/guide/example/example-cont-01.kt index 97431fe9ae5..661f94837ce 100644 --- a/guide/example/example-cont-01.kt +++ b/guide/example/example-cont-01.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun test() { cont { diff --git a/guide/example/example-cont-02.kt b/guide/example/example-cont-02.kt index 09f2fbb5e25..32f66440687 100644 --- a/guide/example/example-cont-02.kt +++ b/guide/example/example-cont-02.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun test() { val shift = cont { diff --git a/guide/example/example-cont-03.kt b/guide/example/example-cont-03.kt new file mode 100644 index 00000000000..986d6e1a59b --- /dev/null +++ b/guide/example/example-cont-03.kt @@ -0,0 +1,20 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont03 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* + +suspend fun test() = checkAll(Arb.string()) { str -> + cont { + shift(str) + }.fold({ it shouldBe str }, { fail("Computation never finishes") }) +} diff --git a/guide/example/example-readme-01.kt b/guide/example/example-readme-01.kt index 19aa895ee1e..9d750458c8a 100644 --- a/guide/example/example-readme-01.kt +++ b/guide/example/example-readme-01.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* object EmptyPath diff --git a/guide/example/example-readme-02.kt b/guide/example/example-readme-02.kt index 957192196e4..df0f5d3be5c 100644 --- a/guide/example/example-readme-02.kt +++ b/guide/example/example-readme-02.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* import java.io.* diff --git a/guide/example/example-readme-03.kt b/guide/example/example-readme-03.kt index ddb95522905..bbecd3f069d 100644 --- a/guide/example/example-readme-03.kt +++ b/guide/example/example-readme-03.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun Cont.toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } diff --git a/guide/example/example-readme-04.kt b/guide/example/example-readme-04.kt index 255794efa5e..921b2c2258a 100644 --- a/guide/example/example-readme-04.kt +++ b/guide/example/example-readme-04.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* val failed: Cont = cont { shift("failed") } diff --git a/guide/example/example-readme-05.kt b/guide/example/example-readme-05.kt index 3fbea223a1e..da43549f87e 100644 --- a/guide/example/example-readme-05.kt +++ b/guide/example/example-readme-05.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun parZip(): Unit = cont { parZip({ diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt index fd0521cd323..358feb9197e 100644 --- a/guide/example/example-readme-06.kt +++ b/guide/example/example-readme-06.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun test() { val exits = (0..3).map { CompletableDeferred() } diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt index 2ed36dbc47c..c951182b1dc 100644 --- a/guide/example/example-readme-07.kt +++ b/guide/example/example-readme-07.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun test() { val exit = CompletableDeferred() diff --git a/guide/example/example-readme-08.kt b/guide/example/example-readme-08.kt index a387444e26f..8998ede5542 100644 --- a/guide/example/example-readme-08.kt +++ b/guide/example/example-readme-08.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* import java.io.* diff --git a/guide/example/example-readme-09.kt b/guide/example/example-readme-09.kt index 91f4e756313..37bf146385b 100644 --- a/guide/example/example-readme-09.kt +++ b/guide/example/example-readme-09.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* import java.io.* diff --git a/guide/example/example-readme-10.kt b/guide/example/example-readme-10.kt index 3ed2fe57934..3e769a31a64 100644 --- a/guide/example/example-readme-10.kt +++ b/guide/example/example-readme-10.kt @@ -10,6 +10,8 @@ import io.kotest.assertions.* import io.kotest.matchers.* import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* suspend fun test() { coroutineScope { diff --git a/guide/test/ContTest.kt b/guide/test/ContTest.kt index 6d1ceaf71f5..9b0a50e6406 100644 --- a/guide/test/ContTest.kt +++ b/guide/test/ContTest.kt @@ -15,4 +15,8 @@ class ContTest : StringSpec({ example.exampleCont02.test() } + "ExampleCont03".config(timeout= Duration.seconds(1)) { + example.exampleCont03.test() + } + }) diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index dfea0a1c76b..3efbe53a1e5 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -167,7 +167,18 @@ public fun Iterable>.sequence(): Cont> = traverseCo /** Context of the [Cont] DSL. */ public interface ContEffect { - /** Short-circuit the [Cont] computation with value [R]. */ + /** + * Short-circuit the [Cont] computation with value [R]. + * ```kotlin + * suspend fun test() = checkAll(Arb.string()) { str -> + * cont { + * shift(str) + * }.fold({ it shouldBe str }, { fail("Computation never finishes") }) + * } + * ``` + * + * + */ public suspend fun shift(r: R): B public suspend fun Cont.bind(): B = fold(this@ContEffect::shift, ::identity) From 98a6fb3ef0df21a3569194d72c4a5ac8f04b89c2 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 10 Nov 2021 19:49:29 +0100 Subject: [PATCH 038/108] toResult compiler bug --- docs/knit.code.include | 1 + guide/example/example-cont-01.kt | 1 + guide/example/example-cont-02.kt | 1 + guide/example/example-cont-03.kt | 1 + guide/example/example-cont-04.kt | 26 ++++ guide/example/example-cont-05.kt | 22 +++ guide/example/example-cont-06.kt | 22 +++ guide/example/example-cont-07.kt | 23 +++ guide/example/example-cont-08.kt | 23 +++ guide/example/example-cont-09.kt | 22 +++ guide/example/example-cont-10.kt | 21 +++ guide/example/example-readme-01.kt | 1 + guide/example/example-readme-02.kt | 1 + guide/example/example-readme-03.kt | 1 + guide/example/example-readme-04.kt | 1 + guide/example/example-readme-05.kt | 1 + guide/example/example-readme-06.kt | 1 + guide/example/example-readme-07.kt | 1 + guide/example/example-readme-08.kt | 1 + guide/example/example-readme-09.kt | 1 + guide/example/example-readme-10.kt | 1 + guide/test/ContTest.kt | 28 ++++ libs.versions.toml | 1 + src/commonMain/kotlin/arrow/Cont.kt | 217 +++++++++++++++++++++------- src/commonMain/kotlin/arrow/ior.kt | 3 +- 25 files changed, 365 insertions(+), 57 deletions(-) create mode 100644 guide/example/example-cont-04.kt create mode 100644 guide/example/example-cont-05.kt create mode 100644 guide/example/example-cont-06.kt create mode 100644 guide/example/example-cont-07.kt create mode 100644 guide/example/example-cont-08.kt create mode 100644 guide/example/example-cont-09.kt create mode 100644 guide/example/example-cont-10.kt diff --git a/docs/knit.code.include b/docs/knit.code.include index 6f0ce786939..e658f50213a 100644 --- a/docs/knit.code.include +++ b/docs/knit.code.include @@ -12,3 +12,4 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* diff --git a/guide/example/example-cont-01.kt b/guide/example/example-cont-01.kt index 661f94837ce..187696e075e 100644 --- a/guide/example/example-cont-01.kt +++ b/guide/example/example-cont-01.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() { cont { diff --git a/guide/example/example-cont-02.kt b/guide/example/example-cont-02.kt index 32f66440687..5f80316335f 100644 --- a/guide/example/example-cont-02.kt +++ b/guide/example/example-cont-02.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() { val shift = cont { diff --git a/guide/example/example-cont-03.kt b/guide/example/example-cont-03.kt index 986d6e1a59b..d0b0c267b2c 100644 --- a/guide/example/example-cont-03.kt +++ b/guide/example/example-cont-03.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() = checkAll(Arb.string()) { str -> cont { diff --git a/guide/example/example-cont-04.kt b/guide/example/example-cont-04.kt new file mode 100644 index 00000000000..8876b19e613 --- /dev/null +++ b/guide/example/example-cont-04.kt @@ -0,0 +1,26 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont04 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +fun Either.toCont(): Cont = cont { + fold({ e -> shift(e) }, ::identity) +} + +suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + cont { + val x: Int = either.toCont().bind() + x + }.toEither() shouldBe either +} diff --git a/guide/example/example-cont-05.kt b/guide/example/example-cont-05.kt new file mode 100644 index 00000000000..c5cfebf13e8 --- /dev/null +++ b/guide/example/example-cont-05.kt @@ -0,0 +1,22 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont05 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + cont { + val x: Int = either.bind() + x + }.toEither() shouldBe either +} diff --git a/guide/example/example-cont-06.kt b/guide/example/example-cont-06.kt new file mode 100644 index 00000000000..abfe8e0b87d --- /dev/null +++ b/guide/example/example-cont-06.kt @@ -0,0 +1,22 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont06 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated -> + cont { + val x: Int = validated.bind() + x + }.toValidated() shouldBe validated +} diff --git a/guide/example/example-cont-07.kt b/guide/example/example-cont-07.kt new file mode 100644 index 00000000000..038455bfaae --- /dev/null +++ b/guide/example/example-cont-07.kt @@ -0,0 +1,23 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont07 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +private val default = "failed" +suspend fun test() = checkAll(Arb.result(Arb.int())) { result -> + cont { + val x: Int = result.bind { _: Throwable -> default } + x + }.toResult { Result.failure(RuntimeException()) }.getOrElse { default } shouldBe result.getOrElse { default } +} diff --git a/guide/example/example-cont-08.kt b/guide/example/example-cont-08.kt new file mode 100644 index 00000000000..9ffba48a522 --- /dev/null +++ b/guide/example/example-cont-08.kt @@ -0,0 +1,23 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont08 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +private val default = "failed" +suspend fun test() = checkAll(Arb.option(Arb.int())) { option -> + cont { + val x: Int = option.bind { default } + x + }.toOption { None }.getOrElse { default } shouldBe option.getOrElse { default } +} diff --git a/guide/example/example-cont-09.kt b/guide/example/example-cont-09.kt new file mode 100644 index 00000000000..b39d375b0e2 --- /dev/null +++ b/guide/example/example-cont-09.kt @@ -0,0 +1,22 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont09 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int -> + cont { + ensure(condition) { failure } + int + }.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure) +} diff --git a/guide/example/example-cont-10.kt b/guide/example/example-cont-10.kt new file mode 100644 index 00000000000..29d6b059743 --- /dev/null +++ b/guide/example/example-cont-10.kt @@ -0,0 +1,21 @@ +// This file was automatically generated from Cont.kt by Knit tool. Do not edit. +package example.exampleCont10 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? -> + cont { + ensureNotNull(int) { failure } + }.toEither() shouldBe (int?.right() ?: failure.left()) +} diff --git a/guide/example/example-readme-01.kt b/guide/example/example-readme-01.kt index 9d750458c8a..cf341cdfd0b 100644 --- a/guide/example/example-readme-01.kt +++ b/guide/example/example-readme-01.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* object EmptyPath diff --git a/guide/example/example-readme-02.kt b/guide/example/example-readme-02.kt index df0f5d3be5c..b9c6a29282e 100644 --- a/guide/example/example-readme-02.kt +++ b/guide/example/example-readme-02.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* import java.io.* diff --git a/guide/example/example-readme-03.kt b/guide/example/example-readme-03.kt index bbecd3f069d..403433687d1 100644 --- a/guide/example/example-readme-03.kt +++ b/guide/example/example-readme-03.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun Cont.toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } diff --git a/guide/example/example-readme-04.kt b/guide/example/example-readme-04.kt index 921b2c2258a..a356dd532e4 100644 --- a/guide/example/example-readme-04.kt +++ b/guide/example/example-readme-04.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* val failed: Cont = cont { shift("failed") } diff --git a/guide/example/example-readme-05.kt b/guide/example/example-readme-05.kt index da43549f87e..82b16b797f6 100644 --- a/guide/example/example-readme-05.kt +++ b/guide/example/example-readme-05.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun parZip(): Unit = cont { parZip({ diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt index 358feb9197e..ad92add5ba3 100644 --- a/guide/example/example-readme-06.kt +++ b/guide/example/example-readme-06.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() { val exits = (0..3).map { CompletableDeferred() } diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt index c951182b1dc..700d99711f4 100644 --- a/guide/example/example-readme-07.kt +++ b/guide/example/example-readme-07.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() { val exit = CompletableDeferred() diff --git a/guide/example/example-readme-08.kt b/guide/example/example-readme-08.kt index 8998ede5542..eb4db930d7f 100644 --- a/guide/example/example-readme-08.kt +++ b/guide/example/example-readme-08.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* import java.io.* diff --git a/guide/example/example-readme-09.kt b/guide/example/example-readme-09.kt index 37bf146385b..0d9ac3ba8b7 100644 --- a/guide/example/example-readme-09.kt +++ b/guide/example/example-readme-09.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* import java.io.* diff --git a/guide/example/example-readme-10.kt b/guide/example/example-readme-10.kt index 3e769a31a64..e1fae7ee600 100644 --- a/guide/example/example-readme-10.kt +++ b/guide/example/example-readme-10.kt @@ -12,6 +12,7 @@ import io.kotest.matchers.types.* import kotlin.coroutines.cancellation.CancellationException import io.kotest.property.* import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* suspend fun test() { coroutineScope { diff --git a/guide/test/ContTest.kt b/guide/test/ContTest.kt index 9b0a50e6406..4b56fcfe86d 100644 --- a/guide/test/ContTest.kt +++ b/guide/test/ContTest.kt @@ -19,4 +19,32 @@ class ContTest : StringSpec({ example.exampleCont03.test() } + "ExampleCont04".config(timeout= Duration.seconds(1)) { + example.exampleCont04.test() + } + + "ExampleCont05".config(timeout= Duration.seconds(1)) { + example.exampleCont05.test() + } + + "ExampleCont06".config(timeout= Duration.seconds(1)) { + example.exampleCont06.test() + } + + "ExampleCont07".config(timeout= Duration.seconds(1)) { + example.exampleCont07.test() + } + + "ExampleCont08".config(timeout= Duration.seconds(1)) { + example.exampleCont08.test() + } + + "ExampleCont09".config(timeout= Duration.seconds(1)) { + example.exampleCont09.test() + } + + "ExampleCont10".config(timeout= Duration.seconds(1)) { + example.exampleCont10.test() + } + }) diff --git a/libs.versions.toml b/libs.versions.toml index ad2a5801923..109fa86afea 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -12,6 +12,7 @@ knit = "0.2.3" [libraries] arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } +arrow-core-test = { module = "io.arrow-kt:arrow-core-test", version.ref = "arrow" } arrow-optics = { module = "io.arrow-kt:arrow-optics", version.ref = "arrow" } arrow-fx = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" } coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index 3efbe53a1e5..d8b7f8c6915 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -116,6 +116,13 @@ public interface Cont { public suspend fun toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } + /** + * [fold] the [Cont] into an [Result]. Where the shifted value [R] is mapped to [Result] by the + * provided function [orElse], and result value [A] is mapped to [Result.success]. + */ + public suspend fun toResult(orElse: suspend (R) -> Result): Result = + fold(orElse) { a -> Result.success(a) } + /** * [fold] the [Cont] into an [Option]. Where the shifted value [R] is mapped to [Option] by the * provided function [orElse], and result value [A] is mapped to [Some]. @@ -131,16 +138,6 @@ public interface Cont { } } - /** Maps the values [A] with the [transform] function into [B]. */ - public fun map(transform: suspend (A) -> B): Cont = cont { - fold(this::shift, transform) - } - - /** Maps the values [A] with the [transform] function into another [Cont] effect. */ - public fun flatMap(transform: suspend (A) -> Cont): Cont = cont { - fold(this::shift, transform).bind() - } - public fun handleError(recover: suspend (R) -> A): Cont = cont { fold(recover, ::identity) } @@ -150,7 +147,9 @@ public interface Cont { } public fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont = - cont { fold(recover, transform) } + cont { + fold(recover, transform) + } public fun redeemWith( recover: suspend (R) -> Cont, @@ -158,13 +157,6 @@ public interface Cont { ): Cont = cont { fold(recover, transform).bind() } } -public fun Iterable.traverseCont(transform: (A) -> Cont): Cont> = - cont { - map { transform(it).bind() } - } - -public fun Iterable>.sequence(): Cont> = traverseCont(::identity) - /** Context of the [Cont] DSL. */ public interface ContEffect { /** @@ -181,44 +173,156 @@ public interface ContEffect { */ public suspend fun shift(r: R): B + /** + * Runs the [Cont] to finish, returning [B] or [shift] in case of [R]. + * + * ```kotlin + * fun Either.toCont(): Cont = cont { + * fold({ e -> shift(e) }, ::identity) + * } + * + * suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + * cont { + * val x: Int = either.toCont().bind() + * x + * }.toEither() shouldBe either + * } + * ``` + * + * + */ public suspend fun Cont.bind(): B = fold(this@ContEffect::shift, ::identity) + /** + * Folds [Either] into [Cont], by returning [B] or a shift with [R]. + * + * ```kotlin + * suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either -> + * cont { + * val x: Int = either.bind() + * x + * }.toEither() shouldBe either + * } + * ``` + * + * + */ public suspend fun Either.bind(): B = when (this) { is Either.Left -> shift(value) is Either.Right -> value } + /** + * Folds [Validated] into [Cont], by returning [B] or a shift with [R]. + * + * ```kotlin + * suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated -> + * cont { + * val x: Int = validated.bind() + * x + * }.toValidated() shouldBe validated + * } + * ``` + * + * + */ public suspend fun Validated.bind(): B = when (this) { is Validated.Valid -> value is Validated.Invalid -> shift(value) } + /** + * Folds [Result] into [Cont], by returning [B] or a transforming [Throwable] into [R] and + * shifting the result. + * + * ```kotlin + * private val default = "failed" + * suspend fun test() = checkAll(Arb.result(Arb.int())) { result -> + * cont { + * val x: Int = result.bind { _: Throwable -> default } + * x + * }.toResult { Result.failure(RuntimeException()) }.getOrElse { default } shouldBe result.getOrElse { default } + * } + * ``` + * + * + */ public suspend fun Result.bind(transform: (Throwable) -> R): B = fold(::identity) { throwable -> shift(transform(throwable)) } + /** + * Folds [Option] into [Cont], by returning [B] or a transforming [None] into [R] and shifting the + * result. + * + * ```kotlin + * private val default = "failed" + * suspend fun test() = checkAll(Arb.option(Arb.int())) { option -> + * cont { + * val x: Int = option.bind { default } + * x + * }.toOption { None }.getOrElse { default } shouldBe option.getOrElse { default } + * } + * ``` + * + * + */ public suspend fun Option.bind(shift: () -> R): B = when (this) { None -> shift(shift()) is Some -> value } - // Monadic version of kotlin.require - public suspend fun ensure(value: Boolean, shift: () -> R): Unit = - if (value) Unit else shift(shift()) + /** + * ensure that condition is `true`, if it's `false` it will `shift` with the provided value [R]. + * Monadic version of [kotlin.require]. + * + * ```kotlin + * suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int -> + * cont { + * ensure(condition) { failure } + * int + * }.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure) + * } + * ``` + * + * + */ + public suspend fun ensure(condition: Boolean, shift: () -> R): Unit = + if (condition) Unit else shift(shift()) } -// Monadic version of kotlin.requireNotNull +/** + * Ensure that [value] is not `null`. if it's non-null it will be smart-casted and returned if it's + * `false` it will `shift` with the provided value [R]. Monadic version of [kotlin.requireNotNull]. + * + * ```kotlin + * suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? -> + * cont { + * ensureNotNull(int) { failure } + * }.toEither() shouldBe (int?.right() ?: failure.left()) + * } + * ``` + * + * + */ @OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so top-level. public suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B { contract { returns() implies (value != null) } return value ?: shift(shift()) } +/** + * **AVOID USING THIS TYPE, it's meant for low-level cancellation code** When in need in low-level + * code, you can use this type to differentiate between a foreign [CancellationException] and the + * one from [Cont]. + */ public sealed class ShiftCancellationException : CancellationException("Shifted Continuation") -private class Internal(val token: Token, val shifted: Any?, val fold: suspend (Any?) -> Any?) : +// Holds `R` and `suspend (R) -> B`, the exception that wins the race, will get to execute +// `recover`. +private class Internal(val token: Token, val shifted: Any?, val recover: suspend (Any?) -> Any?) : ShiftCancellationException() { override fun toString(): String = "ShiftCancellationException($message)" } @@ -239,60 +343,61 @@ private value class ContImpl(private val f: suspend ContEffect.() -> A) } } - override fun map(transform: suspend (A) -> B): Cont = ContImpl { transform(f()) } - - override fun flatMap(transform: suspend (A) -> Cont): Cont = ContImpl { - transform(f()).bind() - } - // We create a `Token` for fold Continuation, so we can properly differentiate between nested // folds override suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B = - suspendCoroutineUninterceptedOrReturn { cont -> - val token = Token() - val effect = - object : ContEffect { - // Shift away from this Continuation by intercepting it, and completing it with - // ShiftCancellationException - // This is needed because this function will never yield a result, - // so it needs to be cancelled to properly support coroutine cancellation - override suspend fun shift(r: R): B = + suspendCoroutineUninterceptedOrReturn { cont -> + val token = Token() + val effect = + object : ContEffect { + // Shift away from this Continuation by intercepting it, and completing it with + // ShiftCancellationException + // This is needed because this function will never yield a result, + // so it needs to be cancelled to properly support coroutine cancellation + override suspend fun shift(r: R): B = // Some interesting consequences of how Continuation Cancellation works in Kotlin. // We have to throw CancellationException to signal the Continuation was cancelled, and we // shifted away. // This however also means that the user can try/catch shift and recover from the // CancellationException and thus effectively recovering from the cancellation/shift. // This means try/catch is also capable of recovering from monadic errors. - // See: ContSpec - try/catch tests - throw Internal(token, r, recover as suspend (Any?) -> Any?) - } - - try { - suspend { transform(f(effect)) } - .startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) - } catch (e: Internal) { - if (token == e.token) { - val f: suspend () -> B = { e.fold(e.shifted) as B } - f.startCoroutineUninterceptedOrReturn(cont) - } else throw e + // See: ContSpec - try/catch tests + throw Internal(token, r, recover as suspend (Any?) -> Any?) } + + try { + suspend { transform(f(effect)) } + .startCoroutineUninterceptedOrReturn(FoldContinuation(token, cont.context, cont)) + } catch (e: Internal) { + if (token == e.token) { + val f: suspend () -> B = { e.recover(e.shifted) as B } + f.startCoroutineUninterceptedOrReturn(cont) + } else throw e } + } } +/** + * Continuation that runs the `recover` function, after attempting to calculate [B]. In case we + * encounter a `shift` after suspension, we will receive [Result.failure] with + * [ShiftCancellationException]. In that case we still need to run `suspend (R) -> B`, which is what + * we do inside the body of this `Continuation`, and we complete the [parent] [Continuation] with + * the result. + */ private class FoldContinuation( private val token: Token, override val context: CoroutineContext, - private val cont: Continuation + private val parent: Continuation ) : Continuation { override fun resumeWith(result: Result) { - result.fold(cont::resume) { throwable -> + result.fold(parent::resume) { throwable -> if (throwable is Internal && token == throwable.token) { - val f: suspend () -> B = { throwable.fold(throwable.shifted) as B } - when (val res = f.startCoroutineUninterceptedOrReturn(cont)) { + val f: suspend () -> B = { throwable.recover(throwable.shifted) as B } + when (val res = f.startCoroutineUninterceptedOrReturn(parent)) { COROUTINE_SUSPENDED -> Unit - else -> cont.resume(res as B) + else -> parent.resume(res as B) } - } else cont.resumeWith(result) + } else parent.resumeWith(result) } } } diff --git a/src/commonMain/kotlin/arrow/ior.kt b/src/commonMain/kotlin/arrow/ior.kt index 61a7690cecc..9a356cc3b76 100644 --- a/src/commonMain/kotlin/arrow/ior.kt +++ b/src/commonMain/kotlin/arrow/ior.kt @@ -24,7 +24,8 @@ public class IorEffect(semigroup: Semigroup, private val cont: ContEffect< private fun combine(other: E): E = leftState.updateAndGet { state -> if (state === EmptyValue) other else EmptyValue.unbox(state).combine(other) - } as E + } as + E public suspend fun Ior.bind(): B = when (this) { From 96f964ba787cb915660ed78d2fc46d8cca7ffebf Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 10 Nov 2021 20:16:04 +0100 Subject: [PATCH 039/108] More docs --- guide/example/example-cont-07.kt | 2 +- guide/example/example-cont-08.kt | 2 +- src/commonMain/kotlin/arrow/Cont.kt | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/guide/example/example-cont-07.kt b/guide/example/example-cont-07.kt index 038455bfaae..d3977d1a4af 100644 --- a/guide/example/example-cont-07.kt +++ b/guide/example/example-cont-07.kt @@ -19,5 +19,5 @@ suspend fun test() = checkAll(Arb.result(Arb.int())) { result -> cont { val x: Int = result.bind { _: Throwable -> default } x - }.toResult { Result.failure(RuntimeException()) }.getOrElse { default } shouldBe result.getOrElse { default } + }.fold({ default }, ::identity) shouldBe result.getOrElse { default } } diff --git a/guide/example/example-cont-08.kt b/guide/example/example-cont-08.kt index 9ffba48a522..0074b911dd2 100644 --- a/guide/example/example-cont-08.kt +++ b/guide/example/example-cont-08.kt @@ -19,5 +19,5 @@ suspend fun test() = checkAll(Arb.option(Arb.int())) { option -> cont { val x: Int = option.bind { default } x - }.toOption { None }.getOrElse { default } shouldBe option.getOrElse { default } + }.fold({ default }, ::identity) shouldBe option.getOrElse { default } } diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index d8b7f8c6915..7d9031d86c6 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -120,8 +120,8 @@ public interface Cont { * [fold] the [Cont] into an [Result]. Where the shifted value [R] is mapped to [Result] by the * provided function [orElse], and result value [A] is mapped to [Result.success]. */ - public suspend fun toResult(orElse: suspend (R) -> Result): Result = - fold(orElse) { a -> Result.success(a) } +// public suspend fun toResult(orElse: suspend (R) -> Result): Result = +// fold(orElse) { a -> Result.success(a) } /** * [fold] the [Cont] into an [Option]. Where the shifted value [R] is mapped to [Option] by the @@ -243,7 +243,7 @@ public interface ContEffect { * cont { * val x: Int = result.bind { _: Throwable -> default } * x - * }.toResult { Result.failure(RuntimeException()) }.getOrElse { default } shouldBe result.getOrElse { default } + * }.fold({ default }, ::identity) shouldBe result.getOrElse { default } * } * ``` * @@ -262,7 +262,7 @@ public interface ContEffect { * cont { * val x: Int = option.bind { default } * x - * }.toOption { None }.getOrElse { default } shouldBe option.getOrElse { default } + * }.fold({ default }, ::identity) shouldBe option.getOrElse { default } * } * ``` * From 3311bc9fba78bb09da9479b35a99393d375e402c Mon Sep 17 00:00:00 2001 From: nomisRev Date: Wed, 10 Nov 2021 19:19:11 +0000 Subject: [PATCH 040/108] Auto update docs --- docs/-cont/arrow/-cont-effect/bind.html | 28 +++++++++++- docs/-cont/arrow/-cont-effect/ensure.html | 8 ++-- docs/-cont/arrow/-cont-effect/index.html | 44 ++++++++++++++++--- docs/-cont/arrow/-cont-effect/shift.html | 6 +-- docs/-cont/arrow/-cont/attempt.html | 4 +- docs/-cont/arrow/-cont/handle-error-with.html | 4 +- docs/-cont/arrow/-cont/handle-error.html | 4 +- docs/-cont/arrow/-cont/index.html | 34 -------------- docs/-cont/arrow/-cont/redeem-with.html | 4 +- docs/-cont/arrow/-cont/redeem.html | 4 +- docs/-cont/arrow/-cont/to-option.html | 4 +- docs/-cont/arrow/-ior-effect/bind.html | 4 +- docs/-cont/arrow/-ior-effect/index.html | 36 +++++++++++++-- docs/-cont/arrow/-ior-effect/shift.html | 6 +-- docs/-cont/arrow/-option-effect/index.html | 40 ++++++++++++++++- docs/-cont/arrow/-option-effect/shift.html | 2 +- .../-shift-cancellation-exception/index.html | 6 +-- docs/-cont/arrow/ensure-not-null.html | 8 +++- docs/-cont/arrow/index.html | 44 ++++--------------- docs/-cont/package-list | 4 -- docs/navigation.html | 10 +---- docs/scripts/navigation-pane.json | 2 +- docs/scripts/pages.json | 2 +- 23 files changed, 181 insertions(+), 127 deletions(-) diff --git a/docs/-cont/arrow/-cont-effect/bind.html b/docs/-cont/arrow/-cont-effect/bind.html index 5a739ee4f1f..98ebb96ee26 100644 --- a/docs/-cont/arrow/-cont-effect/bind.html +++ b/docs/-cont/arrow/-cont-effect/bind.html @@ -26,9 +26,33 @@

bind

-
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
+
open suspend fun <B> Cont<R, B>.bind(): B
-
+

Runs the Cont to finish, returning B or shift in case of R.

fun <E, A> Either<E, A>.toCont(): Cont<E, A> = cont {
fold({ e -> shift(e) }, ::identity)
}

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.toCont().bind()
x
}.toEither() shouldBe either
}
+
+ +
+
open suspend fun <B> Either<R, B>.bind(): B
+
+

Folds Either into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.bind()
x
}.toEither() shouldBe either
}
+
+ +
+
open suspend fun <B> Validated<R, B>.bind(): B
+
+

Folds Validated into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated ->
cont<String, Int> {
val x: Int = validated.bind()
x
}.toValidated() shouldBe validated
}
+
+ +
+
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
+
+

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.result(Arb.int())) { result ->
cont<String, Int> {
val x: Int = result.bind { _: Throwable -> default }
x
}.fold({ default }, ::identity) shouldBe result.getOrElse { default }
}
+
+ +
+
open suspend fun <B> Option<B>.bind(shift: () -> R): B
+
+

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.option(Arb.int())) { option ->
cont<String, Int> {
val x: Int = option.bind { default }
x
}.fold({ default }, ::identity) shouldBe option.getOrElse { default }
}
diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html index 524480ca168..c2dfd49fe2a 100644 --- a/docs/-cont/arrow/-cont-effect/ensure.html +++ b/docs/-cont/arrow/-cont-effect/ensure.html @@ -26,14 +26,14 @@

ensure

-
open suspend fun ensure(value: Boolean, shift: () -> R)
+
open suspend fun ensure(condition: Boolean, shift: () -> R)
-
+

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int ->
cont<String, Int> {
ensure(condition) { failure }
int
}.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure)
}

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html index a59386971f7..d89134f86e0 100644 --- a/docs/-cont/arrow/-cont-effect/index.html +++ b/docs/-cont/arrow/-cont-effect/index.html @@ -38,9 +38,33 @@

Functions

-
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
+
open suspend fun <B> Cont<R, B>.bind(): B
-
+

Runs the Cont to finish, returning B or shift in case of R.

+
+ +
+
open suspend fun <B> Either<R, B>.bind(): B
+
+

Folds Either into Cont, by returning B or a shift with R.

+
+ +
+
open suspend fun <B> Validated<R, B>.bind(): B
+
+

Folds Validated into Cont, by returning B or a shift with R.

+
+ +
+
open suspend fun <B> Option<B>.bind(shift: () -> R): B
+
+

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

+
+ +
+
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
+
+

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

@@ -55,9 +79,9 @@

Functions

-
open suspend fun ensure(value: Boolean, shift: () -> R)
+
open suspend fun ensure(condition: Boolean, shift: () -> R)
-
+

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

@@ -111,7 +135,13 @@

Extensions

-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
+

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

+
+ +
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
@@ -120,10 +150,10 @@

Extensions

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html index e3b480847b6..da094c9d949 100644 --- a/docs/-cont/arrow/-cont-effect/shift.html +++ b/docs/-cont/arrow/-cont-effect/shift.html @@ -28,12 +28,12 @@

shift

abstract suspend fun <B> shift(r: R): B
-

Short-circuit the Cont computation with value R.

+

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html index dd349d40d75..7c7d1ed2884 100644 --- a/docs/-cont/arrow/-cont/attempt.html +++ b/docs/-cont/arrow/-cont/attempt.html @@ -30,10 +30,10 @@

attempt

Runs the Cont and captures any NonFatal exception into Result.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html index c24d525da89..f55aee4f7b2 100644 --- a/docs/-cont/arrow/-cont/handle-error-with.html +++ b/docs/-cont/arrow/-cont/handle-error-with.html @@ -30,10 +30,10 @@

handleError

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html index 22afdccfcc5..8da3cb874b3 100644 --- a/docs/-cont/arrow/-cont/handle-error.html +++ b/docs/-cont/arrow/-cont/handle-error.html @@ -30,10 +30,10 @@

handleError<

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html index b6de9e096e2..df0c7091b91 100644 --- a/docs/-cont/arrow/-cont/index.html +++ b/docs/-cont/arrow/-cont/index.html @@ -41,23 +41,6 @@

Functions

open fun attempt(): Cont<R, Result<A>>

Runs the Cont and captures any NonFatal exception into Result.

-
-
-
-
- -
-
-
flatMap -
Link copied to clipboard
-
-
-
- -
-
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
-
-

Maps the values A with the transform function into another Cont effect.

@@ -115,23 +98,6 @@

Functions

open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
-
-
- -
-
-
map -
Link copied to clipboard
-
-
-
- -
-
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
-
-

Maps the values A with the transform function into B.

diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html index c8e16add54d..7cb7847b1cf 100644 --- a/docs/-cont/arrow/-cont/redeem-with.html +++ b/docs/-cont/arrow/-cont/redeem-with.html @@ -30,10 +30,10 @@

redeemWith

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html index 4d68af9fbb6..7437745d7ca 100644 --- a/docs/-cont/arrow/-cont/redeem.html +++ b/docs/-cont/arrow/-cont/redeem.html @@ -30,10 +30,10 @@

redeem

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html index 6f2c36452ad..753225068c0 100644 --- a/docs/-cont/arrow/-cont/to-option.html +++ b/docs/-cont/arrow/-cont/to-option.html @@ -30,10 +30,10 @@

toOption

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html index df44eaf5d2b..35186b2813c 100644 --- a/docs/-cont/arrow/-ior-effect/bind.html +++ b/docs/-cont/arrow/-ior-effect/bind.html @@ -30,10 +30,10 @@

bind

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-ior-effect/index.html b/docs/-cont/arrow/-ior-effect/index.html index 3c843b41d8d..0887a33d5ab 100644 --- a/docs/-cont/arrow/-ior-effect/index.html +++ b/docs/-cont/arrow/-ior-effect/index.html @@ -38,9 +38,39 @@

Functions

-
open suspend fun <B> Cont<E, B>.bind(): B
open suspend fun <B> Either<E, B>.bind(): B
open suspend fun <B> Validated<E, B>.bind(): B
suspend fun <B> Ior<E, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> E): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
+
open suspend fun <B> Cont<E, B>.bind(): B
+
+

Runs the Cont to finish, returning B or shift in case of R.

+
+ +
+
open suspend fun <B> Either<E, B>.bind(): B
+
+

Folds Either into Cont, by returning B or a shift with R.

+
+ +
+
open suspend fun <B> Validated<E, B>.bind(): B
+
+

Folds Validated into Cont, by returning B or a shift with R.

+
+ +
+
suspend fun <B> Ior<E, B>.bind(): B
+
+ +
+
open suspend fun <B> Option<B>.bind(shift: () -> E): B
+
+

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

+
+ +
+
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
+
+

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

@@ -72,9 +102,9 @@

Functions

-
open suspend fun ensure(value: Boolean, shift: () -> E)
+
open suspend fun ensure(condition: Boolean, shift: () -> E)
-
+

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html index 4893e7c465b..d8f57d6bb04 100644 --- a/docs/-cont/arrow/-ior-effect/shift.html +++ b/docs/-cont/arrow/-ior-effect/shift.html @@ -28,12 +28,12 @@

shift

open suspend override fun <B> shift(r: E): B
-

Short-circuit the Cont computation with value R.

+

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/-option-effect/index.html b/docs/-cont/arrow/-option-effect/index.html index af5616b2587..5967c89a43f 100644 --- a/docs/-cont/arrow/-option-effect/index.html +++ b/docs/-cont/arrow/-option-effect/index.html @@ -38,9 +38,39 @@

Functions

-
open suspend fun <B> Cont<None, B>.bind(): B
open suspend fun <B> Either<None, B>.bind(): B
open suspend fun <B> Validated<None, B>.bind(): B
suspend fun <B> Option<B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> None): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
+
open suspend fun <B> Cont<None, B>.bind(): B
+
+

Runs the Cont to finish, returning B or shift in case of R.

+
+ +
+
open suspend fun <B> Either<None, B>.bind(): B
+
+

Folds Either into Cont, by returning B or a shift with R.

+
+ +
+
open suspend fun <B> Validated<None, B>.bind(): B
+
+

Folds Validated into Cont, by returning B or a shift with R.

+
+ +
+
suspend fun <B> Option<B>.bind(): B
+
+ +
+
open suspend fun <B> Option<B>.bind(shift: () -> None): B
+
+

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

+
+ +
+
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
+
+

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

@@ -55,9 +85,15 @@

Functions

-
suspend fun ensure(value: Boolean)
open suspend fun ensure(value: Boolean, shift: () -> None)
+
suspend fun ensure(value: Boolean)
+
+ +
+
open suspend fun ensure(condition: Boolean, shift: () -> None)
+
+

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

diff --git a/docs/-cont/arrow/-option-effect/shift.html b/docs/-cont/arrow/-option-effect/shift.html index 43dd27b480c..6b483953580 100644 --- a/docs/-cont/arrow/-option-effect/shift.html +++ b/docs/-cont/arrow/-option-effect/shift.html @@ -28,7 +28,7 @@

shift

open suspend override fun <B> shift(r: None): B
-

Short-circuit the Cont computation with value R.

+

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html index 55b3735a20b..693132ef49f 100644 --- a/docs/-cont/arrow/-shift-cancellation-exception/index.html +++ b/docs/-cont/arrow/-shift-cancellation-exception/index.html @@ -22,7 +22,7 @@

ShiftCancellationException

-
sealed class ShiftCancellationException : CancellationException
+
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

@@ -56,10 +56,10 @@

Properties

Sources

-
+
-
common source +
common source
Link copied to clipboard
diff --git a/docs/-cont/arrow/ensure-not-null.html b/docs/-cont/arrow/ensure-not-null.html index 511bbbb022d..9ca1f81a2cc 100644 --- a/docs/-cont/arrow/ensure-not-null.html +++ b/docs/-cont/arrow/ensure-not-null.html @@ -26,7 +26,13 @@

ensureNot
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
+

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? ->
cont<String, Int> {
ensureNotNull(int) { failure }
}.toEither() shouldBe (int?.right() ?: failure.left())
}

+
+ +
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
diff --git a/docs/-cont/arrow/index.html b/docs/-cont/arrow/index.html index bb47ee15bf0..9b475f49318 100644 --- a/docs/-cont/arrow/index.html +++ b/docs/-cont/arrow/index.html @@ -141,7 +141,7 @@

Types

sealed class ShiftCancellationException : CancellationException
-
+

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

@@ -192,9 +192,15 @@

Functions

-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
+ +
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
+
+

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

@@ -246,23 +252,6 @@

Functions

fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-
-
-
-
- -
-
-
sequence -
Link copied to clipboard
-
-
-
- -
-
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
-
-
@@ -280,23 +269,6 @@

Functions

suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
-
- -
-
-
traverseCont -
Link copied to clipboard
-
-
-
- -
-
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
-
-
diff --git a/docs/-cont/package-list b/docs/-cont/package-list index 0a3e95aedb1..dc9e4116bcc 100644 --- a/docs/-cont/package-list +++ b/docs/-cont/package-list @@ -8,17 +8,13 @@ $dokka.location:arrow//ensureNotNull/arrow.ContEffect[arrow.core.None]#TypeParam $dokka.location:arrow//ior/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[arrow.IorEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/ior.html $dokka.location:arrow//option/#kotlin.Function1[arrow.OptionEffect,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/option.html $dokka.location:arrow//restrictedCont/#kotlin.coroutines.SuspendFunction1[arrow.RestrictedContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/restricted-cont.html -$dokka.location:arrow//sequence/kotlin.collections.Iterable[arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#/PointingToDeclaration/-cont/arrow/sequence.html $dokka.location:arrow//toOption/arrow.Cont[arrow.core.None,TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/to-option.html -$dokka.location:arrow//traverseCont/kotlin.collections.Iterable[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/traverse-cont.html $dokka.location:arrow/Cont///PointingToDeclaration/-cont/arrow/-cont/index.html $dokka.location:arrow/Cont/attempt/#/PointingToDeclaration/-cont/arrow/-cont/attempt.html -$dokka.location:arrow/Cont/flatMap/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/flat-map.html $dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html $dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html $dokka.location:arrow/Cont/handleError/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/handle-error.html $dokka.location:arrow/Cont/handleErrorWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/handle-error-with.html -$dokka.location:arrow/Cont/map/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/map.html $dokka.location:arrow/Cont/redeem/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/redeem.html $dokka.location:arrow/Cont/redeemWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/redeem-with.html $dokka.location:arrow/Cont/toEither/#/PointingToDeclaration/-cont/arrow/-cont/to-either.html diff --git a/docs/navigation.html b/docs/navigation.html index 337b751d7f5..da048772463 100644 --- a/docs/navigation.html +++ b/docs/navigation.html @@ -38,18 +38,12 @@ - - diff --git a/docs/scripts/navigation-pane.json b/docs/scripts/navigation-pane.json index f734e4e721f..907bd5783fb 100644 --- a/docs/scripts/navigation-pane.json +++ b/docs/scripts/navigation-pane.json @@ -1 +1 @@ -[{"name":"Cont","description":null,"location":"index.html","searchKeys":["Cont"]},{"name":"arrow","description":null,"location":"-cont/arrow/index.html","searchKeys":["arrow"]},{"name":"Cont","description":null,"location":"-cont/arrow/-cont/index.html","searchKeys":["Cont"]},{"name":"cont()","description":null,"location":"-cont/arrow/cont.html","searchKeys":["cont()"]},{"name":"ContEffect","description":null,"location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect"]},{"name":"either()","description":null,"location":"-cont/arrow/either.html","searchKeys":["either()"]},{"name":"ensureNotNull()","description":null,"location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull()"]},{"name":"ior()","description":null,"location":"-cont/arrow/ior.html","searchKeys":["ior()"]},{"name":"IorEffect","description":null,"location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect"]},{"name":"option()","description":null,"location":"-cont/arrow/option.html","searchKeys":["option()"]},{"name":"OptionEffect","description":null,"location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect"]},{"name":"RestrictedCont","description":null,"location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont"]},{"name":"restrictedCont()","description":null,"location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont()"]},{"name":"RestrictedContEffect","description":null,"location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect"]},{"name":"sequence()","description":null,"location":"-cont/arrow/sequence.html","searchKeys":["sequence()"]},{"name":"ShiftCancellationException","description":null,"location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException"]},{"name":"toOption()","description":null,"location":"-cont/arrow/to-option.html","searchKeys":["toOption()"]},{"name":"traverseCont()","description":null,"location":"-cont/arrow/traverse-cont.html","searchKeys":["traverseCont()"]}] +[{"name":"Cont","description":null,"location":"index.html","searchKeys":["Cont"]},{"name":"arrow","description":null,"location":"-cont/arrow/index.html","searchKeys":["arrow"]},{"name":"Cont","description":null,"location":"-cont/arrow/-cont/index.html","searchKeys":["Cont"]},{"name":"cont()","description":null,"location":"-cont/arrow/cont.html","searchKeys":["cont()"]},{"name":"ContEffect","description":null,"location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect"]},{"name":"either()","description":null,"location":"-cont/arrow/either.html","searchKeys":["either()"]},{"name":"ensureNotNull()","description":null,"location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull()"]},{"name":"ior()","description":null,"location":"-cont/arrow/ior.html","searchKeys":["ior()"]},{"name":"IorEffect","description":null,"location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect"]},{"name":"option()","description":null,"location":"-cont/arrow/option.html","searchKeys":["option()"]},{"name":"OptionEffect","description":null,"location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect"]},{"name":"RestrictedCont","description":null,"location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont"]},{"name":"restrictedCont()","description":null,"location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont()"]},{"name":"RestrictedContEffect","description":null,"location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect"]},{"name":"ShiftCancellationException","description":null,"location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException"]},{"name":"toOption()","description":null,"location":"-cont/arrow/to-option.html","searchKeys":["toOption()"]}] diff --git a/docs/scripts/pages.json b/docs/scripts/pages.json index 446780cce5e..bc0f154c61d 100644 --- a/docs/scripts/pages.json +++ b/docs/scripts/pages.json @@ -1 +1 @@ -[{"name":"abstract fun fold(f: (R) -> B, g: (A) -> B): B","description":"arrow.RestrictedCont.fold","location":"-cont/arrow/-restricted-cont/fold.html","searchKeys":["fold","abstract fun fold(f: (R) -> B, g: (A) -> B): B","arrow.RestrictedCont.fold"]},{"name":"abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.ContEffect.shift","location":"-cont/arrow/-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.ContEffect.shift"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.RestrictedContEffect.shift","location":"-cont/arrow/-restricted-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.RestrictedContEffect.shift"]},{"name":"class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","description":"arrow.IorEffect","location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect","class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","arrow.IorEffect"]},{"name":"fun IorEffect(semigroup: Semigroup, cont: ContEffect)","description":"arrow.IorEffect.IorEffect","location":"-cont/arrow/-ior-effect/-ior-effect.html","searchKeys":["IorEffect","fun IorEffect(semigroup: Semigroup, cont: ContEffect)","arrow.IorEffect.IorEffect"]},{"name":"fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","description":"arrow.traverseCont","location":"-cont/arrow/traverse-cont.html","searchKeys":["traverseCont","fun Iterable.traverseCont(transform: (A) -> Cont): Cont>","arrow.traverseCont"]},{"name":"fun Iterable>.sequence(): Cont>","description":"arrow.sequence","location":"-cont/arrow/sequence.html","searchKeys":["sequence","fun Iterable>.sequence(): Cont>","arrow.sequence"]},{"name":"fun cont(f: suspend ContEffect.() -> A): Cont","description":"arrow.cont","location":"-cont/arrow/cont.html","searchKeys":["cont","fun cont(f: suspend ContEffect.() -> A): Cont","arrow.cont"]},{"name":"fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","description":"arrow.restrictedCont","location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont","fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","arrow.restrictedCont"]},{"name":"fun OptionEffect(cont: ContEffect)","description":"arrow.OptionEffect.OptionEffect","location":"-cont/arrow/-option-effect/-option-effect.html","searchKeys":["OptionEffect","fun OptionEffect(cont: ContEffect)","arrow.OptionEffect.OptionEffect"]},{"name":"interface Cont","description":"arrow.Cont","location":"-cont/arrow/-cont/index.html","searchKeys":["Cont","interface Cont","arrow.Cont"]},{"name":"interface ContEffect","description":"arrow.ContEffect","location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect","interface ContEffect","arrow.ContEffect"]},{"name":"interface RestrictedCont","description":"arrow.RestrictedCont","location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont","interface RestrictedCont","arrow.RestrictedCont"]},{"name":"interface RestrictedContEffect","description":"arrow.RestrictedContEffect","location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect","interface RestrictedContEffect","arrow.RestrictedContEffect"]},{"name":"open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.flatMap","location":"-cont/arrow/-restricted-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.flatMap"]},{"name":"open fun flatMap(transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.flatMap","location":"-cont/arrow/-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(transform: suspend (A) -> Cont): Cont","arrow.Cont.flatMap"]},{"name":"open fun map(f: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.map","location":"-cont/arrow/-restricted-cont/map.html","searchKeys":["map","open fun map(f: (A) -> B): RestrictedCont","arrow.RestrictedCont.map"]},{"name":"open fun map(transform: suspend (A) -> B): Cont","description":"arrow.Cont.map","location":"-cont/arrow/-cont/map.html","searchKeys":["map","open fun map(transform: suspend (A) -> B): Cont","arrow.Cont.map"]},{"name":"open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.redeem","location":"-cont/arrow/-restricted-cont/redeem.html","searchKeys":["redeem","open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","arrow.RestrictedCont.redeem"]},{"name":"open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","description":"arrow.Cont.redeem","location":"-cont/arrow/-cont/redeem.html","searchKeys":["redeem","open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","arrow.Cont.redeem"]},{"name":"open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.redeemWith","location":"-cont/arrow/-restricted-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.redeemWith"]},{"name":"open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.redeemWith","location":"-cont/arrow/-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","arrow.Cont.redeemWith"]},{"name":"open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.handleErrorWith","location":"-cont/arrow/-restricted-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.handleErrorWith"]},{"name":"open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","description":"arrow.Cont.handleErrorWith","location":"-cont/arrow/-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","arrow.Cont.handleErrorWith"]},{"name":"open fun attempt(): Cont>","description":"arrow.Cont.attempt","location":"-cont/arrow/-cont/attempt.html","searchKeys":["attempt","open fun attempt(): Cont>","arrow.Cont.attempt"]},{"name":"open fun attempt(): RestrictedCont>","description":"arrow.RestrictedCont.attempt","location":"-cont/arrow/-restricted-cont/attempt.html","searchKeys":["attempt","open fun attempt(): RestrictedCont>","arrow.RestrictedCont.attempt"]},{"name":"open fun handleError(f: (R) -> A): RestrictedCont","description":"arrow.RestrictedCont.handleError","location":"-cont/arrow/-restricted-cont/handle-error.html","searchKeys":["handleError","open fun handleError(f: (R) -> A): RestrictedCont","arrow.RestrictedCont.handleError"]},{"name":"open fun handleError(recover: suspend (R) -> A): Cont","description":"arrow.Cont.handleError","location":"-cont/arrow/-cont/handle-error.html","searchKeys":["handleError","open fun handleError(recover: suspend (R) -> A): Cont","arrow.Cont.handleError"]},{"name":"open fun toEither(): Either","description":"arrow.RestrictedCont.toEither","location":"-cont/arrow/-restricted-cont/to-either.html","searchKeys":["toEither","open fun toEither(): Either","arrow.RestrictedCont.toEither"]},{"name":"open fun toValidated(): Validated","description":"arrow.RestrictedCont.toValidated","location":"-cont/arrow/-restricted-cont/to-validated.html","searchKeys":["toValidated","open fun toValidated(): Validated","arrow.RestrictedCont.toValidated"]},{"name":"open suspend fun RestrictedCont.bind(): A","description":"arrow.RestrictedContEffect.bind","location":"-cont/arrow/-restricted-cont-effect/bind.html","searchKeys":["bind","open suspend fun RestrictedCont.bind(): A","arrow.RestrictedContEffect.bind"]},{"name":"open suspend fun Cont.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Cont.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Either.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Either.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Option.bind(shift: () -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Option.bind(shift: () -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Result.bind(transform: (Throwable) -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Result.bind(transform: (Throwable) -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Validated.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Validated.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"open suspend fun ensure(value: Boolean, shift: () -> R)","description":"arrow.ContEffect.ensure","location":"-cont/arrow/-cont-effect/ensure.html","searchKeys":["ensure","open suspend fun ensure(value: Boolean, shift: () -> R)","arrow.ContEffect.ensure"]},{"name":"open suspend fun toEither(): Either","description":"arrow.Cont.toEither","location":"-cont/arrow/-cont/to-either.html","searchKeys":["toEither","open suspend fun toEither(): Either","arrow.Cont.toEither"]},{"name":"open suspend fun toIor(): Ior","description":"arrow.Cont.toIor","location":"-cont/arrow/-cont/to-ior.html","searchKeys":["toIor","open suspend fun toIor(): Ior","arrow.Cont.toIor"]},{"name":"open suspend fun toOption(orElse: suspend (R) -> Option): Option","description":"arrow.Cont.toOption","location":"-cont/arrow/-cont/to-option.html","searchKeys":["toOption","open suspend fun toOption(orElse: suspend (R) -> Option): Option","arrow.Cont.toOption"]},{"name":"open suspend fun toValidated(): Validated","description":"arrow.Cont.toValidated","location":"-cont/arrow/-cont/to-validated.html","searchKeys":["toValidated","open suspend fun toValidated(): Validated","arrow.Cont.toValidated"]},{"name":"open suspend override fun shift(r: E): B","description":"arrow.IorEffect.shift","location":"-cont/arrow/-ior-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: E): B","arrow.IorEffect.shift"]},{"name":"open suspend override fun shift(r: None): B","description":"arrow.OptionEffect.shift","location":"-cont/arrow/-option-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: None): B","arrow.OptionEffect.shift"]},{"name":"sealed class ShiftCancellationException : CancellationException","description":"arrow.ShiftCancellationException","location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException","sealed class ShiftCancellationException : CancellationException","arrow.ShiftCancellationException"]},{"name":"suspend fun Cont.toOption(): Option","description":"arrow.toOption","location":"-cont/arrow/to-option.html","searchKeys":["toOption","suspend fun Cont.toOption(): Option","arrow.toOption"]},{"name":"suspend fun option(f: OptionEffect.() -> A): Option","description":"arrow.option","location":"-cont/arrow/option.html","searchKeys":["option","suspend fun option(f: OptionEffect.() -> A): Option","arrow.option"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?): B","arrow.ensureNotNull"]},{"name":"suspend fun Ior.bind(): B","description":"arrow.IorEffect.bind","location":"-cont/arrow/-ior-effect/bind.html","searchKeys":["bind","suspend fun Ior.bind(): B","arrow.IorEffect.bind"]},{"name":"suspend fun Option.bind(): B","description":"arrow.OptionEffect.bind","location":"-cont/arrow/-option-effect/bind.html","searchKeys":["bind","suspend fun Option.bind(): B","arrow.OptionEffect.bind"]},{"name":"suspend fun either(f: suspend ContEffect.() -> A): Either","description":"arrow.either","location":"-cont/arrow/either.html","searchKeys":["either","suspend fun either(f: suspend ContEffect.() -> A): Either","arrow.either"]},{"name":"suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","description":"arrow.ior","location":"-cont/arrow/ior.html","searchKeys":["ior","suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","arrow.ior"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","arrow.ensureNotNull"]},{"name":"suspend fun ensure(value: Boolean)","description":"arrow.OptionEffect.ensure","location":"-cont/arrow/-option-effect/ensure.html","searchKeys":["ensure","suspend fun ensure(value: Boolean)","arrow.OptionEffect.ensure"]},{"name":"value class OptionEffect(cont: ContEffect) : ContEffect ","description":"arrow.OptionEffect","location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect","value class OptionEffect(cont: ContEffect) : ContEffect ","arrow.OptionEffect"]}] +[{"name":"abstract fun fold(f: (R) -> B, g: (A) -> B): B","description":"arrow.RestrictedCont.fold","location":"-cont/arrow/-restricted-cont/fold.html","searchKeys":["fold","abstract fun fold(f: (R) -> B, g: (A) -> B): B","arrow.RestrictedCont.fold"]},{"name":"abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","abstract suspend fun fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.ContEffect.shift","location":"-cont/arrow/-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.ContEffect.shift"]},{"name":"abstract suspend fun shift(r: R): B","description":"arrow.RestrictedContEffect.shift","location":"-cont/arrow/-restricted-cont-effect/shift.html","searchKeys":["shift","abstract suspend fun shift(r: R): B","arrow.RestrictedContEffect.shift"]},{"name":"class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","description":"arrow.IorEffect","location":"-cont/arrow/-ior-effect/index.html","searchKeys":["IorEffect","class IorEffect(semigroup: Semigroup, cont: ContEffect) : ContEffect , Semigroup ","arrow.IorEffect"]},{"name":"fun IorEffect(semigroup: Semigroup, cont: ContEffect)","description":"arrow.IorEffect.IorEffect","location":"-cont/arrow/-ior-effect/-ior-effect.html","searchKeys":["IorEffect","fun IorEffect(semigroup: Semigroup, cont: ContEffect)","arrow.IorEffect.IorEffect"]},{"name":"fun cont(f: suspend ContEffect.() -> A): Cont","description":"arrow.cont","location":"-cont/arrow/cont.html","searchKeys":["cont","fun cont(f: suspend ContEffect.() -> A): Cont","arrow.cont"]},{"name":"fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","description":"arrow.restrictedCont","location":"-cont/arrow/restricted-cont.html","searchKeys":["restrictedCont","fun restrictedCont(f: suspend RestrictedContEffect.() -> A): RestrictedCont","arrow.restrictedCont"]},{"name":"fun OptionEffect(cont: ContEffect)","description":"arrow.OptionEffect.OptionEffect","location":"-cont/arrow/-option-effect/-option-effect.html","searchKeys":["OptionEffect","fun OptionEffect(cont: ContEffect)","arrow.OptionEffect.OptionEffect"]},{"name":"interface Cont","description":"arrow.Cont","location":"-cont/arrow/-cont/index.html","searchKeys":["Cont","interface Cont","arrow.Cont"]},{"name":"interface ContEffect","description":"arrow.ContEffect","location":"-cont/arrow/-cont-effect/index.html","searchKeys":["ContEffect","interface ContEffect","arrow.ContEffect"]},{"name":"interface RestrictedCont","description":"arrow.RestrictedCont","location":"-cont/arrow/-restricted-cont/index.html","searchKeys":["RestrictedCont","interface RestrictedCont","arrow.RestrictedCont"]},{"name":"interface RestrictedContEffect","description":"arrow.RestrictedContEffect","location":"-cont/arrow/-restricted-cont-effect/index.html","searchKeys":["RestrictedContEffect","interface RestrictedContEffect","arrow.RestrictedContEffect"]},{"name":"open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.flatMap","location":"-cont/arrow/-restricted-cont/flat-map.html","searchKeys":["flatMap","open fun flatMap(f: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.flatMap"]},{"name":"open fun map(f: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.map","location":"-cont/arrow/-restricted-cont/map.html","searchKeys":["map","open fun map(f: (A) -> B): RestrictedCont","arrow.RestrictedCont.map"]},{"name":"open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","description":"arrow.RestrictedCont.redeem","location":"-cont/arrow/-restricted-cont/redeem.html","searchKeys":["redeem","open fun redeem(f: (R) -> B, g: (A) -> B): RestrictedCont","arrow.RestrictedCont.redeem"]},{"name":"open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","description":"arrow.Cont.redeem","location":"-cont/arrow/-cont/redeem.html","searchKeys":["redeem","open fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont","arrow.Cont.redeem"]},{"name":"open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.redeemWith","location":"-cont/arrow/-restricted-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(f: (R) -> RestrictedCont, g: (A) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.redeemWith"]},{"name":"open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","description":"arrow.Cont.redeemWith","location":"-cont/arrow/-cont/redeem-with.html","searchKeys":["redeemWith","open fun redeemWith(recover: suspend (R) -> Cont, transform: suspend (A) -> Cont): Cont","arrow.Cont.redeemWith"]},{"name":"open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","description":"arrow.RestrictedCont.handleErrorWith","location":"-cont/arrow/-restricted-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(f: (R) -> RestrictedCont): RestrictedCont","arrow.RestrictedCont.handleErrorWith"]},{"name":"open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","description":"arrow.Cont.handleErrorWith","location":"-cont/arrow/-cont/handle-error-with.html","searchKeys":["handleErrorWith","open fun handleErrorWith(recover: suspend (R) -> Cont): Cont","arrow.Cont.handleErrorWith"]},{"name":"open fun attempt(): Cont>","description":"arrow.Cont.attempt","location":"-cont/arrow/-cont/attempt.html","searchKeys":["attempt","open fun attempt(): Cont>","arrow.Cont.attempt"]},{"name":"open fun attempt(): RestrictedCont>","description":"arrow.RestrictedCont.attempt","location":"-cont/arrow/-restricted-cont/attempt.html","searchKeys":["attempt","open fun attempt(): RestrictedCont>","arrow.RestrictedCont.attempt"]},{"name":"open fun handleError(f: (R) -> A): RestrictedCont","description":"arrow.RestrictedCont.handleError","location":"-cont/arrow/-restricted-cont/handle-error.html","searchKeys":["handleError","open fun handleError(f: (R) -> A): RestrictedCont","arrow.RestrictedCont.handleError"]},{"name":"open fun handleError(recover: suspend (R) -> A): Cont","description":"arrow.Cont.handleError","location":"-cont/arrow/-cont/handle-error.html","searchKeys":["handleError","open fun handleError(recover: suspend (R) -> A): Cont","arrow.Cont.handleError"]},{"name":"open fun toEither(): Either","description":"arrow.RestrictedCont.toEither","location":"-cont/arrow/-restricted-cont/to-either.html","searchKeys":["toEither","open fun toEither(): Either","arrow.RestrictedCont.toEither"]},{"name":"open fun toValidated(): Validated","description":"arrow.RestrictedCont.toValidated","location":"-cont/arrow/-restricted-cont/to-validated.html","searchKeys":["toValidated","open fun toValidated(): Validated","arrow.RestrictedCont.toValidated"]},{"name":"open suspend fun RestrictedCont.bind(): A","description":"arrow.RestrictedContEffect.bind","location":"-cont/arrow/-restricted-cont-effect/bind.html","searchKeys":["bind","open suspend fun RestrictedCont.bind(): A","arrow.RestrictedContEffect.bind"]},{"name":"open suspend fun Cont.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Cont.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Either.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Either.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Option.bind(shift: () -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Option.bind(shift: () -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Result.bind(transform: (Throwable) -> R): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Result.bind(transform: (Throwable) -> R): B","arrow.ContEffect.bind"]},{"name":"open suspend fun Validated.bind(): B","description":"arrow.ContEffect.bind","location":"-cont/arrow/-cont-effect/bind.html","searchKeys":["bind","open suspend fun Validated.bind(): B","arrow.ContEffect.bind"]},{"name":"open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","description":"arrow.Cont.fold","location":"-cont/arrow/-cont/fold.html","searchKeys":["fold","open suspend fun fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B","arrow.Cont.fold"]},{"name":"open suspend fun ensure(condition: Boolean, shift: () -> R)","description":"arrow.ContEffect.ensure","location":"-cont/arrow/-cont-effect/ensure.html","searchKeys":["ensure","open suspend fun ensure(condition: Boolean, shift: () -> R)","arrow.ContEffect.ensure"]},{"name":"open suspend fun toEither(): Either","description":"arrow.Cont.toEither","location":"-cont/arrow/-cont/to-either.html","searchKeys":["toEither","open suspend fun toEither(): Either","arrow.Cont.toEither"]},{"name":"open suspend fun toIor(): Ior","description":"arrow.Cont.toIor","location":"-cont/arrow/-cont/to-ior.html","searchKeys":["toIor","open suspend fun toIor(): Ior","arrow.Cont.toIor"]},{"name":"open suspend fun toOption(orElse: suspend (R) -> Option): Option","description":"arrow.Cont.toOption","location":"-cont/arrow/-cont/to-option.html","searchKeys":["toOption","open suspend fun toOption(orElse: suspend (R) -> Option): Option","arrow.Cont.toOption"]},{"name":"open suspend fun toValidated(): Validated","description":"arrow.Cont.toValidated","location":"-cont/arrow/-cont/to-validated.html","searchKeys":["toValidated","open suspend fun toValidated(): Validated","arrow.Cont.toValidated"]},{"name":"open suspend override fun shift(r: E): B","description":"arrow.IorEffect.shift","location":"-cont/arrow/-ior-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: E): B","arrow.IorEffect.shift"]},{"name":"open suspend override fun shift(r: None): B","description":"arrow.OptionEffect.shift","location":"-cont/arrow/-option-effect/shift.html","searchKeys":["shift","open suspend override fun shift(r: None): B","arrow.OptionEffect.shift"]},{"name":"sealed class ShiftCancellationException : CancellationException","description":"arrow.ShiftCancellationException","location":"-cont/arrow/-shift-cancellation-exception/index.html","searchKeys":["ShiftCancellationException","sealed class ShiftCancellationException : CancellationException","arrow.ShiftCancellationException"]},{"name":"suspend fun Cont.toOption(): Option","description":"arrow.toOption","location":"-cont/arrow/to-option.html","searchKeys":["toOption","suspend fun Cont.toOption(): Option","arrow.toOption"]},{"name":"suspend fun option(f: OptionEffect.() -> A): Option","description":"arrow.option","location":"-cont/arrow/option.html","searchKeys":["option","suspend fun option(f: OptionEffect.() -> A): Option","arrow.option"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?): B","arrow.ensureNotNull"]},{"name":"suspend fun Ior.bind(): B","description":"arrow.IorEffect.bind","location":"-cont/arrow/-ior-effect/bind.html","searchKeys":["bind","suspend fun Ior.bind(): B","arrow.IorEffect.bind"]},{"name":"suspend fun Option.bind(): B","description":"arrow.OptionEffect.bind","location":"-cont/arrow/-option-effect/bind.html","searchKeys":["bind","suspend fun Option.bind(): B","arrow.OptionEffect.bind"]},{"name":"suspend fun either(f: suspend ContEffect.() -> A): Either","description":"arrow.either","location":"-cont/arrow/either.html","searchKeys":["either","suspend fun either(f: suspend ContEffect.() -> A): Either","arrow.either"]},{"name":"suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","description":"arrow.ior","location":"-cont/arrow/ior.html","searchKeys":["ior","suspend fun ior(semigroup: Semigroup, f: suspend IorEffect.() -> A): Ior","arrow.ior"]},{"name":"suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","description":"arrow.ensureNotNull","location":"-cont/arrow/ensure-not-null.html","searchKeys":["ensureNotNull","suspend fun ContEffect.ensureNotNull(value: B?, shift: () -> R): B","arrow.ensureNotNull"]},{"name":"suspend fun ensure(value: Boolean)","description":"arrow.OptionEffect.ensure","location":"-cont/arrow/-option-effect/ensure.html","searchKeys":["ensure","suspend fun ensure(value: Boolean)","arrow.OptionEffect.ensure"]},{"name":"value class OptionEffect(cont: ContEffect) : ContEffect ","description":"arrow.OptionEffect","location":"-cont/arrow/-option-effect/index.html","searchKeys":["OptionEffect","value class OptionEffect(cont: ContEffect) : ContEffect ","arrow.OptionEffect"]}] From 33ed1b03111f2904be5868295aacf34c5d057968 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 11 Nov 2021 20:27:31 +0100 Subject: [PATCH 041/108] More docs --- guide/example/example-readme-01.kt | 3 +- guide/example/example-readme-02.kt | 9 ++++-- guide/example/example-readme-05.kt | 15 ++++++--- guide/example/example-readme-06.kt | 17 +++++++--- guide/example/example-readme-07.kt | 18 ++++++----- guide/example/example-readme-08.kt | 41 ++++++++---------------- guide/example/example-readme-09.kt | 50 ++++++++---------------------- guide/example/example-readme-10.kt | 45 ++++++++++++++++++++++----- guide/example/example-readme-11.kt | 25 +++++++++++++++ guide/example/example-readme-12.kt | 25 +++++++++++++++ guide/test/ReadmeSpec.kt | 12 +++++++ 11 files changed, 167 insertions(+), 93 deletions(-) create mode 100644 guide/example/example-readme-11.kt create mode 100644 guide/example/example-readme-12.kt diff --git a/guide/example/example-readme-01.kt b/guide/example/example-readme-01.kt index cf341cdfd0b..e8d2da0e51a 100644 --- a/guide/example/example-readme-01.kt +++ b/guide/example/example-readme-01.kt @@ -21,5 +21,6 @@ fun readFile(path: String): Cont = cont { } fun readFile2(path: String?): Cont = cont { - ensure(!path.isNullOrBlank()) { EmptyPath } + ensureNotNull(path) { EmptyPath } + ensure(path.isEmpty()) { EmptyPath } } diff --git a/guide/example/example-readme-02.kt b/guide/example/example-readme-02.kt index b9c6a29282e..a62bf0da487 100644 --- a/guide/example/example-readme-02.kt +++ b/guide/example/example-readme-02.kt @@ -41,8 +41,11 @@ fun readFile(path: String?): Cont = cont { suspend fun test() { readFile("").toEither() shouldBe Either.Left(EmptyPath) - readFile("not-found").toValidated() shouldBe Validated.Invalid(FileNotFound("not-found")) + readFile("knit.properties").toValidated() shouldBe Validated.Invalid(FileNotFound("knit.properties")) readFile("gradle.properties").toIor() shouldBe Ior.Left(FileNotFound("gradle.properties")) - readFile("not-found").toOption { None } shouldBe None - readFile("nullable").fold({ _: FileError -> null }, { it }) shouldBe null + readFile("README.MD").toOption { None } shouldBe None + + readFile("build.gradle.kts").fold({ _: FileError -> null }, { it }) + .shouldBeInstanceOf() + .body.shouldNotBeEmpty() } diff --git a/guide/example/example-readme-05.kt b/guide/example/example-readme-05.kt index 82b16b797f6..6e4d5376b96 100644 --- a/guide/example/example-readme-05.kt +++ b/guide/example/example-readme-05.kt @@ -14,8 +14,13 @@ import io.kotest.property.* import io.kotest.property.arbitrary.* import arrow.core.test.generators.* -suspend fun parZip(): Unit = cont { - parZip({ - delay(1_000_000) // Cancelled by shift - }, { shift("error") }) { _, int -> int } -}.fold(::println, ::println) // "error" +suspend fun awaitExitCase(exit: CompletableDeferred): A = + guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } + +suspend fun test() = checkAll(Arb.string()) { error -> + val exit = CompletableDeferred() + cont { + parZip({ awaitExitCase(exit) }, { shift(error) }) { a, b -> a + b } + }.fold({ it shouldBe error }, { fail("Int can never be the result") }) + exit.await().shouldBeTypeOf() +} diff --git a/guide/example/example-readme-06.kt b/guide/example/example-readme-06.kt index ad92add5ba3..57fefa6a603 100644 --- a/guide/example/example-readme-06.kt +++ b/guide/example/example-readme-06.kt @@ -14,13 +14,20 @@ import io.kotest.property.* import io.kotest.property.arbitrary.* import arrow.core.test.generators.* -suspend fun test() { +suspend fun awaitExitCase(exit: CompletableDeferred): A = + guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } + +suspend fun CompletableDeferred.getOrNull(): A? = + if (isCompleted) await() else null + +suspend fun test() = checkAll(Arb.string()) { error -> val exits = (0..3).map { CompletableDeferred() } cont> { (0..4).parTraverse { index -> - if (index == 4) shift("error") - else guaranteeCase({ delay(1_000_000) }) { exitCase -> require(exits[index].complete(exitCase)) } + if (index == 4) shift(error) + else awaitExitCase(exits[index]) } - }.fold({ msg -> msg shouldBe "error" }, { fail("Int can never be the result") }) - exits.awaitAll().forEach { it.shouldBeTypeOf() } + }.fold({ msg -> msg shouldBe error }, { fail("Int can never be the result") }) + // It's possible not all parallel task got launched, and in those cases awaitCancellation never ran + exits.forEach { exit -> exit.getOrNull()?.shouldBeTypeOf() } } diff --git a/guide/example/example-readme-07.kt b/guide/example/example-readme-07.kt index 700d99711f4..ce690c18340 100644 --- a/guide/example/example-readme-07.kt +++ b/guide/example/example-readme-07.kt @@ -14,14 +14,18 @@ import io.kotest.property.* import io.kotest.property.arbitrary.* import arrow.core.test.generators.* -suspend fun test() { +suspend fun awaitExitCase(exit: CompletableDeferred): A = + guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } + +suspend fun CompletableDeferred.getOrNull(): A? = + if (isCompleted) await() else null + +suspend fun test() = checkAll(Arb.string()) { error -> val exit = CompletableDeferred() cont { - raceN({ - guaranteeCase({ delay(1_000_000) }) { exitCase -> require(exit.complete(exitCase)) } - 5 - }) { shift("error") } + raceN({ awaitExitCase(exit) }) { shift(error) } .merge() // Flatten Either result from race into Int - }.fold({ msg -> msg shouldBe "error" }, { fail("Int can never be the result") }) - exit.await().shouldBeTypeOf() + }.fold({ msg -> msg shouldBe error }, { fail("Int can never be the result") }) + // It's possible not all parallel task got launched, and in those cases awaitCancellation never ran + exit.getOrNull()?.shouldBeTypeOf() } diff --git a/guide/example/example-readme-08.kt b/guide/example/example-readme-08.kt index eb4db930d7f..a3226b93b87 100644 --- a/guide/example/example-readme-08.kt +++ b/guide/example/example-readme-08.kt @@ -16,32 +16,17 @@ import arrow.core.test.generators.* import java.io.* -suspend fun bracketCase() = cont { - bracketCase( - acquire = { File("gradle.properties").bufferedReader() }, - use = { reader -> - // some logic - shift("file doesn't contain right content") - }, - release = { reader, exitCase -> - reader.close() - println(exitCase) // ExitCase.Cancelled(ShiftCancellationException("Shifted Continuation")) - } - ) -}.fold(::println, ::println) // "file doesn't contain right content" - -// Available from Arrow 1.1.x -fun Resource.releaseCase(releaseCase: (A, ExitCase) -> Unit): Resource = - flatMap { a -> Resource({ a }, releaseCase) } - -fun bufferedReader(path: String): Resource = - Resource.fromAutoCloseable { - File(path).bufferedReader() - }.releaseCase { _, exitCase -> println(exitCase) } - -suspend fun resource() = cont { - bufferedReader("gradle.properties").use { reader -> - // some logic - shift("file doesn't contain right content") - } // ExitCase.Cancelled(ShiftCancellationException("Shifted Continuation")) printed from release +suspend fun test() = checkAll(Arb.string()) { error -> + val exit = CompletableDeferred() + cont { + bracketCase( + acquire = { File("build.gradle.kts").bufferedReader() }, + use = { reader: BufferedReader -> shift(error) }, + release = { reader, exitCase -> + reader.close() + exit.complete(exitCase) + } + ) + }.fold({ it shouldBe error }, { fail("Int can never be the result") }) + exit.await().shouldBeTypeOf() } diff --git a/guide/example/example-readme-09.kt b/guide/example/example-readme-09.kt index 0d9ac3ba8b7..89e0e91bba5 100644 --- a/guide/example/example-readme-09.kt +++ b/guide/example/example-readme-09.kt @@ -16,44 +16,20 @@ import arrow.core.test.generators.* import java.io.* -@JvmInline -value class Content(val body: List) +fun Resource.releaseCase(releaseCase: suspend (A, ExitCase) -> Unit): Resource = + flatMap { a -> Resource({ a }, releaseCase) } -sealed interface FileError -@JvmInline value class SecurityError(val msg: String?) : FileError -@JvmInline value class FileNotFound(val path: String) : FileError -object EmptyPath : FileError { - override fun toString() = "EmptyPath" -} - -fun readFile(path: String?): Cont = cont { - ensureNotNull(path) { EmptyPath } - ensure(path.isNotEmpty()) { EmptyPath } - try { - val lines = File(path).readLines() - Content(lines) - } catch (e: FileNotFoundException) { - shift(FileNotFound(path)) - } catch (e: SecurityException) { - shift(SecurityError(e.message)) - } -} +suspend fun test() = checkAll(Arb.string()) { error -> + val exit = CompletableDeferred() -fun A.onCancel(f: (CancellationException) -> Unit): A = also { - invokeOnCompletion { error -> - if (error is CancellationException) f(error) else Unit - } -} + fun bufferedReader(path: String): Resource = + Resource.fromAutoCloseable { File(path).bufferedReader() } + .releaseCase { _, exitCase -> exit.complete(exitCase) } -suspend fun test() { - val exit = CompletableDeferred() - cont { - withContext(Dispatchers.IO) { - val job = launch { delay(1_000_000) }.onCancel { ce -> require(exit.complete(ce)) } - val content = readFile("failure").bind() - job.join() - content.body.size - } - }.fold({ e -> e shouldBe FileNotFound("failure") }, { fail("Int can never be the result") }) - exit.await().shouldBeInstanceOf() + cont { + val lineCount = bufferedReader("build.gradle.kts") + .use { reader -> shift(error) } + lineCount + }.fold({ it shouldBe error }, { fail("Int can never be the result") }) + exit.await().shouldBeTypeOf() } diff --git a/guide/example/example-readme-10.kt b/guide/example/example-readme-10.kt index e1fae7ee600..c21a549f1cb 100644 --- a/guide/example/example-readme-10.kt +++ b/guide/example/example-readme-10.kt @@ -14,12 +14,43 @@ import io.kotest.property.* import io.kotest.property.arbitrary.* import arrow.core.test.generators.* -suspend fun test() { - coroutineScope { - cont { - val fa = async { shift(1) } - val fb = async { shift(2) } - fa.await() + fb.await() - }.fold(::identity, ::identity) shouldBeIn listOf(1, 2) +import java.io.* + +@JvmInline +value class Content(val body: List) + +sealed interface FileError +@JvmInline value class SecurityError(val msg: String?) : FileError +@JvmInline value class FileNotFound(val path: String) : FileError +object EmptyPath : FileError { + override fun toString() = "EmptyPath" +} + +fun readFile(path: String?): Cont = cont { + ensureNotNull(path) { EmptyPath } + ensure(path.isNotEmpty()) { EmptyPath } + try { + val lines = File(path).readLines() + Content(lines) + } catch (e: FileNotFoundException) { + shift(FileNotFound(path)) + } catch (e: SecurityException) { + shift(SecurityError(e.message)) } } + +suspend fun awaitExitCase(exit: CompletableDeferred): A = + guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } + +suspend fun test() { + val exit = CompletableDeferred() + cont { + withContext(Dispatchers.IO) { + val job = launch { awaitExitCase(exit) } + val content = readFile("failure").bind() + job.join() + content.body.size + } + }.fold({ e -> e shouldBe FileNotFound("failure") }, { fail("Int can never be the result") }) + exit.await().shouldBeInstanceOf() +} diff --git a/guide/example/example-readme-11.kt b/guide/example/example-readme-11.kt new file mode 100644 index 00000000000..0b475461ccf --- /dev/null +++ b/guide/example/example-readme-11.kt @@ -0,0 +1,25 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme11 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.string(), Arb.string()) { errorA, errorB -> + coroutineScope { + cont { + val fa = async { shift(errorA) } + val fb = async { shift(errorB) } + fa.await() + fb.await() + }.fold({ error -> error shouldBeIn listOf(errorA, errorB) }, { fail("Int can never be the result") }) + } +} diff --git a/guide/example/example-readme-12.kt b/guide/example/example-readme-12.kt new file mode 100644 index 00000000000..20764eb766a --- /dev/null +++ b/guide/example/example-readme-12.kt @@ -0,0 +1,25 @@ +// This file was automatically generated from README.md by Knit tool. Do not edit. +package example.exampleReadme12 + +import arrow.* +import arrow.core.* +import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import io.kotest.matchers.collections.* +import io.kotest.assertions.* +import io.kotest.matchers.* +import io.kotest.matchers.types.* +import kotlin.coroutines.cancellation.CancellationException +import io.kotest.property.* +import io.kotest.property.arbitrary.* +import arrow.core.test.generators.* + +suspend fun test() = checkAll(Arb.string(), Arb.string(), Arb.int()) { errorA, errorB, int -> + cont { + coroutineScope { + launch { shift(errorA) } + launch { shift(errorB) } + int + } + }.fold({ fail("Shift can never finish") }, { it shouldBe int }) +} diff --git a/guide/test/ReadmeSpec.kt b/guide/test/ReadmeSpec.kt index 2ab19ece3fc..ee3f246fec0 100644 --- a/guide/test/ReadmeSpec.kt +++ b/guide/test/ReadmeSpec.kt @@ -23,6 +23,10 @@ class ReadmeSpec : StringSpec({ example.exampleReadme07.test() } + "ExampleReadme08".config(timeout= Duration.seconds(1)) { + example.exampleReadme08.test() + } + "ExampleReadme09".config(timeout= Duration.seconds(1)) { example.exampleReadme09.test() } @@ -31,4 +35,12 @@ class ReadmeSpec : StringSpec({ example.exampleReadme10.test() } + "ExampleReadme11".config(timeout= Duration.seconds(1)) { + example.exampleReadme11.test() + } + + "ExampleReadme12".config(timeout= Duration.seconds(1)) { + example.exampleReadme12.test() + } + }) From de30d732c23c4bf9f0c6902eacd6bc3b1dfe6255 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Fri, 12 Nov 2021 20:05:36 +0100 Subject: [PATCH 042/108] Update to Kotlin 1.6.0-RC2 --- .github/workflows/build.yaml | 4 ++-- .github/workflows/pr.yaml | 4 ++-- libs.versions.toml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 9a3478e690b..90c3a1a6e42 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -18,9 +18,9 @@ jobs: check: strategy: matrix: - os: [ windows-latest, ubuntu-latest ] + os: [ windows-latest, macos-11.0 ] runs-on: ${{matrix.os}} - timeout-minutes: 20 + timeout-minutes: 30 steps: - name: Checkout the repo uses: actions/checkout@v2 diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 3c1a06fe770..8ee069395a9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -14,9 +14,9 @@ jobs: check: strategy: matrix: - os: [ windows-latest, ubuntu-latest ] + os: [ windows-latest, macos-11.0 ] runs-on: ${{matrix.os}} - timeout-minutes: 20 + timeout-minutes: 30 steps: - name: Checkout the repo uses: actions/checkout@v2 diff --git a/libs.versions.toml b/libs.versions.toml index 109fa86afea..95be9510baf 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -3,9 +3,9 @@ arrow = "1.0.1" arrowGradleConfig = "0.5.1" coroutines = "1.5.2" dokka = "1.5.31" -kotest = "5.0.0.M2" +kotest = "5.0.0.M4" kotestGradle = "5.0.0.5" -kotlin = "1.5.31" +kotlin = "1.6.0-RC2" kotlinBinaryCompatibilityValidator = "0.8.0" githooks = "0.0.2" knit = "0.2.3" From c705610eb6c4af2c2e4d43fdb583173babbfa4af Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Fri, 12 Nov 2021 20:07:22 +0100 Subject: [PATCH 043/108] Fix github workflow --- .github/workflows/build.yaml | 2 +- .github/workflows/pr.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 90c3a1a6e42..b80c69df5d2 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -39,7 +39,7 @@ jobs: restore-keys: ${{ runner.os }}-check- - name: Run Ubuntu tests - if: matrix.os == 'ubuntu-latest' + if: matrix.os == 'macos-11.0' run: ./gradlew check - name: Run Windows tests diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 8ee069395a9..d21752ab272 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -34,8 +34,8 @@ jobs: key: ${{ runner.os }}-check-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: ${{ runner.os }}-check- - - name: Run Ubuntu tests - if: matrix.os == 'ubuntu-latest' + - name: Run MacOs tests + if: matrix.os == 'macos-11.0' run: ./gradlew check - name: Run Windows tests From 30750036f87e4bb77b48bbd6e7e6671303956680 Mon Sep 17 00:00:00 2001 From: nomisRev Date: Fri, 12 Nov 2021 19:08:56 +0000 Subject: [PATCH 044/108] Auto update docs --- docs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.html b/docs/index.html index 479e6fd1dd7..9de9f476263 100644 --- a/docs/index.html +++ b/docs/index.html @@ -22,7 +22,7 @@

Cont

-
  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensure(!path.isNullOrBlank()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

      • #strange-edge-cases

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensureNotNull(path) { EmptyPath }
ensure(path.isEmpty()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

From 4a34dc346b57965e70cb80afba1547bbf04717e5 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Fri, 12 Nov 2021 20:26:47 +0100 Subject: [PATCH 045/108] jvmTest only --- .github/workflows/pr.yaml | 4 ++-- src/commonMain/kotlin/arrow/Cont.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index d21752ab272..03146df5f36 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -14,7 +14,7 @@ jobs: check: strategy: matrix: - os: [ windows-latest, macos-11.0 ] + os: [ macos-11.0 ] runs-on: ${{matrix.os}} timeout-minutes: 30 steps: @@ -36,7 +36,7 @@ jobs: - name: Run MacOs tests if: matrix.os == 'macos-11.0' - run: ./gradlew check + run: ./gradlew jvmTest - name: Run Windows tests if: matrix.os == 'windows-latest' diff --git a/src/commonMain/kotlin/arrow/Cont.kt b/src/commonMain/kotlin/arrow/Cont.kt index 7d9031d86c6..1149c31a37a 100644 --- a/src/commonMain/kotlin/arrow/Cont.kt +++ b/src/commonMain/kotlin/arrow/Cont.kt @@ -120,8 +120,8 @@ public interface Cont { * [fold] the [Cont] into an [Result]. Where the shifted value [R] is mapped to [Result] by the * provided function [orElse], and result value [A] is mapped to [Result.success]. */ -// public suspend fun toResult(orElse: suspend (R) -> Result
): Result = -// fold(orElse) { a -> Result.success(a) } + // public suspend fun toResult(orElse: suspend (R) -> Result): Result = + // fold(orElse) { a -> Result.success(a) } /** * [fold] the [Cont] into an [Option]. Where the shifted value [R] is mapped to [Option] by the From 6350e74fd5cbf7f899e702f04d0dbd41dc9a7548 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Fri, 12 Nov 2021 22:17:55 +0100 Subject: [PATCH 046/108] Try again --- src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt b/src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt index 881538bb122..b20bc019d5e 100644 --- a/src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt +++ b/src/commonTest/kotlin/arrow/StructuredConcurrencySpec.kt @@ -1,6 +1,8 @@ package arrow +import arrow.core.Either import arrow.core.identity +import arrow.core.right import arrow.fx.coroutines.ExitCase import arrow.fx.coroutines.guaranteeCase import arrow.fx.coroutines.never @@ -24,6 +26,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeout From 86db144fadfb3eb0eab962d72a7f6fca7f75c3d5 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 15 Nov 2021 16:01:30 +0100 Subject: [PATCH 047/108] Bump Knit & Kotlin --- libs.versions.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libs.versions.toml b/libs.versions.toml index 95be9510baf..82aef07ce50 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -5,10 +5,10 @@ coroutines = "1.5.2" dokka = "1.5.31" kotest = "5.0.0.M4" kotestGradle = "5.0.0.5" -kotlin = "1.6.0-RC2" +kotlin = "1.6.0" kotlinBinaryCompatibilityValidator = "0.8.0" githooks = "0.0.2" -knit = "0.2.3" +knit = "0.3.0" [libraries] arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } @@ -38,4 +38,4 @@ kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotestGr kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "kotlinBinaryCompatibilityValidator" } githooks = { id = "com.github.jakemarsden.git-hooks", version.ref = "githooks" } -knit = { id = "org.jetbrains.kotlinx:kotlinx-knit", version.ref = "knit" } \ No newline at end of file +knit = { id = "org.jetbrains.kotlinx:kotlinx-knit", version.ref = "knit" } From ce90387989343b2dd80bc60835061f1286de92e5 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 22 Nov 2021 10:17:15 +0100 Subject: [PATCH 048/108] Disable MPP test due to bug Kotlin 1.6.0 annotations --- .github/workflows/build.yaml | 4 ++-- libs.versions.toml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index b80c69df5d2..bc616623eb6 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -18,7 +18,7 @@ jobs: check: strategy: matrix: - os: [ windows-latest, macos-11.0 ] + os: [ macos-11.0 ] runs-on: ${{matrix.os}} timeout-minutes: 30 steps: @@ -40,7 +40,7 @@ jobs: - name: Run Ubuntu tests if: matrix.os == 'macos-11.0' - run: ./gradlew check + run: ./gradlew jvmTest - name: Run Windows tests if: matrix.os == 'windows-latest' diff --git a/libs.versions.toml b/libs.versions.toml index 82aef07ce50..c28a32d950e 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -3,8 +3,8 @@ arrow = "1.0.1" arrowGradleConfig = "0.5.1" coroutines = "1.5.2" dokka = "1.5.31" -kotest = "5.0.0.M4" -kotestGradle = "5.0.0.5" +kotest = "5.0.0.RC" +kotestGradle = "5.0.0.RC" kotlin = "1.6.0" kotlinBinaryCompatibilityValidator = "0.8.0" githooks = "0.0.2" From e7613c5a0aa1a03c7fe6bf7daec96e537880b99a Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 22 Nov 2021 10:18:47 +0100 Subject: [PATCH 049/108] Update renovate --- .github/renovate.json | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 .github/renovate.json diff --git a/.github/renovate.json b/.github/renovate.json deleted file mode 100644 index 72240caadae..00000000000 --- a/.github/renovate.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "lockFileMaintenance": { - "enabled": true, - "automerge": true - } -} From 65eddd11a7457f7d8a71ed927c9ee72c0f3a92a4 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 22 Nov 2021 10:01:29 +0000 Subject: [PATCH 050/108] Update all dependencies | datasource | package | from | to | | -------------- | ------------------------------------------------------------- | -------- | ------- | | gradle-version | gradle | 7.2 | 7.3 | | maven | io.kotest.multiplatform:io.kotest.multiplatform.gradle.plugin | 5.0.0.RC | 5.0.0.6 | --- libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs.versions.toml b/libs.versions.toml index c28a32d950e..fa7e7054098 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -4,7 +4,7 @@ arrowGradleConfig = "0.5.1" coroutines = "1.5.2" dokka = "1.5.31" kotest = "5.0.0.RC" -kotestGradle = "5.0.0.RC" +kotestGradle = "5.0.0.6" kotlin = "1.6.0" kotlinBinaryCompatibilityValidator = "0.8.0" githooks = "0.0.2" From cf3ecc294a058a70d7e2ddb0f42cf2f323175259 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 23 Nov 2021 05:43:16 +0000 Subject: [PATCH 051/108] Update actions/cache action to v2.1.7 | datasource | package | from | to | | ----------- | ------------- | ------ | ------ | | github-tags | actions/cache | v2.1.6 | v2.1.7 | | github-tags | actions/cache | v2.1.6 | v2.1.7 | --- .github/workflows/build.yaml | 2 +- .github/workflows/pr.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bc616623eb6..ce9f7a1f3a0 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -27,7 +27,7 @@ jobs: - name: Restore Gradle cache id: cache - uses: actions/cache@v2.1.6 + uses: actions/cache@v2.1.7 with: path: | ~/.gradle/caches diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 03146df5f36..588ee3c20b7 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -23,7 +23,7 @@ jobs: - name: Restore Gradle cache id: cache - uses: actions/cache@v2.1.6 + uses: actions/cache@v2.1.7 with: path: | ~/.gradle/caches From 698eacce86fc34451380e12da2f462d2f99792b5 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 23 Nov 2021 09:55:34 +0000 Subject: [PATCH 052/108] Update all dependencies to v1.6.0 | datasource | package | from | to | | ---------- | ----------------------------------------------------- | ------ | ----- | | maven | org.jetbrains.dokka:org.jetbrains.dokka.gradle.plugin | 1.5.31 | 1.6.0 | | maven | org.jetbrains.dokka:dokka-core | 1.5.31 | 1.6.0 | --- libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs.versions.toml b/libs.versions.toml index fa7e7054098..4fa1a7fc2e4 100644 --- a/libs.versions.toml +++ b/libs.versions.toml @@ -2,7 +2,7 @@ arrow = "1.0.1" arrowGradleConfig = "0.5.1" coroutines = "1.5.2" -dokka = "1.5.31" +dokka = "1.6.0" kotest = "5.0.0.RC" kotestGradle = "5.0.0.6" kotlin = "1.6.0" From 31692c58861e7c7b1552037576874de5d7e96b5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" Date: Tue, 23 Nov 2021 09:58:42 +0000 Subject: [PATCH 053/108] Auto update docs --- docs/-cont/arrow/-cont-effect/bind.html | 65 +- docs/-cont/arrow/-cont-effect/ensure.html | 41 +- docs/-cont/arrow/-cont-effect/index.html | 106 +-- docs/-cont/arrow/-cont-effect/shift.html | 41 +- docs/-cont/arrow/-cont/attempt.html | 41 +- docs/-cont/arrow/-cont/fold.html | 47 +- docs/-cont/arrow/-cont/handle-error-with.html | 41 +- docs/-cont/arrow/-cont/handle-error.html | 41 +- docs/-cont/arrow/-cont/index.html | 152 ++-- docs/-cont/arrow/-cont/redeem-with.html | 41 +- docs/-cont/arrow/-cont/redeem.html | 41 +- docs/-cont/arrow/-cont/to-either.html | 41 +- docs/-cont/arrow/-cont/to-ior.html | 41 +- docs/-cont/arrow/-cont/to-option.html | 41 +- docs/-cont/arrow/-cont/to-validated.html | 41 +- docs/-cont/arrow/-ior-effect/-ior-effect.html | 41 +- docs/-cont/arrow/-ior-effect/bind.html | 41 +- docs/-cont/arrow/-ior-effect/index.html | 126 +--- docs/-cont/arrow/-ior-effect/shift.html | 41 +- .../arrow/-option-effect/-option-effect.html | 41 +- docs/-cont/arrow/-option-effect/bind.html | 41 +- docs/-cont/arrow/-option-effect/ensure.html | 41 +- docs/-cont/arrow/-option-effect/index.html | 102 +-- docs/-cont/arrow/-option-effect/shift.html | 41 +- .../arrow/-restricted-cont-effect/bind.html | 41 +- .../arrow/-restricted-cont-effect/index.html | 56 +- .../arrow/-restricted-cont-effect/shift.html | 41 +- .../-cont/arrow/-restricted-cont/attempt.html | 41 +- .../arrow/-restricted-cont/flat-map.html | 41 +- docs/-cont/arrow/-restricted-cont/fold.html | 41 +- .../-restricted-cont/handle-error-with.html | 41 +- .../arrow/-restricted-cont/handle-error.html | 41 +- docs/-cont/arrow/-restricted-cont/index.html | 136 ++-- docs/-cont/arrow/-restricted-cont/map.html | 41 +- .../arrow/-restricted-cont/redeem-with.html | 41 +- docs/-cont/arrow/-restricted-cont/redeem.html | 41 +- .../arrow/-restricted-cont/to-either.html | 41 +- .../arrow/-restricted-cont/to-validated.html | 41 +- .../-shift-cancellation-exception/index.html | 40 +- docs/-cont/arrow/cont.html | 41 +- docs/-cont/arrow/either.html | 41 +- docs/-cont/arrow/ensure-not-null.html | 47 +- docs/-cont/arrow/index.html | 180 ++--- docs/-cont/arrow/ior.html | 41 +- docs/-cont/arrow/option.html | 41 +- docs/-cont/arrow/restricted-cont.html | 41 +- docs/-cont/arrow/to-option.html | 41 +- docs/images/arrow_down.svg | 6 +- docs/images/logo-icon.svg | 13 +- docs/images/theme-toggle.svg | 4 + docs/index.html | 38 +- docs/navigation.html | 4 +- docs/scripts/main.js | 30 +- docs/scripts/platform-content-handler.js | 130 ++-- docs/scripts/prism.js | 13 + docs/styles/logo-styles.css | 16 +- docs/styles/main.css | 6 +- docs/styles/prism.css | 103 +++ docs/styles/style.css | 676 ++++++++---------- 59 files changed, 1657 insertions(+), 1915 deletions(-) create mode 100644 docs/images/theme-toggle.svg create mode 100644 docs/scripts/prism.js create mode 100644 docs/styles/prism.css diff --git a/docs/-cont/arrow/-cont-effect/bind.html b/docs/-cont/arrow/-cont-effect/bind.html index 98ebb96ee26..2786e532a06 100644 --- a/docs/-cont/arrow/-cont-effect/bind.html +++ b/docs/-cont/arrow/-cont-effect/bind.html @@ -2,59 +2,34 @@ bind - + + +
-
- - -
+
-
-
-
- +
+
+

bind

-
- -
-
open suspend fun <B> Cont<R, B>.bind(): B
-
-

Runs the Cont to finish, returning B or shift in case of R.

fun <E, A> Either<E, A>.toCont(): Cont<E, A> = cont {
fold({ e -> shift(e) }, ::identity)
}

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.toCont().bind()
x
}.toEither() shouldBe either
}
-
- -
-
open suspend fun <B> Either<R, B>.bind(): B
-
-

Folds Either into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.bind()
x
}.toEither() shouldBe either
}
-
- -
-
open suspend fun <B> Validated<R, B>.bind(): B
-
-

Folds Validated into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated ->
cont<String, Int> {
val x: Int = validated.bind()
x
}.toValidated() shouldBe validated
}
-
- -
-
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
-
-

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.result(Arb.int())) { result ->
cont<String, Int> {
val x: Int = result.bind { _: Throwable -> default }
x
}.fold({ default }, ::identity) shouldBe result.getOrElse { default }
}
-
- -
-
open suspend fun <B> Option<B>.bind(shift: () -> R): B
-
-

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.option(Arb.int())) { option ->
cont<String, Int> {
val x: Int = option.bind { default }
x
}.fold({ default }, ::identity) shouldBe option.getOrElse { default }
}
+
open suspend fun <B> Cont<R, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

fun <E, A> Either<E, A>.toCont(): Cont<E, A> = cont {
fold({ e -> shift(e) }, ::identity)
}

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.toCont().bind()
x
}.toEither() shouldBe either
}

open suspend fun <B> Either<R, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.bind()
x
}.toEither() shouldBe either
}

open suspend fun <B> Validated<R, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated ->
cont<String, Int> {
val x: Int = validated.bind()
x
}.toValidated() shouldBe validated
}

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.result(Arb.int())) { result ->
cont<String, Int> {
val x: Int = result.bind { _: Throwable -> default }
x
}.fold({ default }, ::identity) shouldBe result.getOrElse { default }
}

open suspend fun <B> Option<B>.bind(shift: () -> R): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.option(Arb.int())) { option ->
cont<String, Int> {
val x: Int = option.bind { default }
x
}.fold({ default }, ::identity) shouldBe option.getOrElse { default }
}
- +
diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html index c2dfd49fe2a..8cc051235e6 100644 --- a/docs/-cont/arrow/-cont-effect/ensure.html +++ b/docs/-cont/arrow/-cont-effect/ensure.html @@ -2,33 +2,32 @@ ensure - + + +
-
- - -
+
-
-
-
- +
+
+

ensure

-
- -
-
open suspend fun ensure(condition: Boolean, shift: () -> R)
-
-

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int ->
cont<String, Int> {
ensure(condition) { failure }
int
}.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure)
}
+
open suspend fun ensure(condition: Boolean, shift: () -> R)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int ->
cont<String, Int> {
ensure(condition) { failure }
int
}.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure)
}

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html index d89134f86e0..40157c7dd24 100644 --- a/docs/-cont/arrow/-cont-effect/index.html +++ b/docs/-cont/arrow/-cont-effect/index.html @@ -2,27 +2,31 @@ ContEffect - + + +
-
- - -
+
-
-
-
- +
+
+

ContEffect

-
interface ContEffect<R>

Context of the Cont DSL.

+
interface ContEffect<R>

Context of the Cont DSL.

@@ -35,37 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun <B> Cont<R, B>.bind(): B
-
-

Runs the Cont to finish, returning B or shift in case of R.

-
- -
-
open suspend fun <B> Either<R, B>.bind(): B
-
-

Folds Either into Cont, by returning B or a shift with R.

-
- -
-
open suspend fun <B> Validated<R, B>.bind(): B
-
-

Folds Validated into Cont, by returning B or a shift with R.

-
- -
-
open suspend fun <B> Option<B>.bind(shift: () -> R): B
-
-

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

-
- -
-
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
-
-

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
+
+
open suspend fun <B> Cont<R, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<R, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<R, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

open suspend fun <B> Option<B>.bind(shift: () -> R): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

+
@@ -76,13 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun ensure(condition: Boolean, shift: () -> R)
-
-

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
+
+
open suspend fun ensure(condition: Boolean, shift: () -> R)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

+
@@ -93,13 +65,9 @@

Functions

Link copied to clipboard
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-
+
+
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

+
@@ -132,19 +100,9 @@

Extensions

Link copied to clipboard
-
- -
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
-
-

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

-
- -
-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
-
+
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
+
@@ -163,7 +121,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html index da094c9d949..ab61f939e48 100644 --- a/docs/-cont/arrow/-cont-effect/shift.html +++ b/docs/-cont/arrow/-cont-effect/shift.html @@ -2,33 +2,32 @@ shift - + + +
-
- - -
+
-
-
-
- +
+
+

shift

-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
+
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html index 7c7d1ed2884..836c2a03eb1 100644 --- a/docs/-cont/arrow/-cont/attempt.html +++ b/docs/-cont/arrow/-cont/attempt.html @@ -2,33 +2,32 @@ attempt - + + +
-
- - -
+
-
-
-
- +
+
+

attempt

-
- -
-
open fun attempt(): Cont<R, Result<A>>
-
-

Runs the Cont and captures any NonFatal exception into Result.

+
open fun attempt(): Cont<R, Result<A>>

Runs the Cont and captures any NonFatal exception into Result.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/fold.html b/docs/-cont/arrow/-cont/fold.html index f9745e94be5..f1e7bed760e 100644 --- a/docs/-cont/arrow/-cont/fold.html +++ b/docs/-cont/arrow/-cont/fold.html @@ -2,41 +2,34 @@ fold - + + +
-
- - -
+
-
-
-
- +
+
+

fold

-
- -
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

suspend fun test() {
val shift = cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
shift shouldBe "Hello, World!"

val res = cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
res shouldBe 1000
}
-
- -
-
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

suspend fun test() {
val shift = cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
shift shouldBe "Hello, World!"

val res = cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
res shouldBe 1000
}

open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

- +
diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html index f55aee4f7b2..a09454cf586 100644 --- a/docs/-cont/arrow/-cont/handle-error-with.html +++ b/docs/-cont/arrow/-cont/handle-error-with.html @@ -2,33 +2,32 @@ handleErrorWith - + + +
-
- - -
+
-
-
-
- +
+
+

handleErrorWith

-
- -
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html index 8da3cb874b3..80e192e78da 100644 --- a/docs/-cont/arrow/-cont/handle-error.html +++ b/docs/-cont/arrow/-cont/handle-error.html @@ -2,33 +2,32 @@ handleError - + + +
-
- - -
+
-
-
-
- +
+
+

handleError

-
- -
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-
-
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html index df0c7091b91..2c75271a995 100644 --- a/docs/-cont/arrow/-cont/index.html +++ b/docs/-cont/arrow/-cont/index.html @@ -2,27 +2,31 @@ Cont - + + +
-
- - -
+
-
-
-
- +
+
+

Cont

-
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

+
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

@@ -35,13 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun attempt(): Cont<R, Result<A>>
-
-

Runs the Cont and captures any NonFatal exception into Result.

-
+
+
open fun attempt(): Cont<R, Result<A>>

Runs the Cont and captures any NonFatal exception into Result.

+
@@ -52,19 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

-
- -
-
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Like fold but also allows folding over any unexpected Throwable that might have occurred.

-
+
+
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B

Like fold but also allows folding over any unexpected Throwable that might have occurred.

+
@@ -75,13 +65,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-
-
-
+
+
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
+
@@ -92,13 +78,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
-
+
+
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
+
@@ -109,13 +91,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-
-
-
+
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
+
@@ -126,13 +104,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-
-
-
+
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
+
@@ -143,13 +117,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun toEither(): Either<R, A>
-
-

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

-
+
+
open suspend fun toEither(): Either<R, A>

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+
@@ -160,13 +130,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun toIor(): Ior<R, A>
-
-

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

-
+
+
open suspend fun toIor(): Ior<R, A>

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+
@@ -177,13 +143,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
-
-

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

-
+
+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+
@@ -194,13 +156,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun toValidated(): Validated<R, A>
-
-

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

-
+
+
open suspend fun toValidated(): Validated<R, A>

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+
@@ -213,13 +171,9 @@

Extensions

Link copied to clipboard
-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
+
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
@@ -238,7 +192,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html index 7cb7847b1cf..33a99766962 100644 --- a/docs/-cont/arrow/-cont/redeem-with.html +++ b/docs/-cont/arrow/-cont/redeem-with.html @@ -2,33 +2,32 @@ redeemWith - + + +
-
- - -
+
-
-
-
- +
+
+

redeemWith

-
- -
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-
-
+
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html index 7437745d7ca..d4740f44c05 100644 --- a/docs/-cont/arrow/-cont/redeem.html +++ b/docs/-cont/arrow/-cont/redeem.html @@ -2,33 +2,32 @@ redeem - + + +
-
- - -
+
-
-
-
- +
+
+

redeem

-
- -
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-
-
+
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/to-either.html b/docs/-cont/arrow/-cont/to-either.html index 6d9560f5926..6f7550deb4e 100644 --- a/docs/-cont/arrow/-cont/to-either.html +++ b/docs/-cont/arrow/-cont/to-either.html @@ -2,33 +2,32 @@ toEither - + + +
-
- - -
+
-
-
-
- +
+
+

toEither

-
- -
-
open suspend fun toEither(): Either<R, A>
-
-

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

+
open suspend fun toEither(): Either<R, A>

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/to-ior.html b/docs/-cont/arrow/-cont/to-ior.html index bb36145b5e2..4fe3617bd0a 100644 --- a/docs/-cont/arrow/-cont/to-ior.html +++ b/docs/-cont/arrow/-cont/to-ior.html @@ -2,33 +2,32 @@ toIor - + + +
-
- - -
+
-
-
-
- +
+
+

toIor

-
- -
-
open suspend fun toIor(): Ior<R, A>
-
-

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

+
open suspend fun toIor(): Ior<R, A>

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html index 753225068c0..1749c8c9211 100644 --- a/docs/-cont/arrow/-cont/to-option.html +++ b/docs/-cont/arrow/-cont/to-option.html @@ -2,33 +2,32 @@ toOption - + + +
-
- - -
+
-
-
-
- +
+
+

toOption

-
- -
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
-
-

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

+
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-cont/to-validated.html b/docs/-cont/arrow/-cont/to-validated.html index 794a850a02e..e6d525d9f00 100644 --- a/docs/-cont/arrow/-cont/to-validated.html +++ b/docs/-cont/arrow/-cont/to-validated.html @@ -2,33 +2,32 @@ toValidated - + + +
-
- - -
+
-
-
-
- +
+
+

toValidated

-
- -
-
open suspend fun toValidated(): Validated<R, A>
-
-

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

+
open suspend fun toValidated(): Validated<R, A>

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-ior-effect/-ior-effect.html b/docs/-cont/arrow/-ior-effect/-ior-effect.html index 11312ffc4e7..d1ed43e5bbb 100644 --- a/docs/-cont/arrow/-ior-effect/-ior-effect.html +++ b/docs/-cont/arrow/-ior-effect/-ior-effect.html @@ -2,33 +2,32 @@ IorEffect - + + +
-
- - -
+
-
-
-
- +
+
+

IorEffect

-
- -
-
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)
-
-
+
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html index 35186b2813c..f9ae75ed1ce 100644 --- a/docs/-cont/arrow/-ior-effect/bind.html +++ b/docs/-cont/arrow/-ior-effect/bind.html @@ -2,33 +2,32 @@ bind - + + +
-
- - -
+
-
-
-
- +
+
+

bind

-
- -
-
suspend fun <B> Ior<E, B>.bind(): B
-
-
+
suspend fun <B> Ior<E, B>.bind(): B

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-ior-effect/index.html b/docs/-cont/arrow/-ior-effect/index.html index 0887a33d5ab..f25f7af137b 100644 --- a/docs/-cont/arrow/-ior-effect/index.html +++ b/docs/-cont/arrow/-ior-effect/index.html @@ -2,27 +2,31 @@ IorEffect - + + +
-
- - -
+
-
-
-
- +
+
+

IorEffect

-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
@@ -35,43 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun <B> Cont<E, B>.bind(): B
-
-

Runs the Cont to finish, returning B or shift in case of R.

-
- -
-
open suspend fun <B> Either<E, B>.bind(): B
-
-

Folds Either into Cont, by returning B or a shift with R.

-
- -
-
open suspend fun <B> Validated<E, B>.bind(): B
-
-

Folds Validated into Cont, by returning B or a shift with R.

-
- -
-
suspend fun <B> Ior<E, B>.bind(): B
-
-
-
- -
-
open suspend fun <B> Option<B>.bind(shift: () -> E): B
-
-

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

-
- -
-
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
-
-

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
+
+
open suspend fun <B> Cont<E, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<E, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<E, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun <B> Ior<E, B>.bind(): B

open suspend fun <B> Option<B>.bind(shift: () -> E): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

+
@@ -82,13 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
open override fun E.combine(b: E): E
-
-
-
+
+
open override fun E.combine(b: E): E
+
@@ -99,13 +65,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun ensure(condition: Boolean, shift: () -> E)
-
-

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
+
+
open suspend fun ensure(condition: Boolean, shift: () -> E)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

+
@@ -116,13 +78,9 @@

Functions

Link copied to clipboard
-
- -
-
open override fun E.maybeCombine(b: E?): E
-
-
-
+
+
open override fun E.maybeCombine(b: E?): E
+
@@ -133,13 +91,9 @@

Functions

Link copied to clipboard
-
- -
-
open operator override fun E.plus(b: E): E
-
-
-
+
+
open operator override fun E.plus(b: E): E
+
@@ -150,13 +104,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend override fun <B> shift(r: E): B
-
-

Short-circuit the Cont computation with value R.

-
+
+
open suspend override fun <B> shift(r: E): B

Short-circuit the Cont computation with value R.

+
@@ -175,7 +125,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html index d8f57d6bb04..69f2074be1a 100644 --- a/docs/-cont/arrow/-ior-effect/shift.html +++ b/docs/-cont/arrow/-ior-effect/shift.html @@ -2,33 +2,32 @@ shift - + + +
-
- - -
+
-
-
-
- +
+
+

shift

-
- -
-
open suspend override fun <B> shift(r: E): B
-
-

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
+
open suspend override fun <B> shift(r: E): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-option-effect/-option-effect.html b/docs/-cont/arrow/-option-effect/-option-effect.html index 8e9a6203294..f99b1905856 100644 --- a/docs/-cont/arrow/-option-effect/-option-effect.html +++ b/docs/-cont/arrow/-option-effect/-option-effect.html @@ -2,33 +2,32 @@ OptionEffect - + + +
-
- - -
+
-
-
-
- +
+
+

OptionEffect

-
- -
-
fun OptionEffect(cont: ContEffect<None>)
-
-
+
fun OptionEffect(cont: ContEffect<None>)

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-option-effect/bind.html b/docs/-cont/arrow/-option-effect/bind.html index 3a0a59a1b65..af262029008 100644 --- a/docs/-cont/arrow/-option-effect/bind.html +++ b/docs/-cont/arrow/-option-effect/bind.html @@ -2,33 +2,32 @@ bind - + + +
-
- - -
+
-
-
-
- +
+
+

bind

-
- -
-
suspend fun <B> Option<B>.bind(): B
-
-
+
suspend fun <B> Option<B>.bind(): B

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-option-effect/ensure.html b/docs/-cont/arrow/-option-effect/ensure.html index 4adf7508de6..13e9a9cab0e 100644 --- a/docs/-cont/arrow/-option-effect/ensure.html +++ b/docs/-cont/arrow/-option-effect/ensure.html @@ -2,33 +2,32 @@ ensure - + + +
-
- - -
+
-
-
-
- +
+
+

ensure

-
- -
-
suspend fun ensure(value: Boolean)
-
-
+
suspend fun ensure(value: Boolean)

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-option-effect/index.html b/docs/-cont/arrow/-option-effect/index.html index 5967c89a43f..bd40d2cc073 100644 --- a/docs/-cont/arrow/-option-effect/index.html +++ b/docs/-cont/arrow/-option-effect/index.html @@ -2,27 +2,31 @@ OptionEffect - + + +
-
- - -
+
-
-
-
- +
+
+

OptionEffect

-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
@@ -35,43 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun <B> Cont<None, B>.bind(): B
-
-

Runs the Cont to finish, returning B or shift in case of R.

-
- -
-
open suspend fun <B> Either<None, B>.bind(): B
-
-

Folds Either into Cont, by returning B or a shift with R.

-
- -
-
open suspend fun <B> Validated<None, B>.bind(): B
-
-

Folds Validated into Cont, by returning B or a shift with R.

-
- -
-
suspend fun <B> Option<B>.bind(): B
-
-
-
- -
-
open suspend fun <B> Option<B>.bind(shift: () -> None): B
-
-

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

-
- -
-
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
-
-

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
+
+
open suspend fun <B> Cont<None, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<None, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<None, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun <B> Option<B>.bind(): B

open suspend fun <B> Option<B>.bind(shift: () -> None): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

+
@@ -82,19 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun ensure(value: Boolean)
-
-
-
- -
-
open suspend fun ensure(condition: Boolean, shift: () -> None)
-
-

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
+
+
suspend fun ensure(value: Boolean)

open suspend fun ensure(condition: Boolean, shift: () -> None)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

+
@@ -105,13 +65,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend override fun <B> shift(r: None): B
-
-

Short-circuit the Cont computation with value R.

-
+
+
open suspend override fun <B> shift(r: None): B

Short-circuit the Cont computation with value R.

+
@@ -130,7 +86,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-option-effect/shift.html b/docs/-cont/arrow/-option-effect/shift.html index 6b483953580..2f13b2d77ff 100644 --- a/docs/-cont/arrow/-option-effect/shift.html +++ b/docs/-cont/arrow/-option-effect/shift.html @@ -2,33 +2,32 @@ shift - + + +
-
- - -
+
-
-
-
- +
+
+

shift

-
- -
-
open suspend override fun <B> shift(r: None): B
-
-

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
+
open suspend override fun <B> shift(r: None): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont-effect/bind.html b/docs/-cont/arrow/-restricted-cont-effect/bind.html index 3ae1cf2e9c5..1c73843bd1b 100644 --- a/docs/-cont/arrow/-restricted-cont-effect/bind.html +++ b/docs/-cont/arrow/-restricted-cont-effect/bind.html @@ -2,33 +2,32 @@ bind - + + +
-
- - -
+
-
-
-
- +
+
+

bind

-
- -
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-
-
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont-effect/index.html b/docs/-cont/arrow/-restricted-cont-effect/index.html index 5c1647abba6..7366174ec46 100644 --- a/docs/-cont/arrow/-restricted-cont-effect/index.html +++ b/docs/-cont/arrow/-restricted-cont-effect/index.html @@ -2,27 +2,31 @@ RestrictedContEffect - + + +
-
- - -
+
-
-
-
- +
+
+

RestrictedContEffect

-
interface RestrictedContEffect<R>
+
interface RestrictedContEffect<R>
@@ -35,13 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-
-
-
+
+
open suspend fun <A> RestrictedCont<R, A>.bind(): A
+
@@ -52,13 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-
+
+
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

+
@@ -77,7 +73,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont-effect/shift.html b/docs/-cont/arrow/-restricted-cont-effect/shift.html index 75eeffb1dae..516dbfd7a98 100644 --- a/docs/-cont/arrow/-restricted-cont-effect/shift.html +++ b/docs/-cont/arrow/-restricted-cont-effect/shift.html @@ -2,33 +2,32 @@ shift - + + +
-
- - -
+
-
-
-
- +
+
+

shift

-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

+
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/attempt.html b/docs/-cont/arrow/-restricted-cont/attempt.html index f499e255dbd..fe4546e9be3 100644 --- a/docs/-cont/arrow/-restricted-cont/attempt.html +++ b/docs/-cont/arrow/-restricted-cont/attempt.html @@ -2,33 +2,32 @@ attempt - + + +
-
- - -
+
-
-
-
- +
+
+

attempt

-
- -
-
open fun attempt(): RestrictedCont<R, Result<A>>
-
-
+
open fun attempt(): RestrictedCont<R, Result<A>>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/flat-map.html b/docs/-cont/arrow/-restricted-cont/flat-map.html index e4f1bc634c0..00c8b776b48 100644 --- a/docs/-cont/arrow/-restricted-cont/flat-map.html +++ b/docs/-cont/arrow/-restricted-cont/flat-map.html @@ -2,33 +2,32 @@ flatMap - + + +
-
- - -
+
-
-
-
- +
+
+

flatMap

-
- -
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-
-
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/fold.html b/docs/-cont/arrow/-restricted-cont/fold.html index 920f16ab631..2015485d10c 100644 --- a/docs/-cont/arrow/-restricted-cont/fold.html +++ b/docs/-cont/arrow/-restricted-cont/fold.html @@ -2,33 +2,32 @@ fold - + + +
-
- - -
+
-
-
-
- +
+
+

fold

-
- -
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-
-
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/handle-error-with.html b/docs/-cont/arrow/-restricted-cont/handle-error-with.html index 47d096e6f61..9cbda0eac6c 100644 --- a/docs/-cont/arrow/-restricted-cont/handle-error-with.html +++ b/docs/-cont/arrow/-restricted-cont/handle-error-with.html @@ -2,33 +2,32 @@ handleErrorWith - + + +
-
- - -
+
-
-
-
- +
+
+

handleErrorWith

-
- -
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-
-
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/handle-error.html b/docs/-cont/arrow/-restricted-cont/handle-error.html index eb5cfbd5ab1..3eff0690c42 100644 --- a/docs/-cont/arrow/-restricted-cont/handle-error.html +++ b/docs/-cont/arrow/-restricted-cont/handle-error.html @@ -2,33 +2,32 @@ handleError - + + +
-
- - -
+
-
-
-
- +
+
+

handleError

-
- -
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-
-
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/index.html b/docs/-cont/arrow/-restricted-cont/index.html index 7f6eedfe507..e9d47391522 100644 --- a/docs/-cont/arrow/-restricted-cont/index.html +++ b/docs/-cont/arrow/-restricted-cont/index.html @@ -2,27 +2,31 @@ RestrictedCont - + + +
-
- - -
+
-
-
-
- +
+
+

RestrictedCont

-
interface RestrictedCont<R, A>
+
interface RestrictedCont<R, A>
@@ -35,13 +39,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun attempt(): RestrictedCont<R, Result<A>>
-
-
-
+
+
open fun attempt(): RestrictedCont<R, Result<A>>
+
@@ -52,13 +52,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-
-
-
+
+
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
+
@@ -69,13 +65,9 @@

Functions

Link copied to clipboard
-
- -
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-
-
-
+
+
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
+
@@ -86,13 +78,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-
-
-
+
+
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
+
@@ -103,13 +91,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-
-
-
+
+
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
+
@@ -120,13 +104,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-
-
-
+
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
+
@@ -137,13 +117,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-
-
-
+
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
+
@@ -154,13 +130,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-
-
-
+
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
+
@@ -171,13 +143,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun toEither(): Either<R, A>
-
-
-
+
+
open fun toEither(): Either<R, A>
+
@@ -188,13 +156,9 @@

Functions

Link copied to clipboard
-
- -
-
open fun toValidated(): Validated<R, A>
-
-
-
+
+
open fun toValidated(): Validated<R, A>
+
@@ -213,7 +177,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/map.html b/docs/-cont/arrow/-restricted-cont/map.html index 09ae5442552..9b9a7fa6f66 100644 --- a/docs/-cont/arrow/-restricted-cont/map.html +++ b/docs/-cont/arrow/-restricted-cont/map.html @@ -2,33 +2,32 @@ map - + + +
-
- - -
+
-
-
-
- +
+
+

map

-
- -
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-
-
+
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/redeem-with.html b/docs/-cont/arrow/-restricted-cont/redeem-with.html index 6dec0257d9b..6f7b1169f3c 100644 --- a/docs/-cont/arrow/-restricted-cont/redeem-with.html +++ b/docs/-cont/arrow/-restricted-cont/redeem-with.html @@ -2,33 +2,32 @@ redeemWith - + + +
-
- - -
+
-
-
-
- +
+
+

redeemWith

-
- -
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-
-
+
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/redeem.html b/docs/-cont/arrow/-restricted-cont/redeem.html index 7d03b87ed1d..888fed6443c 100644 --- a/docs/-cont/arrow/-restricted-cont/redeem.html +++ b/docs/-cont/arrow/-restricted-cont/redeem.html @@ -2,33 +2,32 @@ redeem - + + +
-
- - -
+
-
-
-
- +
+
+

redeem

-
- -
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-
-
+
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/to-either.html b/docs/-cont/arrow/-restricted-cont/to-either.html index 36647dcaeb9..dbae1c1cd2b 100644 --- a/docs/-cont/arrow/-restricted-cont/to-either.html +++ b/docs/-cont/arrow/-restricted-cont/to-either.html @@ -2,33 +2,32 @@ toEither - + + +
-
- - -
+
-
-
-
- +
+
+

toEither

-
- -
-
open fun toEither(): Either<R, A>
-
-
+
open fun toEither(): Either<R, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-restricted-cont/to-validated.html b/docs/-cont/arrow/-restricted-cont/to-validated.html index 2d8c48e2be6..9aabc76a104 100644 --- a/docs/-cont/arrow/-restricted-cont/to-validated.html +++ b/docs/-cont/arrow/-restricted-cont/to-validated.html @@ -2,33 +2,32 @@ toValidated - + + +
-
- - -
+
-
-
-
- +
+
+

toValidated

-
- -
-
open fun toValidated(): Validated<R, A>
-
-
+
open fun toValidated(): Validated<R, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html index 693132ef49f..b7411120e1d 100644 --- a/docs/-cont/arrow/-shift-cancellation-exception/index.html +++ b/docs/-cont/arrow/-shift-cancellation-exception/index.html @@ -2,27 +2,31 @@ ShiftCancellationException - + + +
-
- - -
+
-
-
-
- +
+
+

ShiftCancellationException

-
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

+
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

@@ -36,7 +40,7 @@

Properties

-
open val cause: Throwable?
+
open val cause: Throwable?
@@ -49,7 +53,7 @@

Properties

-
open val message: String?
+
open val message: String?
@@ -69,7 +73,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/cont.html b/docs/-cont/arrow/cont.html index 7dccae53842..6c4c5d4dc30 100644 --- a/docs/-cont/arrow/cont.html +++ b/docs/-cont/arrow/cont.html @@ -2,33 +2,32 @@ cont - + + +
-
- - -
+
-
-
-
- +
+
+

cont

-
- -
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
-
-

DSL for constructing Cont values

suspend fun test() {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold({ fail("Shift can never be the result") }, { it shouldBe 6 })

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") })
}
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>

DSL for constructing Cont values

suspend fun test() {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold({ fail("Shift can never be the result") }, { it shouldBe 6 })

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") })
}

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/either.html b/docs/-cont/arrow/either.html index 6dadabc5592..eee8781c3a7 100644 --- a/docs/-cont/arrow/either.html +++ b/docs/-cont/arrow/either.html @@ -2,33 +2,32 @@ either - + + +
-
- - -
+
-
-
-
- +
+
+

either

-
- -
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-
-
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/ensure-not-null.html b/docs/-cont/arrow/ensure-not-null.html index 9ca1f81a2cc..e6bd185131d 100644 --- a/docs/-cont/arrow/ensure-not-null.html +++ b/docs/-cont/arrow/ensure-not-null.html @@ -2,41 +2,34 @@ ensureNotNull - + + +
-
- - -
+
-
-
-
- +
+
+

ensureNotNull

-
- -
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
-
-

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? ->
cont<String, Int> {
ensureNotNull(int) { failure }
}.toEither() shouldBe (int?.right() ?: failure.left())
}
-
- -
-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
+
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? ->
cont<String, Int> {
ensureNotNull(int) { failure }
}.toEither() shouldBe (int?.right() ?: failure.left())
}

suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
- +
diff --git a/docs/-cont/arrow/index.html b/docs/-cont/arrow/index.html index 9b475f49318..0090f859005 100644 --- a/docs/-cont/arrow/index.html +++ b/docs/-cont/arrow/index.html @@ -2,24 +2,28 @@ arrow - + + +
-
- - -
+
-
-
-
- +
+
+

Package arrow

@@ -34,13 +38,9 @@

Types

Link copied to clipboard
-
- -
-
interface Cont<R, A>
-
-

Cont represents a suspending computation that runs will either

-
+
+
interface Cont<R, A>

Cont represents a suspending computation that runs will either

+
@@ -51,13 +51,9 @@

Types

Link copied to clipboard
-
- -
-
interface ContEffect<R>
-
-

Context of the Cont DSL.

-
+
+
interface ContEffect<R>

Context of the Cont DSL.

+
@@ -68,13 +64,9 @@

Types

Link copied to clipboard
-
- -
-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
-
-
-
+
+
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
+
@@ -85,13 +77,9 @@

Types

Link copied to clipboard
-
- -
-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
-
-
-
+
+
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
+
@@ -102,13 +90,9 @@

Types

Link copied to clipboard
-
- -
-
interface RestrictedCont<R, A>
-
-
-
+
+
interface RestrictedCont<R, A>
+
@@ -119,13 +103,9 @@

Types

Link copied to clipboard
-
- -
-
interface RestrictedContEffect<R>
-
-
-
+
+
interface RestrictedContEffect<R>
+
@@ -136,13 +116,9 @@

Types

Link copied to clipboard
-
- -
-
sealed class ShiftCancellationException : CancellationException
-
-

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

-
+
+
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

+
@@ -155,13 +131,9 @@

Functions

Link copied to clipboard
-
- -
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
-
-

DSL for constructing Cont values

-
+
+
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>

DSL for constructing Cont values

+
@@ -172,13 +144,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-
-
-
+
+
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
+
@@ -189,19 +157,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
-
- -
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
-
-

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

-
+
+
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B

suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

+
@@ -212,13 +170,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-
-
-
+
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
+
@@ -229,13 +183,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-
-
-
+
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
+
@@ -246,13 +196,9 @@

Functions

Link copied to clipboard
-
- -
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
-
-

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-
+
+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+
@@ -263,13 +209,9 @@

Functions

Link copied to clipboard
-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
+
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>
+
@@ -277,7 +219,7 @@

Functions

- +
diff --git a/docs/-cont/arrow/ior.html b/docs/-cont/arrow/ior.html index ccfe54a3ed6..52c6dfa1aa4 100644 --- a/docs/-cont/arrow/ior.html +++ b/docs/-cont/arrow/ior.html @@ -2,33 +2,32 @@ ior - + + +
-
- - -
+
-
-
-
- +
+
+

ior

-
- -
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-
-
+
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/option.html b/docs/-cont/arrow/option.html index e71079f52bf..36038d05722 100644 --- a/docs/-cont/arrow/option.html +++ b/docs/-cont/arrow/option.html @@ -2,33 +2,32 @@ option - + + +
-
- - -
+
-
-
-
- +
+
+

option

-
- -
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-
-
+
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/restricted-cont.html b/docs/-cont/arrow/restricted-cont.html index 78f3e4ed309..5620af09c07 100644 --- a/docs/-cont/arrow/restricted-cont.html +++ b/docs/-cont/arrow/restricted-cont.html @@ -2,33 +2,32 @@ restrictedCont - + + +
-
- - -
+
-
-
-
- +
+
+

restrictedCont

-
- -
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
-
-

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

+
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/-cont/arrow/to-option.html b/docs/-cont/arrow/to-option.html index d1758476010..6dc2936f0d2 100644 --- a/docs/-cont/arrow/to-option.html +++ b/docs/-cont/arrow/to-option.html @@ -2,33 +2,32 @@ toOption - + + +
-
- - -
+
-
-
-
- +
+
+

toOption

-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
+
suspend fun <A> Cont<None, A>.toOption(): Option<A>

Sources

@@ -41,7 +40,7 @@

Sources

- +
diff --git a/docs/images/arrow_down.svg b/docs/images/arrow_down.svg index 89e7df4710b..c0388dee2ce 100644 --- a/docs/images/arrow_down.svg +++ b/docs/images/arrow_down.svg @@ -1,3 +1,3 @@ - - - + + + \ No newline at end of file diff --git a/docs/images/logo-icon.svg b/docs/images/logo-icon.svg index 1b3b3670e0d..1fea08773f3 100644 --- a/docs/images/logo-icon.svg +++ b/docs/images/logo-icon.svg @@ -1,3 +1,10 @@ - - - + + + + + + + + + + \ No newline at end of file diff --git a/docs/images/theme-toggle.svg b/docs/images/theme-toggle.svg new file mode 100644 index 00000000000..2a8d750ea98 --- /dev/null +++ b/docs/images/theme-toggle.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html index 9de9f476263..5777ba696b0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2,29 +2,33 @@ Cont - + + +
-
- - -
+
-
-
-
- +
+
+

Cont

-
  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

      • #strange-edge-cases

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensureNotNull(path) { EmptyPath }
ensure(path.isEmpty()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

      • #strange-edge-cases

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensureNotNull(path) { EmptyPath }
ensure(path.isEmpty()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

+-->

Packages

@@ -41,7 +45,7 @@

Packages

- +
diff --git a/docs/navigation.html b/docs/navigation.html index da048772463..c962756a1d9 100644 --- a/docs/navigation.html +++ b/docs/navigation.html @@ -1,7 +1,7 @@
- +
- + diff --git a/docs/scripts/main.js b/docs/scripts/main.js index b9637fa31ba..3141dbe50a2 100644 --- a/docs/scripts/main.js +++ b/docs/scripts/main.js @@ -1,17 +1,9 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=390)}([function(e,t,n){e.exports=n(264)()},function(e,t,n){"use strict";e.exports=n(239)},function(e,t,n){var r; +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=378)}([function(e,t,n){e.exports=n(262)()},function(e,t,n){"use strict";e.exports=n(237)},function(e,t,n){var r; /*! Copyright (c) 2017 Jed Watson. Licensed under the MIT License (MIT), see http://jedwatson.github.io/classnames -*/!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;to;)Q(e,n=r[o++],t[n]);return e},X=function(e){var t=F.call(this,e=x(e,!0));return!(this===W&&o(H,e)&&!o(U,e))&&(!(t||!o(this,e)||!o(H,e)||o(this,A)&&this[A][e])||t)},J=function(e,t){if(e=w(e),t=x(t,!0),e!==W||!o(H,t)||o(U,t)){var n=I(e,t);return!n||!o(H,t)||o(e,A)&&e[A][t]||(n.enumerable=!0),n}},Z=function(e){for(var t,n=z(w(e)),r=[],i=0;n.length>i;)o(H,t=n[i++])||t==A||t==c||r.push(t);return r},ee=function(e){for(var t,n=e===W,r=z(n?U:w(e)),i=[],a=0;r.length>a;)!o(H,t=r[a++])||n&&!o(W,t)||i.push(H[t]);return i};B||(l((R=function(){if(this instanceof R)throw TypeError("Symbol is not a constructor!");var e=p(arguments.length>0?arguments[0]:void 0),t=function(n){this===W&&t.call(U,n),o(this,A)&&o(this[A],e)&&(this[A][e]=!1),K(this,e,S(1,n))};return i&&G&&K(W,e,{configurable:!0,set:t}),q(e)}).prototype,"toString",(function(){return this._k})),E.f=J,C.f=Q,n(114).f=O.f=Z,n(95).f=X,T.f=ee,i&&!n(111)&&l(W,"propertyIsEnumerable",X,!0),h.f=function(e){return q(d(e))}),a(a.G+a.W+a.F*!B,{Symbol:R});for(var te="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),ne=0;te.length>ne;)d(te[ne++]);for(var re=P(d.store),oe=0;re.length>oe;)v(re[oe++]);a(a.S+a.F*!B,"Symbol",{for:function(e){return o(D,e+="")?D[e]:D[e]=R(e)},keyFor:function(e){if(!$(e))throw TypeError(e+" is not a symbol!");for(var t in D)if(D[t]===e)return t},useSetter:function(){G=!0},useSimple:function(){G=!1}}),a(a.S+a.F*!B,"Object",{create:function(e,t){return void 0===t?k(e):Y(k(e),t)},defineProperty:Q,defineProperties:Y,getOwnPropertyDescriptor:J,getOwnPropertyNames:Z,getOwnPropertySymbols:ee});var ie=u((function(){T.f(1)}));a(a.S+a.F*ie,"Object",{getOwnPropertySymbols:function(e){return T.f(_(e))}}),M&&a(a.S+a.F*(!B||u((function(){var e=R();return"[null]"!=N([e])||"{}"!=N({a:e})||"{}"!=N(Object(e))}))),"JSON",{stringify:function(e){for(var t,n,r=[e],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=t=r[1],(b(t)||void 0!==e)&&!$(e))return m(t)||(t=function(e,t){if("function"==typeof n&&(t=n.call(this,e,t)),!$(t))return t}),r[1]=t,N.apply(M,r)}}),R.prototype[L]||n(59)(R.prototype,L,R.prototype.valueOf),f(R,"Symbol"),f(Math,"Math",!0),f(r.JSON,"JSON",!0)},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperty:n(39).f})},function(e,t,n){"use strict";n(257);var r=n(27),o=n(135),i=n(30),a=/./.toString,l=function(e){n(42)(RegExp.prototype,"toString",e,!0)};n(31)((function(){return"/a/b"!=a.call({source:"a",flags:"b"})}))?l((function(){var e=r(this);return"/".concat(e.source,"/","flags"in e?e.flags:!i&&e instanceof RegExp?o.call(e):void 0)})):"toString"!=a.name&&l((function(){return a.call(this)}))},function(e,t,n){var r=Date.prototype,o=r.toString,i=r.getTime;new Date(NaN)+""!="Invalid Date"&&n(42)(r,"toString",(function(){var e=i.call(this);return e==e?o.call(this):"Invalid Date"}))},function(e,t,n){n(182)("asyncIterator")},function(e,t,n){var r=n(32),o=n(79),i=n(59),a=n(42),l=n(80),c=function(e,t,n){var u,s,f,p,d=e&c.F,h=e&c.G,v=e&c.S,g=e&c.P,m=e&c.B,y=h?r:v?r[t]||(r[t]={}):(r[t]||{}).prototype,b=h?o:o[t]||(o[t]={}),_=b.prototype||(b.prototype={});for(u in h&&(n=t),n)f=((s=!d&&y&&void 0!==y[u])?y:n)[u],p=m&&s?l(f,r):g&&"function"==typeof f?l(Function.call,f):f,y&&a(y,u,f,e&c.U),b[u]!=f&&i(b,u,p),g&&_[u]!=f&&(_[u]=f)};r.core=o,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){for(var r=n(12),o=n(69),i=n(42),a=n(32),l=n(59),c=n(96),u=n(25),s=u("iterator"),f=u("toStringTag"),p=c.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=o(d),v=0;v=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])}),"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(e,t,n){var r=n(10);r(r.S,"Object",{create:n(83)})},function(e,t,n){var r=n(10),o=n(83),i=n(81),a=n(27),l=n(29),c=n(31),u=n(184),s=(n(32).Reflect||{}).construct,f=c((function(){function e(){}return!(s((function(){}),[],e)instanceof e)})),p=!c((function(){s((function(){}))}));r(r.S+r.F*(f||p),"Reflect",{construct:function(e,t){i(e),a(t);var n=arguments.length<3?e:i(arguments[2]);if(p&&!f)return s(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var r=[null];return r.push.apply(r,t),new(u.apply(e,r))}var c=n.prototype,d=o(l(c)?c:Object.prototype),h=Function.apply.call(e,d,t);return l(h)?h:d}})},function(e,t,n){var r=n(10);r(r.S,"Object",{setPrototypeOf:n(180).set})},function(e,t,n){var r=n(54),o=n(69);n(252)("keys",(function(){return function(e){return o(r(e))}}))},function(e,t,n){"use strict";var r=n(10),o=n(130)(!1),i=[].indexOf,a=!!i&&1/[1].indexOf(1,-0)<0;r(r.P+r.F*(a||!n(71)(i)),"Array",{indexOf:function(e){return a?i.apply(this,arguments)||0:o(this,e,arguments[1])}})},function(e,t,n){var r=n(26),o=n(266);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(10);r(r.S+r.F,"Object",{assign:n(185)})},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}},function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,l=btoa(unescape(encodeURIComponent(JSON.stringify(a)))),c="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(l),"/*# ".concat(c," */")),i=r.sources.map((function(e){return"/*# sourceURL=".concat(r.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([o]).join("\n")}var a,l,c;return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(r)for(var i=0;i=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})}))},function(e,t,n){var r=n(35),o=n(28),i=n(98),a=n(73),l=n(74),c=function(e,t,n){var u,s,f,p=e&c.F,d=e&c.G,h=e&c.S,v=e&c.P,g=e&c.B,m=e&c.W,y=d?o:o[t]||(o[t]={}),b=y.prototype,_=d?r:h?r[t]:(r[t]||{}).prototype;for(u in d&&(n=t),n)(s=!p&&_&&void 0!==_[u])&&l(y,u)||(f=s?_[u]:n[u],y[u]=d&&"function"!=typeof _[u]?n[u]:g&&s?i(f,r):m&&_[u]==f?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(f):v&&"function"==typeof f?i(Function.call,f):f,v&&((y.virtual||(y.virtual={}))[u]=f,e&c.R&&b&&!b[u]&&a(b,u,f)))};c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){var r=n(26),o=n(332);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(113),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(70);e.exports=function(e){return Object(r(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(1);r(r.P+r.F*!n(71)([].map,!0),"Array",{map:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(64);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){e.exports=!n(85)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";var r=n(80),o=n(10),i=n(54),a=n(189),l=n(190),c=n(53),u=n(174),s=n(191);o(o.S+o.F*!n(192)((function(e){Array.from(e)})),"Array",{from:function(e){var t,n,o,f,p=i(e),d="function"==typeof this?this:Array,h=arguments.length,v=h>1?arguments[1]:void 0,g=void 0!==v,m=0,y=s(p);if(g&&(v=r(v,h>2?arguments[2]:void 0,2)),null==y||d==Array&&l(y))for(n=new d(t=c(p.length));t>m;m++)u(n,m,g?v(p[m],m):p[m]);else for(f=y.call(p),n=new d;!(o=f.next()).done;m++)u(n,m,g?a(f,v,[o.value,m],!0):o.value);return n.length=m,n}})},function(e,t,n){var r=n(39),o=n(91);e.exports=n(30)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(112),o=n(70);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(0),i=n(71)([].forEach,!0);r(r.P+r.F*!i,"Array",{forEach:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(80),o=n(112),i=n(54),a=n(53),l=n(259);e.exports=function(e,t){var n=1==e,c=2==e,u=3==e,s=4==e,f=6==e,p=5==e||f,d=t||l;return function(t,l,h){for(var v,g,m=i(t),y=o(m),b=r(l,h,3),_=a(y.length),w=0,x=n?d(t,_):c?d(t,0):void 0;_>w;w++)if((p||w in y)&&(g=b(v=y[w],w,m),e))if(n)x[w]=g;else if(g)switch(e){case 3:return!0;case 5:return v;case 6:return w;case 2:x.push(v)}else if(s)return!1;return f?-1:u||s?s:x}}},function(e,t,n){var r=n(56),o=n(200),i=n(147),a=Object.defineProperty;t.f=n(57)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){e.exports={default:n(282),__esModule:!0}},function(e,t,n){"use strict";t.__esModule=!0;var r=a(n(304)),o=a(n(308)),i=a(n(205));function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+(void 0===t?"undefined":(0,i.default)(t)));e.prototype=(0,o.default)(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(r.default?(0,r.default)(e,t):e.__proto__=t)}},function(e,t,n){var r=n(26),o=n(335);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(26),o=n(376);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(173),o=n(132);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){"use strict";var r=n(31);e.exports=function(e,t){return!!e&&r((function(){t?e.call(null,(function(){}),1):e.call(null)}))}},function(e,t,n){"use strict";var r=n(27),o=n(54),i=n(53),a=n(113),l=n(138),c=n(139),u=Math.max,s=Math.min,f=Math.floor,p=/\$([$&`']|\d\d?|<[^>]*>)/g,d=/\$([$&`']|\d\d?)/g;n(140)("replace",2,(function(e,t,n,h){return[function(r,o){var i=e(this),a=null==r?void 0:r[t];return void 0!==a?a.call(r,i,o):n.call(String(i),r,o)},function(e,t){var o=h(n,e,this,t);if(o.done)return o.value;var f=r(e),p=String(this),d="function"==typeof t;d||(t=String(t));var g=f.global;if(g){var m=f.unicode;f.lastIndex=0}for(var y=[];;){var b=c(f,p);if(null===b)break;if(y.push(b),!g)break;""===String(b[0])&&(f.lastIndex=l(p,i(f.lastIndex),m))}for(var _,w="",x=0,S=0;S=x&&(w+=p.slice(x,O)+I,x=O+k.length)}return w+p.slice(x)}];function v(e,t,r,i,a,l){var c=r+e.length,u=i.length,s=d;return void 0!==a&&(a=o(a),s=p),n.call(l,s,(function(n,o){var l;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,r);case"'":return t.slice(c);case"<":l=a[o.slice(1,-1)];break;default:var s=+o;if(0===s)return n;if(s>u){var p=f(s/10);return 0===p?n:p<=u?void 0===i[p-1]?o.charAt(1):i[p-1]+o.charAt(1):n}l=i[s-1]}return void 0===l?"":l}))}}))},function(e,t,n){var r=n(63),o=n(121);e.exports=n(57)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(202),o=n(148);e.exports=function(e){return r(o(e))}},function(e,t,n){(function(e,r){var o; -/** - * @license - * Lodash - * Copyright OpenJS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */(function(){var i="Expected a function",a="__lodash_placeholder__",l=[["ary",128],["bind",1],["bindKey",2],["curry",8],["curryRight",16],["flip",512],["partial",32],["partialRight",64],["rearg",256]],c="[object Arguments]",u="[object Array]",s="[object Boolean]",f="[object Date]",p="[object Error]",d="[object Function]",h="[object GeneratorFunction]",v="[object Map]",g="[object Number]",m="[object Object]",y="[object RegExp]",b="[object Set]",_="[object String]",w="[object Symbol]",x="[object WeakMap]",S="[object ArrayBuffer]",k="[object DataView]",O="[object Float32Array]",E="[object Float64Array]",T="[object Int8Array]",C="[object Int16Array]",P="[object Int32Array]",I="[object Uint8Array]",j="[object Uint16Array]",z="[object Uint32Array]",R=/\b__p \+= '';/g,M=/\b(__p \+=) '' \+/g,N=/(__e\(.*?\)|\b__t\)) \+\n'';/g,A=/&(?:amp|lt|gt|quot|#39);/g,L=/[&<>"']/g,F=RegExp(A.source),D=RegExp(L.source),H=/<%-([\s\S]+?)%>/g,U=/<%([\s\S]+?)%>/g,W=/<%=([\s\S]+?)%>/g,B=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,V=/^\w*$/,G=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,K=/[\\^$.*+?()[\]{}|]/g,q=RegExp(K.source),$=/^\s+|\s+$/g,Q=/^\s+/,Y=/\s+$/,X=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,J=/\{\n\/\* \[wrapped with (.+)\] \*/,Z=/,? & /,ee=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,te=/\\(\\)?/g,ne=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,re=/\w*$/,oe=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,ae=/^\[object .+?Constructor\]$/,le=/^0o[0-7]+$/i,ce=/^(?:0|[1-9]\d*)$/,ue=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,se=/($^)/,fe=/['\n\r\u2028\u2029\\]/g,pe="\\u0300-\\u036f\\ufe20-\\ufe2f\\u20d0-\\u20ff",de="\\xac\\xb1\\xd7\\xf7\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf\\u2000-\\u206f \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",he="[\\ud800-\\udfff]",ve="["+de+"]",ge="["+pe+"]",me="\\d+",ye="[\\u2700-\\u27bf]",be="[a-z\\xdf-\\xf6\\xf8-\\xff]",_e="[^\\ud800-\\udfff"+de+me+"\\u2700-\\u27bfa-z\\xdf-\\xf6\\xf8-\\xffA-Z\\xc0-\\xd6\\xd8-\\xde]",we="\\ud83c[\\udffb-\\udfff]",xe="[^\\ud800-\\udfff]",Se="(?:\\ud83c[\\udde6-\\uddff]){2}",ke="[\\ud800-\\udbff][\\udc00-\\udfff]",Oe="[A-Z\\xc0-\\xd6\\xd8-\\xde]",Ee="(?:"+be+"|"+_e+")",Te="(?:"+Oe+"|"+_e+")",Ce="(?:"+ge+"|"+we+")"+"?",Pe="[\\ufe0e\\ufe0f]?"+Ce+("(?:\\u200d(?:"+[xe,Se,ke].join("|")+")[\\ufe0e\\ufe0f]?"+Ce+")*"),Ie="(?:"+[ye,Se,ke].join("|")+")"+Pe,je="(?:"+[xe+ge+"?",ge,Se,ke,he].join("|")+")",ze=RegExp("['’]","g"),Re=RegExp(ge,"g"),Me=RegExp(we+"(?="+we+")|"+je+Pe,"g"),Ne=RegExp([Oe+"?"+be+"+(?:['’](?:d|ll|m|re|s|t|ve))?(?="+[ve,Oe,"$"].join("|")+")",Te+"+(?:['’](?:D|LL|M|RE|S|T|VE))?(?="+[ve,Oe+Ee,"$"].join("|")+")",Oe+"?"+Ee+"+(?:['’](?:d|ll|m|re|s|t|ve))?",Oe+"+(?:['’](?:D|LL|M|RE|S|T|VE))?","\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])","\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",me,Ie].join("|"),"g"),Ae=RegExp("[\\u200d\\ud800-\\udfff"+pe+"\\ufe0e\\ufe0f]"),Le=/[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Fe=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],De=-1,He={};He[O]=He[E]=He[T]=He[C]=He[P]=He[I]=He["[object Uint8ClampedArray]"]=He[j]=He[z]=!0,He[c]=He[u]=He[S]=He[s]=He[k]=He[f]=He[p]=He[d]=He[v]=He[g]=He[m]=He[y]=He[b]=He[_]=He[x]=!1;var Ue={};Ue[c]=Ue[u]=Ue[S]=Ue[k]=Ue[s]=Ue[f]=Ue[O]=Ue[E]=Ue[T]=Ue[C]=Ue[P]=Ue[v]=Ue[g]=Ue[m]=Ue[y]=Ue[b]=Ue[_]=Ue[w]=Ue[I]=Ue["[object Uint8ClampedArray]"]=Ue[j]=Ue[z]=!0,Ue[p]=Ue[d]=Ue[x]=!1;var We={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Be=parseFloat,Ve=parseInt,Ge="object"==typeof e&&e&&e.Object===Object&&e,Ke="object"==typeof self&&self&&self.Object===Object&&self,qe=Ge||Ke||Function("return this")(),$e=t&&!t.nodeType&&t,Qe=$e&&"object"==typeof r&&r&&!r.nodeType&&r,Ye=Qe&&Qe.exports===$e,Xe=Ye&&Ge.process,Je=function(){try{var e=Qe&&Qe.require&&Qe.require("util").types;return e||Xe&&Xe.binding&&Xe.binding("util")}catch(e){}}(),Ze=Je&&Je.isArrayBuffer,et=Je&&Je.isDate,tt=Je&&Je.isMap,nt=Je&&Je.isRegExp,rt=Je&&Je.isSet,ot=Je&&Je.isTypedArray;function it(e,t,n){switch(n.length){case 0:return e.call(t);case 1:return e.call(t,n[0]);case 2:return e.call(t,n[0],n[1]);case 3:return e.call(t,n[0],n[1],n[2])}return e.apply(t,n)}function at(e,t,n,r){for(var o=-1,i=null==e?0:e.length;++o-1}function pt(e,t,n){for(var r=-1,o=null==e?0:e.length;++r-1;);return n}function Mt(e,t){for(var n=e.length;n--&&wt(t,e[n],0)>-1;);return n}function Nt(e,t){for(var n=e.length,r=0;n--;)e[n]===t&&++r;return r}var At=Et({"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C","Č":"C","ć":"c","ĉ":"c","ċ":"c","č":"c","Ď":"D","Đ":"D","ď":"d","đ":"d","Ē":"E","Ĕ":"E","Ė":"E","Ę":"E","Ě":"E","ē":"e","ĕ":"e","ė":"e","ę":"e","ě":"e","Ĝ":"G","Ğ":"G","Ġ":"G","Ģ":"G","ĝ":"g","ğ":"g","ġ":"g","ģ":"g","Ĥ":"H","Ħ":"H","ĥ":"h","ħ":"h","Ĩ":"I","Ī":"I","Ĭ":"I","Į":"I","İ":"I","ĩ":"i","ī":"i","ĭ":"i","į":"i","ı":"i","Ĵ":"J","ĵ":"j","Ķ":"K","ķ":"k","ĸ":"k","Ĺ":"L","Ļ":"L","Ľ":"L","Ŀ":"L","Ł":"L","ĺ":"l","ļ":"l","ľ":"l","ŀ":"l","ł":"l","Ń":"N","Ņ":"N","Ň":"N","Ŋ":"N","ń":"n","ņ":"n","ň":"n","ŋ":"n","Ō":"O","Ŏ":"O","Ő":"O","ō":"o","ŏ":"o","ő":"o","Ŕ":"R","Ŗ":"R","Ř":"R","ŕ":"r","ŗ":"r","ř":"r","Ś":"S","Ŝ":"S","Ş":"S","Š":"S","ś":"s","ŝ":"s","ş":"s","š":"s","Ţ":"T","Ť":"T","Ŧ":"T","ţ":"t","ť":"t","ŧ":"t","Ũ":"U","Ū":"U","Ŭ":"U","Ů":"U","Ű":"U","Ų":"U","ũ":"u","ū":"u","ŭ":"u","ů":"u","ű":"u","ų":"u","Ŵ":"W","ŵ":"w","Ŷ":"Y","ŷ":"y","Ÿ":"Y","Ź":"Z","Ż":"Z","Ž":"Z","ź":"z","ż":"z","ž":"z","IJ":"IJ","ij":"ij","Œ":"Oe","œ":"oe","ʼn":"'n","ſ":"s"}),Lt=Et({"&":"&","<":"<",">":">",'"':""","'":"'"});function Ft(e){return"\\"+We[e]}function Dt(e){return Ae.test(e)}function Ht(e){var t=-1,n=Array(e.size);return e.forEach((function(e,r){n[++t]=[r,e]})),n}function Ut(e,t){return function(n){return e(t(n))}}function Wt(e,t){for(var n=-1,r=e.length,o=0,i=[];++n",""":'"',"'":"'"});var $t=function e(t){var n,r=(t=null==t?qe:$t.defaults(qe.Object(),t,$t.pick(qe,Fe))).Array,o=t.Date,pe=t.Error,de=t.Function,he=t.Math,ve=t.Object,ge=t.RegExp,me=t.String,ye=t.TypeError,be=r.prototype,_e=de.prototype,we=ve.prototype,xe=t["__core-js_shared__"],Se=_e.toString,ke=we.hasOwnProperty,Oe=0,Ee=(n=/[^.]+$/.exec(xe&&xe.keys&&xe.keys.IE_PROTO||""))?"Symbol(src)_1."+n:"",Te=we.toString,Ce=Se.call(ve),Pe=qe._,Ie=ge("^"+Se.call(ke).replace(K,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$"),je=Ye?t.Buffer:void 0,Me=t.Symbol,Ae=t.Uint8Array,We=je?je.allocUnsafe:void 0,Ge=Ut(ve.getPrototypeOf,ve),Ke=ve.create,$e=we.propertyIsEnumerable,Qe=be.splice,Xe=Me?Me.isConcatSpreadable:void 0,Je=Me?Me.iterator:void 0,yt=Me?Me.toStringTag:void 0,Et=function(){try{var e=ei(ve,"defineProperty");return e({},"",{}),e}catch(e){}}(),Qt=t.clearTimeout!==qe.clearTimeout&&t.clearTimeout,Yt=o&&o.now!==qe.Date.now&&o.now,Xt=t.setTimeout!==qe.setTimeout&&t.setTimeout,Jt=he.ceil,Zt=he.floor,en=ve.getOwnPropertySymbols,tn=je?je.isBuffer:void 0,nn=t.isFinite,rn=be.join,on=Ut(ve.keys,ve),an=he.max,ln=he.min,cn=o.now,un=t.parseInt,sn=he.random,fn=be.reverse,pn=ei(t,"DataView"),dn=ei(t,"Map"),hn=ei(t,"Promise"),vn=ei(t,"Set"),gn=ei(t,"WeakMap"),mn=ei(ve,"create"),yn=gn&&new gn,bn={},_n=Ti(pn),wn=Ti(dn),xn=Ti(hn),Sn=Ti(vn),kn=Ti(gn),On=Me?Me.prototype:void 0,En=On?On.valueOf:void 0,Tn=On?On.toString:void 0;function Cn(e){if(Va(e)&&!Ra(e)&&!(e instanceof zn)){if(e instanceof jn)return e;if(ke.call(e,"__wrapped__"))return Ci(e)}return new jn(e)}var Pn=function(){function e(){}return function(t){if(!Ba(t))return{};if(Ke)return Ke(t);e.prototype=t;var n=new e;return e.prototype=void 0,n}}();function In(){}function jn(e,t){this.__wrapped__=e,this.__actions__=[],this.__chain__=!!t,this.__index__=0,this.__values__=void 0}function zn(e){this.__wrapped__=e,this.__actions__=[],this.__dir__=1,this.__filtered__=!1,this.__iteratees__=[],this.__takeCount__=4294967295,this.__views__=[]}function Rn(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t=t?e:t)),e}function Yn(e,t,n,r,o,i){var a,l=1&t,u=2&t,p=4&t;if(n&&(a=o?n(e,r,o,i):n(e)),void 0!==a)return a;if(!Ba(e))return e;var x=Ra(e);if(x){if(a=function(e){var t=e.length,n=new e.constructor(t);t&&"string"==typeof e[0]&&ke.call(e,"index")&&(n.index=e.index,n.input=e.input);return n}(e),!l)return yo(e,a)}else{var R=ri(e),M=R==d||R==h;if(La(e))return fo(e,l);if(R==m||R==c||M&&!o){if(a=u||M?{}:ii(e),!l)return u?function(e,t){return bo(e,ni(e),t)}(e,function(e,t){return e&&bo(t,wl(t),e)}(a,e)):function(e,t){return bo(e,ti(e),t)}(e,Kn(a,e))}else{if(!Ue[R])return o?e:{};a=function(e,t,n){var r=e.constructor;switch(t){case S:return po(e);case s:case f:return new r(+e);case k:return function(e,t){var n=t?po(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.byteLength)}(e,n);case O:case E:case T:case C:case P:case I:case"[object Uint8ClampedArray]":case j:case z:return ho(e,n);case v:return new r;case g:case _:return new r(e);case y:return function(e){var t=new e.constructor(e.source,re.exec(e));return t.lastIndex=e.lastIndex,t}(e);case b:return new r;case w:return o=e,En?ve(En.call(o)):{}}var o}(e,R,l)}}i||(i=new Ln);var N=i.get(e);if(N)return N;i.set(e,a),Qa(e)?e.forEach((function(r){a.add(Yn(r,t,n,r,e,i))})):Ga(e)&&e.forEach((function(r,o){a.set(o,Yn(r,t,n,o,e,i))}));var A=x?void 0:(p?u?qo:Ko:u?wl:_l)(e);return lt(A||e,(function(r,o){A&&(r=e[o=r]),Bn(a,o,Yn(r,t,n,o,e,i))})),a}function Xn(e,t,n){var r=n.length;if(null==e)return!r;for(e=ve(e);r--;){var o=n[r],i=t[o],a=e[o];if(void 0===a&&!(o in e)||!i(a))return!1}return!0}function Jn(e,t,n){if("function"!=typeof e)throw new ye(i);return _i((function(){e.apply(void 0,n)}),t)}function Zn(e,t,n,r){var o=-1,i=ft,a=!0,l=e.length,c=[],u=t.length;if(!l)return c;n&&(t=dt(t,It(n))),r?(i=pt,a=!1):t.length>=200&&(i=zt,a=!1,t=new An(t));e:for(;++o-1},Mn.prototype.set=function(e,t){var n=this.__data__,r=Vn(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this},Nn.prototype.clear=function(){this.size=0,this.__data__={hash:new Rn,map:new(dn||Mn),string:new Rn}},Nn.prototype.delete=function(e){var t=Jo(this,e).delete(e);return this.size-=t?1:0,t},Nn.prototype.get=function(e){return Jo(this,e).get(e)},Nn.prototype.has=function(e){return Jo(this,e).has(e)},Nn.prototype.set=function(e,t){var n=Jo(this,e),r=n.size;return n.set(e,t),this.size+=n.size==r?0:1,this},An.prototype.add=An.prototype.push=function(e){return this.__data__.set(e,"__lodash_hash_undefined__"),this},An.prototype.has=function(e){return this.__data__.has(e)},Ln.prototype.clear=function(){this.__data__=new Mn,this.size=0},Ln.prototype.delete=function(e){var t=this.__data__,n=t.delete(e);return this.size=t.size,n},Ln.prototype.get=function(e){return this.__data__.get(e)},Ln.prototype.has=function(e){return this.__data__.has(e)},Ln.prototype.set=function(e,t){var n=this.__data__;if(n instanceof Mn){var r=n.__data__;if(!dn||r.length<199)return r.push([e,t]),this.size=++n.size,this;n=this.__data__=new Nn(r)}return n.set(e,t),this.size=n.size,this};var er=xo(cr),tr=xo(ur,!0);function nr(e,t){var n=!0;return er(e,(function(e,r,o){return n=!!t(e,r,o)})),n}function rr(e,t,n){for(var r=-1,o=e.length;++r0&&n(l)?t>1?ir(l,t-1,n,r,o):ht(o,l):r||(o[o.length]=l)}return o}var ar=So(),lr=So(!0);function cr(e,t){return e&&ar(e,t,_l)}function ur(e,t){return e&&lr(e,t,_l)}function sr(e,t){return st(t,(function(t){return Ha(e[t])}))}function fr(e,t){for(var n=0,r=(t=lo(t,e)).length;null!=e&&nt}function vr(e,t){return null!=e&&ke.call(e,t)}function gr(e,t){return null!=e&&t in ve(e)}function mr(e,t,n){for(var o=n?pt:ft,i=e[0].length,a=e.length,l=a,c=r(a),u=1/0,s=[];l--;){var f=e[l];l&&t&&(f=dt(f,It(t))),u=ln(f.length,u),c[l]=!n&&(t||i>=120&&f.length>=120)?new An(l&&f):void 0}f=e[0];var p=-1,d=c[0];e:for(;++p=l)return c;var u=n[r];return c*("desc"==u?-1:1)}}return e.index-t.index}(e,t,n)}))}function Rr(e,t,n){for(var r=-1,o=t.length,i={};++r-1;)l!==e&&Qe.call(l,c,1),Qe.call(e,c,1);return e}function Nr(e,t){for(var n=e?t.length:0,r=n-1;n--;){var o=t[n];if(n==r||o!==i){var i=o;li(o)?Qe.call(e,o,1):Zr(e,o)}}return e}function Ar(e,t){return e+Zt(sn()*(t-e+1))}function Lr(e,t){var n="";if(!e||t<1||t>9007199254740991)return n;do{t%2&&(n+=e),(t=Zt(t/2))&&(e+=e)}while(t);return n}function Fr(e,t){return wi(vi(e,t,Kl),e+"")}function Dr(e){return Dn(Pl(e))}function Hr(e,t){var n=Pl(e);return ki(n,Qn(t,0,n.length))}function Ur(e,t,n,r){if(!Ba(e))return e;for(var o=-1,i=(t=lo(t,e)).length,a=i-1,l=e;null!=l&&++oi?0:i+t),(n=n>i?i:n)<0&&(n+=i),i=t>n?0:n-t>>>0,t>>>=0;for(var a=r(i);++o>>1,a=e[i];null!==a&&!Xa(a)&&(n?a<=t:a=200){var u=t?null:Fo(e);if(u)return Bt(u);a=!1,o=zt,c=new An}else c=t?[]:l;e:for(;++r=r?e:Gr(e,t,n)}var so=Qt||function(e){return qe.clearTimeout(e)};function fo(e,t){if(t)return e.slice();var n=e.length,r=We?We(n):new e.constructor(n);return e.copy(r),r}function po(e){var t=new e.constructor(e.byteLength);return new Ae(t).set(new Ae(e)),t}function ho(e,t){var n=t?po(e.buffer):e.buffer;return new e.constructor(n,e.byteOffset,e.length)}function vo(e,t){if(e!==t){var n=void 0!==e,r=null===e,o=e==e,i=Xa(e),a=void 0!==t,l=null===t,c=t==t,u=Xa(t);if(!l&&!u&&!i&&e>t||i&&a&&c&&!l&&!u||r&&a&&c||!n&&c||!o)return 1;if(!r&&!i&&!u&&e1?n[o-1]:void 0,a=o>2?n[2]:void 0;for(i=e.length>3&&"function"==typeof i?(o--,i):void 0,a&&ci(n[0],n[1],a)&&(i=o<3?void 0:i,o=1),t=ve(t);++r-1?o[i?t[a]:a]:void 0}}function Co(e){return Go((function(t){var n=t.length,r=n,o=jn.prototype.thru;for(e&&t.reverse();r--;){var a=t[r];if("function"!=typeof a)throw new ye(i);if(o&&!l&&"wrapper"==Qo(a))var l=new jn([],!0)}for(r=l?r:n;++r1&&b.reverse(),f&&ul))return!1;var u=i.get(e),s=i.get(t);if(u&&s)return u==t&&s==e;var f=-1,p=!0,d=2&n?new An:void 0;for(i.set(e,t),i.set(t,e);++f-1&&e%1==0&&e1?"& ":"")+t[r],t=t.join(n>2?", ":" "),e.replace(X,"{\n/* [wrapped with "+t+"] */\n")}(r,function(e,t){return lt(l,(function(n){var r="_."+n[0];t&n[1]&&!ft(e,r)&&e.push(r)})),e.sort()}(function(e){var t=e.match(J);return t?t[1].split(Z):[]}(r),n)))}function Si(e){var t=0,n=0;return function(){var r=cn(),o=16-(r-n);if(n=r,o>0){if(++t>=800)return arguments[0]}else t=0;return e.apply(void 0,arguments)}}function ki(e,t){var n=-1,r=e.length,o=r-1;for(t=void 0===t?r:t;++n1?e[t-1]:void 0;return n="function"==typeof n?(e.pop(),n):void 0,$i(e,n)}));function ta(e){var t=Cn(e);return t.__chain__=!0,t}function na(e,t){return t(e)}var ra=Go((function(e){var t=e.length,n=t?e[0]:0,r=this.__wrapped__,o=function(t){return $n(t,e)};return!(t>1||this.__actions__.length)&&r instanceof zn&&li(n)?((r=r.slice(n,+n+(t?1:0))).__actions__.push({func:na,args:[o],thisArg:void 0}),new jn(r,this.__chain__).thru((function(e){return t&&!e.length&&e.push(void 0),e}))):this.thru(o)}));var oa=_o((function(e,t,n){ke.call(e,n)?++e[n]:qn(e,n,1)}));var ia=To(zi),aa=To(Ri);function la(e,t){return(Ra(e)?lt:er)(e,Xo(t,3))}function ca(e,t){return(Ra(e)?ct:tr)(e,Xo(t,3))}var ua=_o((function(e,t,n){ke.call(e,n)?e[n].push(t):qn(e,n,[t])}));var sa=Fr((function(e,t,n){var o=-1,i="function"==typeof t,a=Na(e)?r(e.length):[];return er(e,(function(e){a[++o]=i?it(t,e,n):yr(e,t,n)})),a})),fa=_o((function(e,t,n){qn(e,n,t)}));function pa(e,t){return(Ra(e)?dt:Tr)(e,Xo(t,3))}var da=_o((function(e,t,n){e[n?0:1].push(t)}),(function(){return[[],[]]}));var ha=Fr((function(e,t){if(null==e)return[];var n=t.length;return n>1&&ci(e,t[0],t[1])?t=[]:n>2&&ci(t[0],t[1],t[2])&&(t=[t[0]]),zr(e,ir(t,1),[])})),va=Yt||function(){return qe.Date.now()};function ga(e,t,n){return t=n?void 0:t,Ho(e,128,void 0,void 0,void 0,void 0,t=e&&null==t?e.length:t)}function ma(e,t){var n;if("function"!=typeof t)throw new ye(i);return e=rl(e),function(){return--e>0&&(n=t.apply(this,arguments)),e<=1&&(t=void 0),n}}var ya=Fr((function(e,t,n){var r=1;if(n.length){var o=Wt(n,Yo(ya));r|=32}return Ho(e,r,t,n,o)})),ba=Fr((function(e,t,n){var r=3;if(n.length){var o=Wt(n,Yo(ba));r|=32}return Ho(t,r,e,n,o)}));function _a(e,t,n){var r,o,a,l,c,u,s=0,f=!1,p=!1,d=!0;if("function"!=typeof e)throw new ye(i);function h(t){var n=r,i=o;return r=o=void 0,s=t,l=e.apply(i,n)}function v(e){return s=e,c=_i(m,t),f?h(e):l}function g(e){var n=e-u;return void 0===u||n>=t||n<0||p&&e-s>=a}function m(){var e=va();if(g(e))return y(e);c=_i(m,function(e){var n=t-(e-u);return p?ln(n,a-(e-s)):n}(e))}function y(e){return c=void 0,d&&r?h(e):(r=o=void 0,l)}function b(){var e=va(),n=g(e);if(r=arguments,o=this,u=e,n){if(void 0===c)return v(u);if(p)return so(c),c=_i(m,t),h(u)}return void 0===c&&(c=_i(m,t)),l}return t=il(t)||0,Ba(n)&&(f=!!n.leading,a=(p="maxWait"in n)?an(il(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),b.cancel=function(){void 0!==c&&so(c),s=0,r=u=o=c=void 0},b.flush=function(){return void 0===c?l:y(va())},b}var wa=Fr((function(e,t){return Jn(e,1,t)})),xa=Fr((function(e,t,n){return Jn(e,il(t)||0,n)}));function Sa(e,t){if("function"!=typeof e||null!=t&&"function"!=typeof t)throw new ye(i);var n=function(){var r=arguments,o=t?t.apply(this,r):r[0],i=n.cache;if(i.has(o))return i.get(o);var a=e.apply(this,r);return n.cache=i.set(o,a)||i,a};return n.cache=new(Sa.Cache||Nn),n}function ka(e){if("function"!=typeof e)throw new ye(i);return function(){var t=arguments;switch(t.length){case 0:return!e.call(this);case 1:return!e.call(this,t[0]);case 2:return!e.call(this,t[0],t[1]);case 3:return!e.call(this,t[0],t[1],t[2])}return!e.apply(this,t)}}Sa.Cache=Nn;var Oa=co((function(e,t){var n=(t=1==t.length&&Ra(t[0])?dt(t[0],It(Xo())):dt(ir(t,1),It(Xo()))).length;return Fr((function(r){for(var o=-1,i=ln(r.length,n);++o=t})),za=br(function(){return arguments}())?br:function(e){return Va(e)&&ke.call(e,"callee")&&!$e.call(e,"callee")},Ra=r.isArray,Ma=Ze?It(Ze):function(e){return Va(e)&&dr(e)==S};function Na(e){return null!=e&&Wa(e.length)&&!Ha(e)}function Aa(e){return Va(e)&&Na(e)}var La=tn||ic,Fa=et?It(et):function(e){return Va(e)&&dr(e)==f};function Da(e){if(!Va(e))return!1;var t=dr(e);return t==p||"[object DOMException]"==t||"string"==typeof e.message&&"string"==typeof e.name&&!qa(e)}function Ha(e){if(!Ba(e))return!1;var t=dr(e);return t==d||t==h||"[object AsyncFunction]"==t||"[object Proxy]"==t}function Ua(e){return"number"==typeof e&&e==rl(e)}function Wa(e){return"number"==typeof e&&e>-1&&e%1==0&&e<=9007199254740991}function Ba(e){var t=typeof e;return null!=e&&("object"==t||"function"==t)}function Va(e){return null!=e&&"object"==typeof e}var Ga=tt?It(tt):function(e){return Va(e)&&ri(e)==v};function Ka(e){return"number"==typeof e||Va(e)&&dr(e)==g}function qa(e){if(!Va(e)||dr(e)!=m)return!1;var t=Ge(e);if(null===t)return!0;var n=ke.call(t,"constructor")&&t.constructor;return"function"==typeof n&&n instanceof n&&Se.call(n)==Ce}var $a=nt?It(nt):function(e){return Va(e)&&dr(e)==y};var Qa=rt?It(rt):function(e){return Va(e)&&ri(e)==b};function Ya(e){return"string"==typeof e||!Ra(e)&&Va(e)&&dr(e)==_}function Xa(e){return"symbol"==typeof e||Va(e)&&dr(e)==w}var Ja=ot?It(ot):function(e){return Va(e)&&Wa(e.length)&&!!He[dr(e)]};var Za=No(Er),el=No((function(e,t){return e<=t}));function tl(e){if(!e)return[];if(Na(e))return Ya(e)?Kt(e):yo(e);if(Je&&e[Je])return function(e){for(var t,n=[];!(t=e.next()).done;)n.push(t.value);return n}(e[Je]());var t=ri(e);return(t==v?Ht:t==b?Bt:Pl)(e)}function nl(e){return e?(e=il(e))===1/0||e===-1/0?17976931348623157e292*(e<0?-1:1):e==e?e:0:0===e?e:0}function rl(e){var t=nl(e),n=t%1;return t==t?n?t-n:t:0}function ol(e){return e?Qn(rl(e),0,4294967295):0}function il(e){if("number"==typeof e)return e;if(Xa(e))return NaN;if(Ba(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=Ba(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace($,"");var n=ie.test(e);return n||le.test(e)?Ve(e.slice(2),n?2:8):oe.test(e)?NaN:+e}function al(e){return bo(e,wl(e))}function ll(e){return null==e?"":Xr(e)}var cl=wo((function(e,t){if(pi(t)||Na(t))bo(t,_l(t),e);else for(var n in t)ke.call(t,n)&&Bn(e,n,t[n])})),ul=wo((function(e,t){bo(t,wl(t),e)})),sl=wo((function(e,t,n,r){bo(t,wl(t),e,r)})),fl=wo((function(e,t,n,r){bo(t,_l(t),e,r)})),pl=Go($n);var dl=Fr((function(e,t){e=ve(e);var n=-1,r=t.length,o=r>2?t[2]:void 0;for(o&&ci(t[0],t[1],o)&&(r=1);++n1),t})),bo(e,qo(e),n),r&&(n=Yn(n,7,Bo));for(var o=t.length;o--;)Zr(n,t[o]);return n}));var Ol=Go((function(e,t){return null==e?{}:function(e,t){return Rr(e,t,(function(t,n){return gl(e,n)}))}(e,t)}));function El(e,t){if(null==e)return{};var n=dt(qo(e),(function(e){return[e]}));return t=Xo(t),Rr(e,n,(function(e,n){return t(e,n[0])}))}var Tl=Do(_l),Cl=Do(wl);function Pl(e){return null==e?[]:jt(e,_l(e))}var Il=Oo((function(e,t,n){return t=t.toLowerCase(),e+(n?jl(t):t)}));function jl(e){return Dl(ll(e).toLowerCase())}function zl(e){return(e=ll(e))&&e.replace(ue,At).replace(Re,"")}var Rl=Oo((function(e,t,n){return e+(n?"-":"")+t.toLowerCase()})),Ml=Oo((function(e,t,n){return e+(n?" ":"")+t.toLowerCase()})),Nl=ko("toLowerCase");var Al=Oo((function(e,t,n){return e+(n?"_":"")+t.toLowerCase()}));var Ll=Oo((function(e,t,n){return e+(n?" ":"")+Dl(t)}));var Fl=Oo((function(e,t,n){return e+(n?" ":"")+t.toUpperCase()})),Dl=ko("toUpperCase");function Hl(e,t,n){return e=ll(e),void 0===(t=n?void 0:t)?function(e){return Le.test(e)}(e)?function(e){return e.match(Ne)||[]}(e):function(e){return e.match(ee)||[]}(e):e.match(t)||[]}var Ul=Fr((function(e,t){try{return it(e,void 0,t)}catch(e){return Da(e)?e:new pe(e)}})),Wl=Go((function(e,t){return lt(t,(function(t){t=Ei(t),qn(e,t,ya(e[t],e))})),e}));function Bl(e){return function(){return e}}var Vl=Co(),Gl=Co(!0);function Kl(e){return e}function ql(e){return Sr("function"==typeof e?e:Yn(e,1))}var $l=Fr((function(e,t){return function(n){return yr(n,e,t)}})),Ql=Fr((function(e,t){return function(n){return yr(e,n,t)}}));function Yl(e,t,n){var r=_l(t),o=sr(t,r);null!=n||Ba(t)&&(o.length||!r.length)||(n=t,t=e,e=this,o=sr(t,_l(t)));var i=!(Ba(n)&&"chain"in n&&!n.chain),a=Ha(e);return lt(o,(function(n){var r=t[n];e[n]=r,a&&(e.prototype[n]=function(){var t=this.__chain__;if(i||t){var n=e(this.__wrapped__),o=n.__actions__=yo(this.__actions__);return o.push({func:r,args:arguments,thisArg:e}),n.__chain__=t,n}return r.apply(e,ht([this.value()],arguments))})})),e}function Xl(){}var Jl=zo(dt),Zl=zo(ut),ec=zo(mt);function tc(e){return ui(e)?Ot(Ei(e)):function(e){return function(t){return fr(t,e)}}(e)}var nc=Mo(),rc=Mo(!0);function oc(){return[]}function ic(){return!1}var ac=jo((function(e,t){return e+t}),0),lc=Lo("ceil"),cc=jo((function(e,t){return e/t}),1),uc=Lo("floor");var sc,fc=jo((function(e,t){return e*t}),1),pc=Lo("round"),dc=jo((function(e,t){return e-t}),0);return Cn.after=function(e,t){if("function"!=typeof t)throw new ye(i);return e=rl(e),function(){if(--e<1)return t.apply(this,arguments)}},Cn.ary=ga,Cn.assign=cl,Cn.assignIn=ul,Cn.assignInWith=sl,Cn.assignWith=fl,Cn.at=pl,Cn.before=ma,Cn.bind=ya,Cn.bindAll=Wl,Cn.bindKey=ba,Cn.castArray=function(){if(!arguments.length)return[];var e=arguments[0];return Ra(e)?e:[e]},Cn.chain=ta,Cn.chunk=function(e,t,n){t=(n?ci(e,t,n):void 0===t)?1:an(rl(t),0);var o=null==e?0:e.length;if(!o||t<1)return[];for(var i=0,a=0,l=r(Jt(o/t));io?0:o+n),(r=void 0===r||r>o?o:rl(r))<0&&(r+=o),r=n>r?0:ol(r);n>>0)?(e=ll(e))&&("string"==typeof t||null!=t&&!$a(t))&&!(t=Xr(t))&&Dt(e)?uo(Kt(e),0,n):e.split(t,n):[]},Cn.spread=function(e,t){if("function"!=typeof e)throw new ye(i);return t=null==t?0:an(rl(t),0),Fr((function(n){var r=n[t],o=uo(n,0,t);return r&&ht(o,r),it(e,this,o)}))},Cn.tail=function(e){var t=null==e?0:e.length;return t?Gr(e,1,t):[]},Cn.take=function(e,t,n){return e&&e.length?Gr(e,0,(t=n||void 0===t?1:rl(t))<0?0:t):[]},Cn.takeRight=function(e,t,n){var r=null==e?0:e.length;return r?Gr(e,(t=r-(t=n||void 0===t?1:rl(t)))<0?0:t,r):[]},Cn.takeRightWhile=function(e,t){return e&&e.length?to(e,Xo(t,3),!1,!0):[]},Cn.takeWhile=function(e,t){return e&&e.length?to(e,Xo(t,3)):[]},Cn.tap=function(e,t){return t(e),e},Cn.throttle=function(e,t,n){var r=!0,o=!0;if("function"!=typeof e)throw new ye(i);return Ba(n)&&(r="leading"in n?!!n.leading:r,o="trailing"in n?!!n.trailing:o),_a(e,t,{leading:r,maxWait:t,trailing:o})},Cn.thru=na,Cn.toArray=tl,Cn.toPairs=Tl,Cn.toPairsIn=Cl,Cn.toPath=function(e){return Ra(e)?dt(e,Ei):Xa(e)?[e]:yo(Oi(ll(e)))},Cn.toPlainObject=al,Cn.transform=function(e,t,n){var r=Ra(e),o=r||La(e)||Ja(e);if(t=Xo(t,4),null==n){var i=e&&e.constructor;n=o?r?new i:[]:Ba(e)&&Ha(i)?Pn(Ge(e)):{}}return(o?lt:cr)(e,(function(e,r,o){return t(n,e,r,o)})),n},Cn.unary=function(e){return ga(e,1)},Cn.union=Vi,Cn.unionBy=Gi,Cn.unionWith=Ki,Cn.uniq=function(e){return e&&e.length?Jr(e):[]},Cn.uniqBy=function(e,t){return e&&e.length?Jr(e,Xo(t,2)):[]},Cn.uniqWith=function(e,t){return t="function"==typeof t?t:void 0,e&&e.length?Jr(e,void 0,t):[]},Cn.unset=function(e,t){return null==e||Zr(e,t)},Cn.unzip=qi,Cn.unzipWith=$i,Cn.update=function(e,t,n){return null==e?e:eo(e,t,ao(n))},Cn.updateWith=function(e,t,n,r){return r="function"==typeof r?r:void 0,null==e?e:eo(e,t,ao(n),r)},Cn.values=Pl,Cn.valuesIn=function(e){return null==e?[]:jt(e,wl(e))},Cn.without=Qi,Cn.words=Hl,Cn.wrap=function(e,t){return Ea(ao(t),e)},Cn.xor=Yi,Cn.xorBy=Xi,Cn.xorWith=Ji,Cn.zip=Zi,Cn.zipObject=function(e,t){return oo(e||[],t||[],Bn)},Cn.zipObjectDeep=function(e,t){return oo(e||[],t||[],Ur)},Cn.zipWith=ea,Cn.entries=Tl,Cn.entriesIn=Cl,Cn.extend=ul,Cn.extendWith=sl,Yl(Cn,Cn),Cn.add=ac,Cn.attempt=Ul,Cn.camelCase=Il,Cn.capitalize=jl,Cn.ceil=lc,Cn.clamp=function(e,t,n){return void 0===n&&(n=t,t=void 0),void 0!==n&&(n=(n=il(n))==n?n:0),void 0!==t&&(t=(t=il(t))==t?t:0),Qn(il(e),t,n)},Cn.clone=function(e){return Yn(e,4)},Cn.cloneDeep=function(e){return Yn(e,5)},Cn.cloneDeepWith=function(e,t){return Yn(e,5,t="function"==typeof t?t:void 0)},Cn.cloneWith=function(e,t){return Yn(e,4,t="function"==typeof t?t:void 0)},Cn.conformsTo=function(e,t){return null==t||Xn(e,t,_l(t))},Cn.deburr=zl,Cn.defaultTo=function(e,t){return null==e||e!=e?t:e},Cn.divide=cc,Cn.endsWith=function(e,t,n){e=ll(e),t=Xr(t);var r=e.length,o=n=void 0===n?r:Qn(rl(n),0,r);return(n-=t.length)>=0&&e.slice(n,o)==t},Cn.eq=Pa,Cn.escape=function(e){return(e=ll(e))&&D.test(e)?e.replace(L,Lt):e},Cn.escapeRegExp=function(e){return(e=ll(e))&&q.test(e)?e.replace(K,"\\$&"):e},Cn.every=function(e,t,n){var r=Ra(e)?ut:nr;return n&&ci(e,t,n)&&(t=void 0),r(e,Xo(t,3))},Cn.find=ia,Cn.findIndex=zi,Cn.findKey=function(e,t){return bt(e,Xo(t,3),cr)},Cn.findLast=aa,Cn.findLastIndex=Ri,Cn.findLastKey=function(e,t){return bt(e,Xo(t,3),ur)},Cn.floor=uc,Cn.forEach=la,Cn.forEachRight=ca,Cn.forIn=function(e,t){return null==e?e:ar(e,Xo(t,3),wl)},Cn.forInRight=function(e,t){return null==e?e:lr(e,Xo(t,3),wl)},Cn.forOwn=function(e,t){return e&&cr(e,Xo(t,3))},Cn.forOwnRight=function(e,t){return e&&ur(e,Xo(t,3))},Cn.get=vl,Cn.gt=Ia,Cn.gte=ja,Cn.has=function(e,t){return null!=e&&oi(e,t,vr)},Cn.hasIn=gl,Cn.head=Ni,Cn.identity=Kl,Cn.includes=function(e,t,n,r){e=Na(e)?e:Pl(e),n=n&&!r?rl(n):0;var o=e.length;return n<0&&(n=an(o+n,0)),Ya(e)?n<=o&&e.indexOf(t,n)>-1:!!o&&wt(e,t,n)>-1},Cn.indexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=null==n?0:rl(n);return o<0&&(o=an(r+o,0)),wt(e,t,o)},Cn.inRange=function(e,t,n){return t=nl(t),void 0===n?(n=t,t=0):n=nl(n),function(e,t,n){return e>=ln(t,n)&&e=-9007199254740991&&e<=9007199254740991},Cn.isSet=Qa,Cn.isString=Ya,Cn.isSymbol=Xa,Cn.isTypedArray=Ja,Cn.isUndefined=function(e){return void 0===e},Cn.isWeakMap=function(e){return Va(e)&&ri(e)==x},Cn.isWeakSet=function(e){return Va(e)&&"[object WeakSet]"==dr(e)},Cn.join=function(e,t){return null==e?"":rn.call(e,t)},Cn.kebabCase=Rl,Cn.last=Di,Cn.lastIndexOf=function(e,t,n){var r=null==e?0:e.length;if(!r)return-1;var o=r;return void 0!==n&&(o=(o=rl(n))<0?an(r+o,0):ln(o,r-1)),t==t?function(e,t,n){for(var r=n+1;r--;)if(e[r]===t)return r;return r}(e,t,o):_t(e,St,o,!0)},Cn.lowerCase=Ml,Cn.lowerFirst=Nl,Cn.lt=Za,Cn.lte=el,Cn.max=function(e){return e&&e.length?rr(e,Kl,hr):void 0},Cn.maxBy=function(e,t){return e&&e.length?rr(e,Xo(t,2),hr):void 0},Cn.mean=function(e){return kt(e,Kl)},Cn.meanBy=function(e,t){return kt(e,Xo(t,2))},Cn.min=function(e){return e&&e.length?rr(e,Kl,Er):void 0},Cn.minBy=function(e,t){return e&&e.length?rr(e,Xo(t,2),Er):void 0},Cn.stubArray=oc,Cn.stubFalse=ic,Cn.stubObject=function(){return{}},Cn.stubString=function(){return""},Cn.stubTrue=function(){return!0},Cn.multiply=fc,Cn.nth=function(e,t){return e&&e.length?jr(e,rl(t)):void 0},Cn.noConflict=function(){return qe._===this&&(qe._=Pe),this},Cn.noop=Xl,Cn.now=va,Cn.pad=function(e,t,n){e=ll(e);var r=(t=rl(t))?Gt(e):0;if(!t||r>=t)return e;var o=(t-r)/2;return Ro(Zt(o),n)+e+Ro(Jt(o),n)},Cn.padEnd=function(e,t,n){e=ll(e);var r=(t=rl(t))?Gt(e):0;return t&&rt){var r=e;e=t,t=r}if(n||e%1||t%1){var o=sn();return ln(e+o*(t-e+Be("1e-"+((o+"").length-1))),t)}return Ar(e,t)},Cn.reduce=function(e,t,n){var r=Ra(e)?vt:Tt,o=arguments.length<3;return r(e,Xo(t,4),n,o,er)},Cn.reduceRight=function(e,t,n){var r=Ra(e)?gt:Tt,o=arguments.length<3;return r(e,Xo(t,4),n,o,tr)},Cn.repeat=function(e,t,n){return t=(n?ci(e,t,n):void 0===t)?1:rl(t),Lr(ll(e),t)},Cn.replace=function(){var e=arguments,t=ll(e[0]);return e.length<3?t:t.replace(e[1],e[2])},Cn.result=function(e,t,n){var r=-1,o=(t=lo(t,e)).length;for(o||(o=1,e=void 0);++r9007199254740991)return[];var n=4294967295,r=ln(e,4294967295);e-=4294967295;for(var o=Pt(r,t=Xo(t));++n=i)return e;var l=n-Gt(r);if(l<1)return r;var c=a?uo(a,0,l).join(""):e.slice(0,l);if(void 0===o)return c+r;if(a&&(l+=c.length-l),$a(o)){if(e.slice(l).search(o)){var u,s=c;for(o.global||(o=ge(o.source,ll(re.exec(o))+"g")),o.lastIndex=0;u=o.exec(s);)var f=u.index;c=c.slice(0,void 0===f?l:f)}}else if(e.indexOf(Xr(o),l)!=l){var p=c.lastIndexOf(o);p>-1&&(c=c.slice(0,p))}return c+r},Cn.unescape=function(e){return(e=ll(e))&&F.test(e)?e.replace(A,qt):e},Cn.uniqueId=function(e){var t=++Oe;return ll(e)+t},Cn.upperCase=Fl,Cn.upperFirst=Dl,Cn.each=la,Cn.eachRight=ca,Cn.first=Ni,Yl(Cn,(sc={},cr(Cn,(function(e,t){ke.call(Cn.prototype,t)||(sc[t]=e)})),sc),{chain:!1}),Cn.VERSION="4.17.19",lt(["bind","bindKey","curry","curryRight","partial","partialRight"],(function(e){Cn[e].placeholder=Cn})),lt(["drop","take"],(function(e,t){zn.prototype[e]=function(n){n=void 0===n?1:an(rl(n),0);var r=this.__filtered__&&!t?new zn(this):this.clone();return r.__filtered__?r.__takeCount__=ln(n,r.__takeCount__):r.__views__.push({size:ln(n,4294967295),type:e+(r.__dir__<0?"Right":"")}),r},zn.prototype[e+"Right"]=function(t){return this.reverse()[e](t).reverse()}})),lt(["filter","map","takeWhile"],(function(e,t){var n=t+1,r=1==n||3==n;zn.prototype[e]=function(e){var t=this.clone();return t.__iteratees__.push({iteratee:Xo(e,3),type:n}),t.__filtered__=t.__filtered__||r,t}})),lt(["head","last"],(function(e,t){var n="take"+(t?"Right":"");zn.prototype[e]=function(){return this[n](1).value()[0]}})),lt(["initial","tail"],(function(e,t){var n="drop"+(t?"":"Right");zn.prototype[e]=function(){return this.__filtered__?new zn(this):this[n](1)}})),zn.prototype.compact=function(){return this.filter(Kl)},zn.prototype.find=function(e){return this.filter(e).head()},zn.prototype.findLast=function(e){return this.reverse().find(e)},zn.prototype.invokeMap=Fr((function(e,t){return"function"==typeof e?new zn(this):this.map((function(n){return yr(n,e,t)}))})),zn.prototype.reject=function(e){return this.filter(ka(Xo(e)))},zn.prototype.slice=function(e,t){e=rl(e);var n=this;return n.__filtered__&&(e>0||t<0)?new zn(n):(e<0?n=n.takeRight(-e):e&&(n=n.drop(e)),void 0!==t&&(n=(t=rl(t))<0?n.dropRight(-t):n.take(t-e)),n)},zn.prototype.takeRightWhile=function(e){return this.reverse().takeWhile(e).reverse()},zn.prototype.toArray=function(){return this.take(4294967295)},cr(zn.prototype,(function(e,t){var n=/^(?:filter|find|map|reject)|While$/.test(t),r=/^(?:head|last)$/.test(t),o=Cn[r?"take"+("last"==t?"Right":""):t],i=r||/^find/.test(t);o&&(Cn.prototype[t]=function(){var t=this.__wrapped__,a=r?[1]:arguments,l=t instanceof zn,c=a[0],u=l||Ra(t),s=function(e){var t=o.apply(Cn,ht([e],a));return r&&f?t[0]:t};u&&n&&"function"==typeof c&&1!=c.length&&(l=u=!1);var f=this.__chain__,p=!!this.__actions__.length,d=i&&!f,h=l&&!p;if(!i&&u){t=h?t:new zn(this);var v=e.apply(t,a);return v.__actions__.push({func:na,args:[s],thisArg:void 0}),new jn(v,f)}return d&&h?e.apply(this,a):(v=this.thru(s),d?r?v.value()[0]:v.value():v)})})),lt(["pop","push","shift","sort","splice","unshift"],(function(e){var t=be[e],n=/^(?:push|sort|unshift)$/.test(e)?"tap":"thru",r=/^(?:pop|shift)$/.test(e);Cn.prototype[e]=function(){var e=arguments;if(r&&!this.__chain__){var o=this.value();return t.apply(Ra(o)?o:[],e)}return this[n]((function(n){return t.apply(Ra(n)?n:[],e)}))}})),cr(zn.prototype,(function(e,t){var n=Cn[t];if(n){var r=n.name+"";ke.call(bn,r)||(bn[r]=[]),bn[r].push({name:t,func:n})}})),bn[Po(void 0,2).name]=[{name:"wrapper",func:void 0}],zn.prototype.clone=function(){var e=new zn(this.__wrapped__);return e.__actions__=yo(this.__actions__),e.__dir__=this.__dir__,e.__filtered__=this.__filtered__,e.__iteratees__=yo(this.__iteratees__),e.__takeCount__=this.__takeCount__,e.__views__=yo(this.__views__),e},zn.prototype.reverse=function(){if(this.__filtered__){var e=new zn(this);e.__dir__=-1,e.__filtered__=!0}else(e=this.clone()).__dir__*=-1;return e},zn.prototype.value=function(){var e=this.__wrapped__.value(),t=this.__dir__,n=Ra(e),r=t<0,o=n?e.length:0,i=function(e,t,n){var r=-1,o=n.length;for(;++r=this.__values__.length;return{done:e,value:e?void 0:this.__values__[this.__index__++]}},Cn.prototype.plant=function(e){for(var t,n=this;n instanceof In;){var r=Ci(n);r.__index__=0,r.__values__=void 0,t?o.__wrapped__=r:t=r;var o=r;n=n.__wrapped__}return o.__wrapped__=e,t},Cn.prototype.reverse=function(){var e=this.__wrapped__;if(e instanceof zn){var t=e;return this.__actions__.length&&(t=new zn(this)),(t=t.reverse()).__actions__.push({func:na,args:[Bi],thisArg:void 0}),new jn(t,this.__chain__)}return this.thru(Bi)},Cn.prototype.toJSON=Cn.prototype.valueOf=Cn.prototype.value=function(){return no(this.__wrapped__,this.__actions__)},Cn.prototype.first=Cn.prototype.head,Je&&(Cn.prototype[Je]=function(){return this}),Cn}();qe._=$t,void 0===(o=function(){return $t}.call(t,n,t,r))||(r.exports=o)}).call(this)}).call(this,n(108),n(243)(e))},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(108))},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperties:n(172)})},function(e,t){var n=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=n)},function(e,t,n){var r=n(81);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var r=n(10),o=n(249),i=n(60),a=n(94),l=n(174);r(r.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n,r=i(e),c=a.f,u=o(r),s={},f=0;u.length>f;)void 0!==(n=c(r,t=u[f++]))&&l(s,t,n);return s}})},function(e,t,n){var r=n(27),o=n(172),i=n(132),a=n(131)("IE_PROTO"),l=function(){},c=function(){var e,t=n(171)("iframe"),r=i.length;for(t.style.display="none",n(251).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write(" - - - -
-
-
-
-
-
- -
-

bind

-
-
open suspend fun <B> Cont<R, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

fun <E, A> Either<E, A>.toCont(): Cont<E, A> = cont {
fold({ e -> shift(e) }, ::identity)
}

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.toCont().bind()
x
}.toEither() shouldBe either
}

open suspend fun <B> Either<R, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.either(Arb.string(), Arb.int())) { either ->
cont<String, Int> {
val x: Int = either.bind()
x
}.toEither() shouldBe either
}

open suspend fun <B> Validated<R, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun test() = checkAll(Arb.validated(Arb.string(), Arb.int())) { validated ->
cont<String, Int> {
val x: Int = validated.bind()
x
}.toValidated() shouldBe validated
}

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.result(Arb.int())) { result ->
cont<String, Int> {
val x: Int = result.bind { _: Throwable -> default }
x
}.fold({ default }, ::identity) shouldBe result.getOrElse { default }
}

open suspend fun <B> Option<B>.bind(shift: () -> R): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

private val default = "failed"
suspend fun test() = checkAll(Arb.option(Arb.int())) { option ->
cont<String, Int> {
val x: Int = option.bind { default }
x
}.fold({ default }, ::identity) shouldBe option.getOrElse { default }
}
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont-effect/ensure.html b/docs/-cont/arrow/-cont-effect/ensure.html deleted file mode 100644 index 8cc051235e6..00000000000 --- a/docs/-cont/arrow/-cont-effect/ensure.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - ensure - - - - -
-
-
-
-
-
- -
-

ensure

-
-
open suspend fun ensure(condition: Boolean, shift: () -> R)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

suspend fun test() = checkAll(Arb.boolean(), Arb.string(), Arb.int()) { condition, failure, int ->
cont<String, Int> {
ensure(condition) { failure }
int
}.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure)
}
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont-effect/index.html b/docs/-cont/arrow/-cont-effect/index.html deleted file mode 100644 index 40157c7dd24..00000000000 --- a/docs/-cont/arrow/-cont-effect/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - - - ContEffect - - - - -
-
-
-
-
-
- -
-

ContEffect

-
interface ContEffect<R>

Context of the Cont DSL.

-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
-
open suspend fun <B> Cont<R, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<R, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<R, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

open suspend fun <B> Option<B>.bind(shift: () -> R): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
-
open suspend fun ensure(condition: Boolean, shift: () -> R)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
-
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Inheritors

-
-
-
-
IorEffect -
Link copied to clipboard
-
-
-
-
- -
-
-
OptionEffect -
Link copied to clipboard
-
-
-
-
-
-

Extensions

-
-
-
-
ensureNotNull -
Link copied to clipboard
-
-
-
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont-effect/shift.html b/docs/-cont/arrow/-cont-effect/shift.html deleted file mode 100644 index ab61f939e48..00000000000 --- a/docs/-cont/arrow/-cont-effect/shift.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - shift - - - - -
-
-
-
-
-
- -
-

shift

-
-
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/attempt.html b/docs/-cont/arrow/-cont/attempt.html deleted file mode 100644 index 836c2a03eb1..00000000000 --- a/docs/-cont/arrow/-cont/attempt.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - attempt - - - - -
-
-
-
-
-
- -
-

attempt

-
-
open fun attempt(): Cont<R, Result<A>>

Runs the Cont and captures any NonFatal exception into Result.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/flat-map.html b/docs/-cont/arrow/-cont/flat-map.html deleted file mode 100644 index 8d77d603941..00000000000 --- a/docs/-cont/arrow/-cont/flat-map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - flatMap - - -
-
- - -
-
-
-
-
-
- -
-

flatMap

-
-
- -
-
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
-
-

Maps the values A with the transform function into another Cont effect.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/fold.html b/docs/-cont/arrow/-cont/fold.html deleted file mode 100644 index f1e7bed760e..00000000000 --- a/docs/-cont/arrow/-cont/fold.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - fold - - - - -
-
-
-
-
-
- -
-

fold

-
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

suspend fun test() {
val shift = cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
shift shouldBe "Hello, World!"

val res = cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
res shouldBe 1000
}

open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/handle-error-with.html b/docs/-cont/arrow/-cont/handle-error-with.html deleted file mode 100644 index a09454cf586..00000000000 --- a/docs/-cont/arrow/-cont/handle-error-with.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - handleErrorWith - - - - -
-
-
-
-
-
- -
-

handleErrorWith

-
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/handle-error.html b/docs/-cont/arrow/-cont/handle-error.html deleted file mode 100644 index 80e192e78da..00000000000 --- a/docs/-cont/arrow/-cont/handle-error.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - handleError - - - - -
-
-
-
-
-
- -
-

handleError

-
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/index.html b/docs/-cont/arrow/-cont/index.html deleted file mode 100644 index 2c75271a995..00000000000 --- a/docs/-cont/arrow/-cont/index.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - Cont - - - - -
-
-
-
-
-
- -
-

Cont

-
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

-
-
-
-
-

Functions

-
-
-
-
attempt -
Link copied to clipboard
-
-
-
-
open fun attempt(): Cont<R, Result<A>>

Runs the Cont and captures any NonFatal exception into Result.

-
-
-
-
- -
-
-
fold -
Link copied to clipboard
-
-
-
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B

Like fold but also allows folding over any unexpected Throwable that might have occurred.

-
-
-
-
- -
-
-
handleError -
Link copied to clipboard
-
-
-
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-
-
-
-
- -
-
-
handleErrorWith -
Link copied to clipboard
-
-
-
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
-
-
- -
-
-
redeem -
Link copied to clipboard
-
-
-
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-
-
-
-
- -
-
-
redeemWith -
Link copied to clipboard
-
-
-
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-
-
-
-
- -
-
-
toEither -
Link copied to clipboard
-
-
-
-
open suspend fun toEither(): Either<R, A>

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

-
-
-
-
- -
-
-
toIor -
Link copied to clipboard
-
-
-
-
open suspend fun toIor(): Ior<R, A>

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

-
-
-
-
- -
-
-
toOption -
Link copied to clipboard
-
-
-
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

-
-
-
-
- -
-
-
toValidated -
Link copied to clipboard
-
-
-
-
open suspend fun toValidated(): Validated<R, A>

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

-
-
-
-
-
-

Extensions

-
-
-
-
toOption -
Link copied to clipboard
-
-
-
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/map.html b/docs/-cont/arrow/-cont/map.html deleted file mode 100644 index d126007c562..00000000000 --- a/docs/-cont/arrow/-cont/map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - map - - -
-
- - -
-
-
-
-
-
- -
-

map

-
-
- -
-
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
-
-

Maps the values A with the transform function into B.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/redeem-with.html b/docs/-cont/arrow/-cont/redeem-with.html deleted file mode 100644 index 33a99766962..00000000000 --- a/docs/-cont/arrow/-cont/redeem-with.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - redeemWith - - - - -
-
-
-
-
-
- -
-

redeemWith

-
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/redeem.html b/docs/-cont/arrow/-cont/redeem.html deleted file mode 100644 index d4740f44c05..00000000000 --- a/docs/-cont/arrow/-cont/redeem.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - redeem - - - - -
-
-
-
-
-
- -
-

redeem

-
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/to-either.html b/docs/-cont/arrow/-cont/to-either.html deleted file mode 100644 index 6f7550deb4e..00000000000 --- a/docs/-cont/arrow/-cont/to-either.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toEither - - - - -
-
-
-
-
-
- -
-

toEither

-
-
open suspend fun toEither(): Either<R, A>

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/to-ior.html b/docs/-cont/arrow/-cont/to-ior.html deleted file mode 100644 index 4fe3617bd0a..00000000000 --- a/docs/-cont/arrow/-cont/to-ior.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toIor - - - - -
-
-
-
-
-
- -
-

toIor

-
-
open suspend fun toIor(): Ior<R, A>

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/to-option.html b/docs/-cont/arrow/-cont/to-option.html deleted file mode 100644 index 1749c8c9211..00000000000 --- a/docs/-cont/arrow/-cont/to-option.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toOption - - - - -
-
-
-
-
-
- -
-

toOption

-
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-cont/to-validated.html b/docs/-cont/arrow/-cont/to-validated.html deleted file mode 100644 index e6d525d9f00..00000000000 --- a/docs/-cont/arrow/-cont/to-validated.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toValidated - - - - -
-
-
-
-
-
- -
-

toValidated

-
-
open suspend fun toValidated(): Validated<R, A>

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-ior-effect/-ior-effect.html b/docs/-cont/arrow/-ior-effect/-ior-effect.html deleted file mode 100644 index d1ed43e5bbb..00000000000 --- a/docs/-cont/arrow/-ior-effect/-ior-effect.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - IorEffect - - - - -
-
-
-
-
-
- -
-

IorEffect

-
-
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-ior-effect/bind.html b/docs/-cont/arrow/-ior-effect/bind.html deleted file mode 100644 index f9ae75ed1ce..00000000000 --- a/docs/-cont/arrow/-ior-effect/bind.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - bind - - - - -
-
-
-
-
-
- -
-

bind

-
-
suspend fun <B> Ior<E, B>.bind(): B
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-ior-effect/index.html b/docs/-cont/arrow/-ior-effect/index.html deleted file mode 100644 index f25f7af137b..00000000000 --- a/docs/-cont/arrow/-ior-effect/index.html +++ /dev/null @@ -1,133 +0,0 @@ - - - - IorEffect - - - - -
-
-
-
-
-
- -
-

IorEffect

-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
-
open suspend fun <B> Cont<E, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<E, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<E, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun <B> Ior<E, B>.bind(): B

open suspend fun <B> Option<B>.bind(shift: () -> E): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
-
-
-
- -
-
-
combine -
Link copied to clipboard
-
-
-
-
open override fun E.combine(b: E): E
-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
-
open suspend fun ensure(condition: Boolean, shift: () -> E)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
-
-
-
- -
-
-
maybeCombine -
Link copied to clipboard
-
-
-
-
open override fun E.maybeCombine(b: E?): E
-
-
-
-
- -
-
-
plus -
Link copied to clipboard
-
-
-
-
open operator override fun E.plus(b: E): E
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
-
open suspend override fun <B> shift(r: E): B

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-ior-effect/shift.html b/docs/-cont/arrow/-ior-effect/shift.html deleted file mode 100644 index 69f2074be1a..00000000000 --- a/docs/-cont/arrow/-ior-effect/shift.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - shift - - - - -
-
-
-
-
-
- -
-

shift

-
-
open suspend override fun <B> shift(r: E): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-option-effect/-option-effect.html b/docs/-cont/arrow/-option-effect/-option-effect.html deleted file mode 100644 index f99b1905856..00000000000 --- a/docs/-cont/arrow/-option-effect/-option-effect.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - OptionEffect - - - - -
-
-
-
-
-
- -
-

OptionEffect

-
-
fun OptionEffect(cont: ContEffect<None>)
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-option-effect/bind.html b/docs/-cont/arrow/-option-effect/bind.html deleted file mode 100644 index af262029008..00000000000 --- a/docs/-cont/arrow/-option-effect/bind.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - bind - - - - -
-
-
-
-
-
- -
-

bind

-
-
suspend fun <B> Option<B>.bind(): B
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-option-effect/ensure.html b/docs/-cont/arrow/-option-effect/ensure.html deleted file mode 100644 index 13e9a9cab0e..00000000000 --- a/docs/-cont/arrow/-option-effect/ensure.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - ensure - - - - -
-
-
-
-
-
- -
-

ensure

-
-
suspend fun ensure(value: Boolean)
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-option-effect/index.html b/docs/-cont/arrow/-option-effect/index.html deleted file mode 100644 index bd40d2cc073..00000000000 --- a/docs/-cont/arrow/-option-effect/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - - OptionEffect - - - - -
-
-
-
-
-
- -
-

OptionEffect

-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
-
open suspend fun <B> Cont<None, B>.bind(): B

Runs the Cont to finish, returning B or shift in case of R.

open suspend fun <B> Either<None, B>.bind(): B

Folds Either into Cont, by returning B or a shift with R.

open suspend fun <B> Validated<None, B>.bind(): B

Folds Validated into Cont, by returning B or a shift with R.

suspend fun <B> Option<B>.bind(): B

open suspend fun <B> Option<B>.bind(shift: () -> None): B

Folds Option into Cont, by returning B or a transforming None into R and shifting the result.

open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B

Folds Result into Cont, by returning B or a transforming Throwable into R and shifting the result.

-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
-
suspend fun ensure(value: Boolean)

open suspend fun ensure(condition: Boolean, shift: () -> None)

ensure that condition is true, if it's false it will shift with the provided value R. Monadic version of kotlin.require.

-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
-
open suspend override fun <B> shift(r: None): B

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-option-effect/shift.html b/docs/-cont/arrow/-option-effect/shift.html deleted file mode 100644 index 2f13b2d77ff..00000000000 --- a/docs/-cont/arrow/-option-effect/shift.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - shift - - - - -
-
-
-
-
-
- -
-

shift

-
-
open suspend override fun <B> shift(r: None): B

Short-circuit the Cont computation with value R.

suspend fun test() = checkAll(Arb.string()) { str ->
cont<String, Int> {
shift(str)
}.fold({ it shouldBe str }, { fail("Computation never finishes") })
}
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont-effect/bind.html b/docs/-cont/arrow/-restricted-cont-effect/bind.html deleted file mode 100644 index 1c73843bd1b..00000000000 --- a/docs/-cont/arrow/-restricted-cont-effect/bind.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - bind - - - - -
-
-
-
-
-
- -
-

bind

-
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont-effect/index.html b/docs/-cont/arrow/-restricted-cont-effect/index.html deleted file mode 100644 index 7366174ec46..00000000000 --- a/docs/-cont/arrow/-restricted-cont-effect/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - RestrictedContEffect - - - - -
-
-
-
-
-
- -
-

RestrictedContEffect

-
interface RestrictedContEffect<R>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
-
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont-effect/shift.html b/docs/-cont/arrow/-restricted-cont-effect/shift.html deleted file mode 100644 index 516dbfd7a98..00000000000 --- a/docs/-cont/arrow/-restricted-cont-effect/shift.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - shift - - - - -
-
-
-
-
-
- -
-

shift

-
-
abstract suspend fun <B> shift(r: R): B

Short-circuit the Cont computation with value R.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/attempt.html b/docs/-cont/arrow/-restricted-cont/attempt.html deleted file mode 100644 index fe4546e9be3..00000000000 --- a/docs/-cont/arrow/-restricted-cont/attempt.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - attempt - - - - -
-
-
-
-
-
- -
-

attempt

-
-
open fun attempt(): RestrictedCont<R, Result<A>>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/flat-map.html b/docs/-cont/arrow/-restricted-cont/flat-map.html deleted file mode 100644 index 00c8b776b48..00000000000 --- a/docs/-cont/arrow/-restricted-cont/flat-map.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - flatMap - - - - -
-
-
-
-
-
- -
-

flatMap

-
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/fold.html b/docs/-cont/arrow/-restricted-cont/fold.html deleted file mode 100644 index 2015485d10c..00000000000 --- a/docs/-cont/arrow/-restricted-cont/fold.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - fold - - - - -
-
-
-
-
-
- -
-

fold

-
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/handle-error-with.html b/docs/-cont/arrow/-restricted-cont/handle-error-with.html deleted file mode 100644 index 9cbda0eac6c..00000000000 --- a/docs/-cont/arrow/-restricted-cont/handle-error-with.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - handleErrorWith - - - - -
-
-
-
-
-
- -
-

handleErrorWith

-
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/handle-error.html b/docs/-cont/arrow/-restricted-cont/handle-error.html deleted file mode 100644 index 3eff0690c42..00000000000 --- a/docs/-cont/arrow/-restricted-cont/handle-error.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - handleError - - - - -
-
-
-
-
-
- -
-

handleError

-
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/index.html b/docs/-cont/arrow/-restricted-cont/index.html deleted file mode 100644 index e9d47391522..00000000000 --- a/docs/-cont/arrow/-restricted-cont/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - RestrictedCont - - - - -
-
-
-
-
-
- -
-

RestrictedCont

-
interface RestrictedCont<R, A>
-
-
-
-
-

Functions

-
-
-
-
attempt -
Link copied to clipboard
-
-
-
-
open fun attempt(): RestrictedCont<R, Result<A>>
-
-
-
-
- -
-
-
flatMap -
Link copied to clipboard
-
-
-
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-
-
-
-
- -
-
-
fold -
Link copied to clipboard
-
-
-
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-
-
-
-
- -
-
-
handleError -
Link copied to clipboard
-
-
-
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-
-
-
-
- -
-
-
handleErrorWith -
Link copied to clipboard
-
-
-
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-
-
-
-
- -
-
-
map -
Link copied to clipboard
-
-
-
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-
-
-
-
- -
-
-
redeem -
Link copied to clipboard
-
-
-
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-
-
-
-
- -
-
-
redeemWith -
Link copied to clipboard
-
-
-
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-
-
-
-
- -
-
-
toEither -
Link copied to clipboard
-
-
-
-
open fun toEither(): Either<R, A>
-
-
-
-
- -
-
-
toValidated -
Link copied to clipboard
-
-
-
-
open fun toValidated(): Validated<R, A>
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/map.html b/docs/-cont/arrow/-restricted-cont/map.html deleted file mode 100644 index 9b9a7fa6f66..00000000000 --- a/docs/-cont/arrow/-restricted-cont/map.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - map - - - - -
-
-
-
-
-
- -
-

map

-
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/redeem-with.html b/docs/-cont/arrow/-restricted-cont/redeem-with.html deleted file mode 100644 index 6f7b1169f3c..00000000000 --- a/docs/-cont/arrow/-restricted-cont/redeem-with.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - redeemWith - - - - -
-
-
-
-
-
- -
-

redeemWith

-
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/redeem.html b/docs/-cont/arrow/-restricted-cont/redeem.html deleted file mode 100644 index 888fed6443c..00000000000 --- a/docs/-cont/arrow/-restricted-cont/redeem.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - redeem - - - - -
-
-
-
-
-
- -
-

redeem

-
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/to-either.html b/docs/-cont/arrow/-restricted-cont/to-either.html deleted file mode 100644 index dbae1c1cd2b..00000000000 --- a/docs/-cont/arrow/-restricted-cont/to-either.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toEither - - - - -
-
-
-
-
-
- -
-

toEither

-
-
open fun toEither(): Either<R, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-restricted-cont/to-validated.html b/docs/-cont/arrow/-restricted-cont/to-validated.html deleted file mode 100644 index 9aabc76a104..00000000000 --- a/docs/-cont/arrow/-restricted-cont/to-validated.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toValidated - - - - -
-
-
-
-
-
- -
-

toValidated

-
-
open fun toValidated(): Validated<R, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/-shift-cancellation-exception/index.html b/docs/-cont/arrow/-shift-cancellation-exception/index.html deleted file mode 100644 index b7411120e1d..00000000000 --- a/docs/-cont/arrow/-shift-cancellation-exception/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - ShiftCancellationException - - - - -
-
-
-
-
-
- -
-

ShiftCancellationException

-
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

-
-
-
-
-

Properties

-
-
-
-
cause -
Link copied to clipboard
-
-
-
-
open val cause: Throwable?
-
-
-
-
- -
-
-
message -
Link copied to clipboard
-
-
-
-
open val message: String?
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/cont.html b/docs/-cont/arrow/cont.html deleted file mode 100644 index 6c4c5d4dc30..00000000000 --- a/docs/-cont/arrow/cont.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - cont - - - - -
-
-
-
-
-
- -
-

cont

-
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>

DSL for constructing Cont values

suspend fun test() {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold({ fail("Shift can never be the result") }, { it shouldBe 6 })

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold({ it shouldBe "Option was empty" }, { fail("Int can never be the result") })
}
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/either.html b/docs/-cont/arrow/either.html deleted file mode 100644 index eee8781c3a7..00000000000 --- a/docs/-cont/arrow/either.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - either - - - - -
-
-
-
-
-
- -
-

either

-
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/ensure-not-null.html b/docs/-cont/arrow/ensure-not-null.html deleted file mode 100644 index e6bd185131d..00000000000 --- a/docs/-cont/arrow/ensure-not-null.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - ensureNotNull - - - - -
-
-
-
-
-
- -
-

ensureNotNull

-
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

suspend fun test() = checkAll(Arb.string(), Arb.int().orNull()) { failure, int: Int? ->
cont<String, Int> {
ensureNotNull(int) { failure }
}.toEither() shouldBe (int?.right() ?: failure.left())
}

suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
- -
-
- - - diff --git a/docs/-cont/arrow/index.html b/docs/-cont/arrow/index.html deleted file mode 100644 index 0090f859005..00000000000 --- a/docs/-cont/arrow/index.html +++ /dev/null @@ -1,227 +0,0 @@ - - - - arrow - - - - -
-
-
-
-
-
- -
-

Package arrow

-
-
-
-
-

Types

-
-
-
-
Cont -
Link copied to clipboard
-
-
-
-
interface Cont<R, A>

Cont represents a suspending computation that runs will either

-
-
-
-
- -
-
-
ContEffect -
Link copied to clipboard
-
-
-
-
interface ContEffect<R>

Context of the Cont DSL.

-
-
-
-
- -
-
-
IorEffect -
Link copied to clipboard
-
-
-
-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
-
-
-
-
- -
-
-
OptionEffect -
Link copied to clipboard
-
-
-
-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
-
-
-
-
- -
-
-
RestrictedCont -
Link copied to clipboard
-
-
-
-
interface RestrictedCont<R, A>
-
-
-
-
- -
-
-
RestrictedContEffect -
Link copied to clipboard
-
-
-
-
interface RestrictedContEffect<R>
-
-
-
-
- -
-
-
ShiftCancellationException -
Link copied to clipboard
-
-
-
-
sealed class ShiftCancellationException : CancellationException

AVOID USING THIS TYPE, it's meant for low-level cancellation code When in need in low-level code, you can use this type to differentiate between a foreign CancellationException and the one from Cont.

-
-
-
-
-
-

Functions

-
-
-
-
cont -
Link copied to clipboard
-
-
-
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>

DSL for constructing Cont values

-
-
-
-
- -
-
-
either -
Link copied to clipboard
-
-
-
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-
-
-
-
- -
-
-
ensureNotNull -
Link copied to clipboard
-
-
-
-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B

suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B

Ensure that value is not null. if it's non-null it will be smart-casted and returned if it's false it will shift with the provided value R. Monadic version of kotlin.requireNotNull.

-
-
-
-
- -
-
-
ior -
Link copied to clipboard
-
-
-
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-
-
-
-
- -
-
-
option -
Link copied to clipboard
-
-
-
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-
-
-
-
- -
-
-
restrictedCont -
Link copied to clipboard
-
-
-
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-
-
-
-
- -
-
-
toOption -
Link copied to clipboard
-
-
-
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/ior.html b/docs/-cont/arrow/ior.html deleted file mode 100644 index 52c6dfa1aa4..00000000000 --- a/docs/-cont/arrow/ior.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - ior - - - - -
-
-
-
-
-
- -
-

ior

-
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/option.html b/docs/-cont/arrow/option.html deleted file mode 100644 index 36038d05722..00000000000 --- a/docs/-cont/arrow/option.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - option - - - - -
-
-
-
-
-
- -
-

option

-
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/restricted-cont.html b/docs/-cont/arrow/restricted-cont.html deleted file mode 100644 index 5620af09c07..00000000000 --- a/docs/-cont/arrow/restricted-cont.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - restrictedCont - - - - -
-
-
-
-
-
- -
-

restrictedCont

-
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/sequence.html b/docs/-cont/arrow/sequence.html deleted file mode 100644 index af6f9147118..00000000000 --- a/docs/-cont/arrow/sequence.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - sequence - - -
-
- - -
-
-
-
-
-
- -
-

sequence

-
-
- -
-
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/to-option.html b/docs/-cont/arrow/to-option.html deleted file mode 100644 index 6dc2936f0d2..00000000000 --- a/docs/-cont/arrow/to-option.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - toOption - - - - -
-
-
-
-
-
- -
-

toOption

-
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/arrow/traverse-cont.html b/docs/-cont/arrow/traverse-cont.html deleted file mode 100644 index f4b34f139a3..00000000000 --- a/docs/-cont/arrow/traverse-cont.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - traverseCont - - -
-
- - -
-
-
-
-
-
- -
-

traverseCont

-
-
- -
-
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-cont/package-list b/docs/-cont/package-list deleted file mode 100644 index dc9e4116bcc..00000000000 --- a/docs/-cont/package-list +++ /dev/null @@ -1,57 +0,0 @@ -$dokka.format:html-v1 -$dokka.linkExtension:html -$dokka.location:arrow////PointingToDeclaration/-cont/arrow/index.html -$dokka.location:arrow//cont/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/cont.html -$dokka.location:arrow//either/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/either.html -$dokka.location:arrow//ensureNotNull/arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]#TypeParam(bounds=[kotlin.Any])?#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/ensure-not-null.html -$dokka.location:arrow//ensureNotNull/arrow.ContEffect[arrow.core.None]#TypeParam(bounds=[kotlin.Any])?/PointingToDeclaration/-cont/arrow/ensure-not-null.html -$dokka.location:arrow//ior/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[arrow.IorEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/ior.html -$dokka.location:arrow//option/#kotlin.Function1[arrow.OptionEffect,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/option.html -$dokka.location:arrow//restrictedCont/#kotlin.coroutines.SuspendFunction1[arrow.RestrictedContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/restricted-cont.html -$dokka.location:arrow//toOption/arrow.Cont[arrow.core.None,TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/to-option.html -$dokka.location:arrow/Cont///PointingToDeclaration/-cont/arrow/-cont/index.html -$dokka.location:arrow/Cont/attempt/#/PointingToDeclaration/-cont/arrow/-cont/attempt.html -$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html -$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/fold.html -$dokka.location:arrow/Cont/handleError/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/handle-error.html -$dokka.location:arrow/Cont/handleErrorWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/handle-error-with.html -$dokka.location:arrow/Cont/redeem/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont/redeem.html -$dokka.location:arrow/Cont/redeemWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/redeem-with.html -$dokka.location:arrow/Cont/toEither/#/PointingToDeclaration/-cont/arrow/-cont/to-either.html -$dokka.location:arrow/Cont/toIor/#/PointingToDeclaration/-cont/arrow/-cont/to-ior.html -$dokka.location:arrow/Cont/toOption/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-cont/to-option.html -$dokka.location:arrow/Cont/toValidated/#/PointingToDeclaration/-cont/arrow/-cont/to-validated.html -$dokka.location:arrow/ContEffect///PointingToDeclaration/-cont/arrow/-cont-effect/index.html -$dokka.location:arrow/ContEffect/bind/arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Either[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Validated[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/kotlin.Result[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/ensure/#kotlin.Boolean#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-cont-effect/ensure.html -$dokka.location:arrow/ContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-cont-effect/shift.html -$dokka.location:arrow/IorEffect///PointingToDeclaration/-cont/arrow/-ior-effect/index.html -$dokka.location:arrow/IorEffect/IorEffect/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-ior-effect/-ior-effect.html -$dokka.location:arrow/IorEffect/bind/arrow.core.Ior[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-ior-effect/bind.html -$dokka.location:arrow/IorEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-ior-effect/shift.html -$dokka.location:arrow/OptionEffect///PointingToDeclaration/-cont/arrow/-option-effect/index.html -$dokka.location:arrow/OptionEffect/OptionEffect/#arrow.ContEffect[arrow.core.None]/PointingToDeclaration/-cont/arrow/-option-effect/-option-effect.html -$dokka.location:arrow/OptionEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-option-effect/bind.html -$dokka.location:arrow/OptionEffect/ensure/#kotlin.Boolean/PointingToDeclaration/-cont/arrow/-option-effect/ensure.html -$dokka.location:arrow/OptionEffect/shift/#arrow.core.None/PointingToDeclaration/-cont/arrow/-option-effect/shift.html -$dokka.location:arrow/RestrictedCont///PointingToDeclaration/-cont/arrow/-restricted-cont/index.html -$dokka.location:arrow/RestrictedCont/attempt/#/PointingToDeclaration/-cont/arrow/-restricted-cont/attempt.html -$dokka.location:arrow/RestrictedCont/flatMap/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/flat-map.html -$dokka.location:arrow/RestrictedCont/fold/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/fold.html -$dokka.location:arrow/RestrictedCont/handleError/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/handle-error.html -$dokka.location:arrow/RestrictedCont/handleErrorWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/handle-error-with.html -$dokka.location:arrow/RestrictedCont/map/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/map.html -$dokka.location:arrow/RestrictedCont/redeem/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-cont/arrow/-restricted-cont/redeem.html -$dokka.location:arrow/RestrictedCont/redeemWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-cont/arrow/-restricted-cont/redeem-with.html -$dokka.location:arrow/RestrictedCont/toEither/#/PointingToDeclaration/-cont/arrow/-restricted-cont/to-either.html -$dokka.location:arrow/RestrictedCont/toValidated/#/PointingToDeclaration/-cont/arrow/-restricted-cont/to-validated.html -$dokka.location:arrow/RestrictedContEffect///PointingToDeclaration/-cont/arrow/-restricted-cont-effect/index.html -$dokka.location:arrow/RestrictedContEffect/bind/arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-cont/arrow/-restricted-cont-effect/bind.html -$dokka.location:arrow/RestrictedContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-cont/arrow/-restricted-cont-effect/shift.html -$dokka.location:arrow/ShiftCancellationException///PointingToDeclaration/-cont/arrow/-shift-cancellation-exception/index.html -arrow - diff --git a/docs/-continuation/arrow/-cont-effect/bind.html b/docs/-continuation/arrow/-cont-effect/bind.html deleted file mode 100644 index ea811f6e6fa..00000000000 --- a/docs/-continuation/arrow/-cont-effect/bind.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - bind - - -
-
- - -
-
-
-
-
-
- -
-

bind

-
-
- -
-
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont-effect/ensure.html b/docs/-continuation/arrow/-cont-effect/ensure.html deleted file mode 100644 index 7c799a3d725..00000000000 --- a/docs/-continuation/arrow/-cont-effect/ensure.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - ensure - - -
-
- - -
-
-
-
-
-
- -
-

ensure

-
-
- -
-
open suspend fun ensure(value: Boolean, shift: () -> R)
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont-effect/index.html b/docs/-continuation/arrow/-cont-effect/index.html deleted file mode 100644 index 20ba2f0257a..00000000000 --- a/docs/-continuation/arrow/-cont-effect/index.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - ContEffect - - -
-
- - -
-
-
-
-
-
- -
-

ContEffect

-
interface ContEffect<R>

Context of the Cont DSL.

-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
- -
-
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
-
-
-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
- -
-
open suspend fun ensure(value: Boolean, shift: () -> R)
-
-
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Inheritors

-
-
-
-
IorEffect -
Link copied to clipboard
-
-
-
-
- -
-
-
OptionEffect -
Link copied to clipboard
-
-
-
-
-
-

Extensions

-
-
-
-
ensureNotNull -
Link copied to clipboard
-
-
-
- -
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont-effect/shift.html b/docs/-continuation/arrow/-cont-effect/shift.html deleted file mode 100644 index 4fb153f5644..00000000000 --- a/docs/-continuation/arrow/-cont-effect/shift.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - shift - - -
-
- - -
-
-
-
-
-
- -
-

shift

-
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/attempt.html b/docs/-continuation/arrow/-cont/attempt.html deleted file mode 100644 index 55e2c6c32a6..00000000000 --- a/docs/-continuation/arrow/-cont/attempt.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - attempt - - -
-
- - -
-
-
-
-
-
- -
-

attempt

-
-
- -
-
open fun attempt(): Cont<R, Result<A>>
-
-

Runs the Cont and captures any NonFatal exception into Result.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/flat-map.html b/docs/-continuation/arrow/-cont/flat-map.html deleted file mode 100644 index 294f0e5bbf9..00000000000 --- a/docs/-continuation/arrow/-cont/flat-map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - flatMap - - -
-
- - -
-
-
-
-
-
- -
-

flatMap

-
-
- -
-
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
-
-

Maps the values A with the transform function into another Cont effect.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/fold.html b/docs/-continuation/arrow/-cont/fold.html deleted file mode 100644 index 25ebbab7111..00000000000 --- a/docs/-continuation/arrow/-cont/fold.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - fold - - -
-
- - -
-
-
-
-
-
- -
-

fold

-
-
- -
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

When the Cont has shifted with R it will recover the shifted value to B, and when it ran the computation to completion it will transform the value A to B.

import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
cont<String, Int> {
shift("Hello, World!")
}.fold({ str: String -> str }, { int -> int.toString() })
.let(::println)

cont<String, Int> {
1000
}.fold({ str: String -> str.length }, { int -> int })
.let(::println)
}
Hello, World!
1000
-
- -
-
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Like fold but also allows folding over any unexpected Throwable that might have occurred.

See also

-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/handle-error-with.html b/docs/-continuation/arrow/-cont/handle-error-with.html deleted file mode 100644 index f35dc87a3d7..00000000000 --- a/docs/-continuation/arrow/-cont/handle-error-with.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - handleErrorWith - - -
-
- - -
-
-
-
-
-
- -
-

handleErrorWith

-
-
- -
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/handle-error.html b/docs/-continuation/arrow/-cont/handle-error.html deleted file mode 100644 index 8fa296f3699..00000000000 --- a/docs/-continuation/arrow/-cont/handle-error.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - handleError - - -
-
- - -
-
-
-
-
-
- -
-

handleError

-
-
- -
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/index.html b/docs/-continuation/arrow/-cont/index.html deleted file mode 100644 index da8ee04e718..00000000000 --- a/docs/-continuation/arrow/-cont/index.html +++ /dev/null @@ -1,280 +0,0 @@ - - - - Cont - - -
-
- - -
-
-
-
-
-
- -
-

Cont

-
interface Cont<R, A>

Cont represents a suspending computation that runs will either

  • Complete with a value of A.

  • Short-circuit with a value of R.

So Cont is defined by fold, to map both values of R and A to a value of B.

-
-
-
-
-

Functions

-
-
-
-
attempt -
Link copied to clipboard
-
-
-
- -
-
open fun attempt(): Cont<R, Result<A>>
-
-

Runs the Cont and captures any NonFatal exception into Result.

-
-
-
-
- -
-
-
flatMap -
Link copied to clipboard
-
-
-
- -
-
open fun <B> flatMap(transform: suspend (A) -> Cont<R, B>): Cont<R, B>
-
-

Maps the values A with the transform function into another Cont effect.

-
-
-
-
- -
-
-
fold -
Link copied to clipboard
-
-
-
- -
-
abstract suspend fun <B> fold(recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Runs the suspending computation by creating a Continuation, and running the fold function over the computation.

-
- -
-
open suspend fun <B> fold(error: suspend (error: Throwable) -> B, recover: suspend (R) -> B, transform: suspend (A) -> B): B
-
-

Like fold but also allows folding over any unexpected Throwable that might have occurred.

-
-
-
-
- -
-
-
handleError -
Link copied to clipboard
-
-
-
- -
-
open fun handleError(recover: suspend (R) -> A): Cont<Nothing, A>
-
-
-
-
-
-
- -
-
-
handleErrorWith -
Link copied to clipboard
-
-
-
- -
-
open fun <R2> handleErrorWith(recover: suspend (R) -> Cont<R2, A>): Cont<R2, A>
-
-
-
-
-
-
- -
-
-
map -
Link copied to clipboard
-
-
-
- -
-
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
-
-

Maps the values A with the transform function into B.

-
-
-
-
- -
-
-
redeem -
Link copied to clipboard
-
-
-
- -
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-
-
-
-
-
-
- -
-
-
redeemWith -
Link copied to clipboard
-
-
-
- -
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-
-
-
-
-
-
- -
-
-
toEither -
Link copied to clipboard
-
-
-
- -
-
open suspend fun toEither(): Either<R, A>
-
-

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

-
-
-
-
- -
-
-
toIor -
Link copied to clipboard
-
-
-
- -
-
open suspend fun toIor(): Ior<R, A>
-
-

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

-
-
-
-
- -
-
-
toOption -
Link copied to clipboard
-
-
-
- -
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
-
-

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

-
-
-
-
- -
-
-
toValidated -
Link copied to clipboard
-
-
-
- -
-
open suspend fun toValidated(): Validated<R, A>
-
-

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

-
-
-
-
-
-

Extensions

-
-
-
-
toOption -
Link copied to clipboard
-
-
-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/map.html b/docs/-continuation/arrow/-cont/map.html deleted file mode 100644 index 36a33383701..00000000000 --- a/docs/-continuation/arrow/-cont/map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - map - - -
-
- - -
-
-
-
-
-
- -
-

map

-
-
- -
-
open fun <B> map(transform: suspend (A) -> B): Cont<R, B>
-
-

Maps the values A with the transform function into B.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/redeem-with.html b/docs/-continuation/arrow/-cont/redeem-with.html deleted file mode 100644 index 64ffbae01eb..00000000000 --- a/docs/-continuation/arrow/-cont/redeem-with.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - redeemWith - - -
-
- - -
-
-
-
-
-
- -
-

redeemWith

-
-
- -
-
open fun <R2, B> redeemWith(recover: suspend (R) -> Cont<R2, B>, transform: suspend (A) -> Cont<R2, B>): Cont<R2, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/redeem.html b/docs/-continuation/arrow/-cont/redeem.html deleted file mode 100644 index 1d34126822e..00000000000 --- a/docs/-continuation/arrow/-cont/redeem.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - redeem - - -
-
- - -
-
-
-
-
-
- -
-

redeem

-
-
- -
-
open fun <B> redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Cont<Nothing, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/to-either.html b/docs/-continuation/arrow/-cont/to-either.html deleted file mode 100644 index 80d3f31cebd..00000000000 --- a/docs/-continuation/arrow/-cont/to-either.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toEither - - -
-
- - -
-
-
-
-
-
- -
-

toEither

-
-
- -
-
open suspend fun toEither(): Either<R, A>
-
-

fold the Cont into an Either. Where the shifted value R is mapped to Either.Left, and result value A is mapped to Either.Right.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/to-ior.html b/docs/-continuation/arrow/-cont/to-ior.html deleted file mode 100644 index 9b37b90c48e..00000000000 --- a/docs/-continuation/arrow/-cont/to-ior.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toIor - - -
-
- - -
-
-
-
-
-
- -
-

toIor

-
-
- -
-
open suspend fun toIor(): Ior<R, A>
-
-

fold the Cont into an Ior. Where the shifted value R is mapped to Ior.Left, and result value A is mapped to Ior.Right.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/to-option.html b/docs/-continuation/arrow/-cont/to-option.html deleted file mode 100644 index d083137aea2..00000000000 --- a/docs/-continuation/arrow/-cont/to-option.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toOption - - -
-
- - -
-
-
-
-
-
- -
-

toOption

-
-
- -
-
open suspend fun toOption(orElse: suspend (R) -> Option<A>): Option<A>
-
-

fold the Cont into an Option. Where the shifted value R is mapped to Option by the provided function orElse, and result value A is mapped to Some.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-cont/to-validated.html b/docs/-continuation/arrow/-cont/to-validated.html deleted file mode 100644 index f8c20cc77ee..00000000000 --- a/docs/-continuation/arrow/-cont/to-validated.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toValidated - - -
-
- - -
-
-
-
-
-
- -
-

toValidated

-
-
- -
-
open suspend fun toValidated(): Validated<R, A>
-
-

fold the Cont into an Validated. Where the shifted value R is mapped to Validated.Invalid, and result value A is mapped to Validated.Valid.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-ior-effect/-ior-effect.html b/docs/-continuation/arrow/-ior-effect/-ior-effect.html deleted file mode 100644 index bfc2746ecd1..00000000000 --- a/docs/-continuation/arrow/-ior-effect/-ior-effect.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - IorEffect - - -
-
- - -
-
-
-
-
-
- -
-

IorEffect

-
-
- -
-
fun <E> IorEffect(semigroup: Semigroup<E>, cont: ContEffect<E>)
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-ior-effect/bind.html b/docs/-continuation/arrow/-ior-effect/bind.html deleted file mode 100644 index 9603c2beaf3..00000000000 --- a/docs/-continuation/arrow/-ior-effect/bind.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - bind - - -
-
- - -
-
-
-
-
-
- -
-

bind

-
-
- -
-
suspend fun <B> Ior<E, B>.bind(): B
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-ior-effect/index.html b/docs/-continuation/arrow/-ior-effect/index.html deleted file mode 100644 index 3f7f5cfb294..00000000000 --- a/docs/-continuation/arrow/-ior-effect/index.html +++ /dev/null @@ -1,153 +0,0 @@ - - - - IorEffect - - -
-
- - -
-
-
-
-
-
- -
-

IorEffect

-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
- -
-
open suspend fun <B> Cont<E, B>.bind(): B
open suspend fun <B> Either<E, B>.bind(): B
open suspend fun <B> Validated<E, B>.bind(): B
suspend fun <B> Ior<E, B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> E): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> E): B
-
-
-
-
-
-
- -
-
-
combine -
Link copied to clipboard
-
-
-
- -
-
open override fun E.combine(b: E): E
-
-
-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
- -
-
open suspend fun ensure(value: Boolean, shift: () -> E)
-
-
-
-
-
-
- -
-
-
maybeCombine -
Link copied to clipboard
-
-
-
- -
-
open override fun E.maybeCombine(b: E?): E
-
-
-
-
-
-
- -
-
-
plus -
Link copied to clipboard
-
-
-
- -
-
open operator override fun E.plus(b: E): E
-
-
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
- -
-
open suspend override fun <B> shift(r: E): B
-
-

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-ior-effect/shift.html b/docs/-continuation/arrow/-ior-effect/shift.html deleted file mode 100644 index cdda291eb20..00000000000 --- a/docs/-continuation/arrow/-ior-effect/shift.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - shift - - -
-
- - -
-
-
-
-
-
- -
-

shift

-
-
- -
-
open suspend override fun <B> shift(r: E): B
-
-

Short-circuit the Cont computation with value R.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-option-effect/-option-effect.html b/docs/-continuation/arrow/-option-effect/-option-effect.html deleted file mode 100644 index 79ae4e9ad3f..00000000000 --- a/docs/-continuation/arrow/-option-effect/-option-effect.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - OptionEffect - - -
-
- - -
-
-
-
-
-
- -
-

OptionEffect

-
-
- -
-
fun OptionEffect(cont: ContEffect<None>)
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-option-effect/bind.html b/docs/-continuation/arrow/-option-effect/bind.html deleted file mode 100644 index 65c50d497ef..00000000000 --- a/docs/-continuation/arrow/-option-effect/bind.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - bind - - -
-
- - -
-
-
-
-
-
- -
-

bind

-
-
- -
-
suspend fun <B> Option<B>.bind(): B
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-option-effect/ensure.html b/docs/-continuation/arrow/-option-effect/ensure.html deleted file mode 100644 index 1473fbd564f..00000000000 --- a/docs/-continuation/arrow/-option-effect/ensure.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - ensure - - -
-
- - -
-
-
-
-
-
- -
-

ensure

-
-
- -
-
suspend fun ensure(value: Boolean)
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-option-effect/index.html b/docs/-continuation/arrow/-option-effect/index.html deleted file mode 100644 index c9720cec4df..00000000000 --- a/docs/-continuation/arrow/-option-effect/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - OptionEffect - - -
-
- - -
-
-
-
-
-
- -
-

OptionEffect

-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
- -
-
open suspend fun <B> Cont<None, B>.bind(): B
open suspend fun <B> Either<None, B>.bind(): B
open suspend fun <B> Validated<None, B>.bind(): B
suspend fun <B> Option<B>.bind(): B
open suspend fun <B> Option<B>.bind(shift: () -> None): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> None): B
-
-
-
-
-
-
- -
-
-
ensure -
Link copied to clipboard
-
-
-
- -
-
suspend fun ensure(value: Boolean)
open suspend fun ensure(value: Boolean, shift: () -> None)
-
-
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
- -
-
open suspend override fun <B> shift(r: None): B
-
-

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-option-effect/shift.html b/docs/-continuation/arrow/-option-effect/shift.html deleted file mode 100644 index 543ebed5eae..00000000000 --- a/docs/-continuation/arrow/-option-effect/shift.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - shift - - -
-
- - -
-
-
-
-
-
- -
-

shift

-
-
- -
-
open suspend override fun <B> shift(r: None): B
-
-

Short-circuit the Cont computation with value R.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont-effect/bind.html b/docs/-continuation/arrow/-restricted-cont-effect/bind.html deleted file mode 100644 index 4a237f713fa..00000000000 --- a/docs/-continuation/arrow/-restricted-cont-effect/bind.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - bind - - -
-
- - -
-
-
-
-
-
- -
-

bind

-
-
- -
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont-effect/index.html b/docs/-continuation/arrow/-restricted-cont-effect/index.html deleted file mode 100644 index 7393b400496..00000000000 --- a/docs/-continuation/arrow/-restricted-cont-effect/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - RestrictedContEffect - - -
-
- - -
-
-
-
-
-
- -
-

RestrictedContEffect

-
interface RestrictedContEffect<R>
-
-
-
-
-

Functions

-
-
-
-
bind -
Link copied to clipboard
-
-
-
- -
-
open suspend fun <A> RestrictedCont<R, A>.bind(): A
-
-
-
-
-
-
- -
-
-
shift -
Link copied to clipboard
-
-
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont-effect/shift.html b/docs/-continuation/arrow/-restricted-cont-effect/shift.html deleted file mode 100644 index 9a7de49fe40..00000000000 --- a/docs/-continuation/arrow/-restricted-cont-effect/shift.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - shift - - -
-
- - -
-
-
-
-
-
- -
-

shift

-
-
- -
-
abstract suspend fun <B> shift(r: R): B
-
-

Short-circuit the Cont computation with value R.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/attempt.html b/docs/-continuation/arrow/-restricted-cont/attempt.html deleted file mode 100644 index c256d0f28f5..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/attempt.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - attempt - - -
-
- - -
-
-
-
-
-
- -
-

attempt

-
-
- -
-
open fun attempt(): RestrictedCont<R, Result<A>>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/flat-map.html b/docs/-continuation/arrow/-restricted-cont/flat-map.html deleted file mode 100644 index 88d5c49771d..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/flat-map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - flatMap - - -
-
- - -
-
-
-
-
-
- -
-

flatMap

-
-
- -
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/fold.html b/docs/-continuation/arrow/-restricted-cont/fold.html deleted file mode 100644 index 68d2d16569a..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/fold.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - fold - - -
-
- - -
-
-
-
-
-
- -
-

fold

-
-
- -
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/handle-error-with.html b/docs/-continuation/arrow/-restricted-cont/handle-error-with.html deleted file mode 100644 index 5051a0306e7..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/handle-error-with.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - handleErrorWith - - -
-
- - -
-
-
-
-
-
- -
-

handleErrorWith

-
-
- -
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/handle-error.html b/docs/-continuation/arrow/-restricted-cont/handle-error.html deleted file mode 100644 index e88b7bf681f..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/handle-error.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - handleError - - -
-
- - -
-
-
-
-
-
- -
-

handleError

-
-
- -
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/index.html b/docs/-continuation/arrow/-restricted-cont/index.html deleted file mode 100644 index dd86932c806..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/index.html +++ /dev/null @@ -1,221 +0,0 @@ - - - - RestrictedCont - - -
-
- - -
-
-
-
-
-
- -
-

RestrictedCont

-
interface RestrictedCont<R, A>
-
-
-
-
-

Functions

-
-
-
-
attempt -
Link copied to clipboard
-
-
-
- -
-
open fun attempt(): RestrictedCont<R, Result<A>>
-
-
-
-
-
-
- -
-
-
flatMap -
Link copied to clipboard
-
-
-
- -
-
open fun <B> flatMap(f: (A) -> RestrictedCont<R, B>): RestrictedCont<R, B>
-
-
-
-
-
-
- -
-
-
fold -
Link copied to clipboard
-
-
-
- -
-
abstract fun <B> fold(f: (R) -> B, g: (A) -> B): B
-
-
-
-
-
-
- -
-
-
handleError -
Link copied to clipboard
-
-
-
- -
-
open fun handleError(f: (R) -> A): RestrictedCont<Nothing, A>
-
-
-
-
-
-
- -
-
-
handleErrorWith -
Link copied to clipboard
-
-
-
- -
-
open fun <R2> handleErrorWith(f: (R) -> RestrictedCont<R2, A>): RestrictedCont<R2, A>
-
-
-
-
-
-
- -
-
-
map -
Link copied to clipboard
-
-
-
- -
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-
-
-
-
-
-
- -
-
-
redeem -
Link copied to clipboard
-
-
-
- -
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-
-
-
-
-
-
- -
-
-
redeemWith -
Link copied to clipboard
-
-
-
- -
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-
-
-
-
-
-
- -
-
-
toEither -
Link copied to clipboard
-
-
-
- -
-
open fun toEither(): Either<R, A>
-
-
-
-
-
-
- -
-
-
toValidated -
Link copied to clipboard
-
-
-
- -
-
open fun toValidated(): Validated<R, A>
-
-
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/map.html b/docs/-continuation/arrow/-restricted-cont/map.html deleted file mode 100644 index 724eb070771..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/map.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - map - - -
-
- - -
-
-
-
-
-
- -
-

map

-
-
- -
-
open fun <B> map(f: (A) -> B): RestrictedCont<R, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/redeem-with.html b/docs/-continuation/arrow/-restricted-cont/redeem-with.html deleted file mode 100644 index fb364445780..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/redeem-with.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - redeemWith - - -
-
- - -
-
-
-
-
-
- -
-

redeemWith

-
-
- -
-
open fun <R2, B> redeemWith(f: (R) -> RestrictedCont<R2, B>, g: (A) -> RestrictedCont<R2, B>): RestrictedCont<R2, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/redeem.html b/docs/-continuation/arrow/-restricted-cont/redeem.html deleted file mode 100644 index 46490f72c51..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/redeem.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - redeem - - -
-
- - -
-
-
-
-
-
- -
-

redeem

-
-
- -
-
open fun <B> redeem(f: (R) -> B, g: (A) -> B): RestrictedCont<Nothing, B>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/to-either.html b/docs/-continuation/arrow/-restricted-cont/to-either.html deleted file mode 100644 index 3e2ec14d5f9..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/to-either.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toEither - - -
-
- - -
-
-
-
-
-
- -
-

toEither

-
-
- -
-
open fun toEither(): Either<R, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-restricted-cont/to-validated.html b/docs/-continuation/arrow/-restricted-cont/to-validated.html deleted file mode 100644 index 728384f62d4..00000000000 --- a/docs/-continuation/arrow/-restricted-cont/to-validated.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toValidated - - -
-
- - -
-
-
-
-
-
- -
-

toValidated

-
-
- -
-
open fun toValidated(): Validated<R, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/-shift-cancellation-exception/index.html b/docs/-continuation/arrow/-shift-cancellation-exception/index.html deleted file mode 100644 index fd74753fbec..00000000000 --- a/docs/-continuation/arrow/-shift-cancellation-exception/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - ShiftCancellationException - - -
-
- - -
-
-
-
-
-
- -
-

ShiftCancellationException

-
sealed class ShiftCancellationException : CancellationException
-
-
-
-
-

Properties

-
-
-
-
cause -
Link copied to clipboard
-
-
-
-
open val cause: Throwable?
-
-
-
-
- -
-
-
message -
Link copied to clipboard
-
-
-
-
open val message: String?
-
-
-
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/cont.html b/docs/-continuation/arrow/cont.html deleted file mode 100644 index 2e33fb68104..00000000000 --- a/docs/-continuation/arrow/cont.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - cont - - -
-
- - -
-
-
-
-
-
- -
-

cont

-
-
- -
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
-
-

DSL for constructing Cont values

import arrow.core.*
import arrow.cont
import kotlinx.coroutines.runBlocking

fun main() = runBlocking<Unit> {
cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z = Option(3).bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)

cont<String, Int> {
val x = Either.Right(1).bind()
val y = Validated.Valid(2).bind()
val z: Int = None.bind { "Option was empty" }
x + y + z
}.fold(::println, ::println)
}
6
Option was empty
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/either.html b/docs/-continuation/arrow/either.html deleted file mode 100644 index f2201c282b8..00000000000 --- a/docs/-continuation/arrow/either.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - either - - -
-
- - -
-
-
-
-
-
- -
-

either

-
-
- -
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/ensure-not-null.html b/docs/-continuation/arrow/ensure-not-null.html deleted file mode 100644 index 8ea4e5d042e..00000000000 --- a/docs/-continuation/arrow/ensure-not-null.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - ensureNotNull - - -
-
- - -
-
-
-
-
-
- -
-

ensureNotNull

-
-
- -
-
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/index.html b/docs/-continuation/arrow/index.html deleted file mode 100644 index 3f0f0ffbf28..00000000000 --- a/docs/-continuation/arrow/index.html +++ /dev/null @@ -1,313 +0,0 @@ - - - - arrow - - -
-
- - -
-
-
-
-
-
- -
-

Package arrow

-
-
-
-
-

Types

-
-
-
-
Cont -
Link copied to clipboard
-
-
-
- -
-
interface Cont<R, A>
-
-

Cont represents a suspending computation that runs will either

-
-
-
-
- -
-
-
ContEffect -
Link copied to clipboard
-
-
-
- -
-
interface ContEffect<R>
-
-

Context of the Cont DSL.

-
-
-
-
- -
-
-
IorEffect -
Link copied to clipboard
-
-
-
- -
-
class IorEffect<E>(semigroup: Semigroup<E>, cont: ContEffect<E>) : ContEffect<E> , Semigroup<E>
-
-
-
-
-
-
- -
-
-
OptionEffect -
Link copied to clipboard
-
-
-
- -
-
value class OptionEffect(cont: ContEffect<None>) : ContEffect<None>
-
-
-
-
-
-
- -
-
-
RestrictedCont -
Link copied to clipboard
-
-
-
- -
-
interface RestrictedCont<R, A>
-
-
-
-
-
-
- -
-
-
RestrictedContEffect -
Link copied to clipboard
-
-
-
- -
-
interface RestrictedContEffect<R>
-
-
-
-
-
-
- -
-
-
ShiftCancellationException -
Link copied to clipboard
-
-
-
- -
-
sealed class ShiftCancellationException : CancellationException
-
-
-
-
-
-
-
-

Functions

-
-
-
-
cont -
Link copied to clipboard
-
-
-
- -
-
fun <R, A> cont(f: suspend ContEffect<R>.() -> A): Cont<R, A>
-
-

DSL for constructing Cont values

-
-
-
-
- -
-
-
either -
Link copied to clipboard
-
-
-
- -
-
suspend fun <E, A> either(f: suspend ContEffect<E>.() -> A): Either<E, A>
-
-
-
-
-
-
- -
-
-
ensureNotNull -
Link copied to clipboard
-
-
-
- -
-
suspend fun <B : Any> ContEffect<None>.ensureNotNull(value: B?): B
suspend fun <R, B : Any> ContEffect<R>.ensureNotNull(value: B?, shift: () -> R): B
-
-
-
-
-
-
- -
-
-
ior -
Link copied to clipboard
-
-
-
- -
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-
-
-
-
-
-
- -
-
-
option -
Link copied to clipboard
-
-
-
- -
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-
-
-
-
-
-
- -
-
-
restrictedCont -
Link copied to clipboard
-
-
-
- -
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
-
-

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-
-
-
-
- -
-
-
sequence -
Link copied to clipboard
-
-
-
- -
-
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
-
-
-
-
-
-
- -
-
-
toOption -
Link copied to clipboard
-
-
-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-
-
-
-
- -
-
-
traverseCont -
Link copied to clipboard
-
-
-
- -
-
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
-
-
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/ior.html b/docs/-continuation/arrow/ior.html deleted file mode 100644 index fff8760bce5..00000000000 --- a/docs/-continuation/arrow/ior.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - ior - - -
-
- - -
-
-
-
-
-
- -
-

ior

-
-
- -
-
suspend fun <E, A> ior(semigroup: Semigroup<E>, f: suspend IorEffect<E>.() -> A): Ior<E, A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/option.html b/docs/-continuation/arrow/option.html deleted file mode 100644 index 91e56e8f851..00000000000 --- a/docs/-continuation/arrow/option.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - option - - -
-
- - -
-
-
-
-
-
- -
-

option

-
-
- -
-
suspend fun <A> option(f: OptionEffect.() -> A): Option<A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/restricted-cont.html b/docs/-continuation/arrow/restricted-cont.html deleted file mode 100644 index 7586bc9d1a0..00000000000 --- a/docs/-continuation/arrow/restricted-cont.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - restrictedCont - - -
-
- - -
-
-
-
-
-
- -
-

restrictedCont

-
-
- -
-
fun <R, A> restrictedCont(f: suspend RestrictedContEffect<R>.() -> A): RestrictedCont<R, A>
-
-

RestrictsSuspension version of Cont<R, A>. This version runs eagerly, can can be used in non-suspending code.

-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/sequence.html b/docs/-continuation/arrow/sequence.html deleted file mode 100644 index d0777547d7a..00000000000 --- a/docs/-continuation/arrow/sequence.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - sequence - - -
-
- - -
-
-
-
-
-
- -
-

sequence

-
-
- -
-
fun <R, A> Iterable<Cont<R, A>>.sequence(): Cont<R, List<A>>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/to-option.html b/docs/-continuation/arrow/to-option.html deleted file mode 100644 index 76026ba991b..00000000000 --- a/docs/-continuation/arrow/to-option.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - toOption - - -
-
- - -
-
-
-
-
-
- -
-

toOption

-
-
- -
-
suspend fun <A> Cont<None, A>.toOption(): Option<A>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/arrow/traverse-cont.html b/docs/-continuation/arrow/traverse-cont.html deleted file mode 100644 index 9a5a51c21d7..00000000000 --- a/docs/-continuation/arrow/traverse-cont.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - traverseCont - - -
-
- - -
-
-
-
-
-
- -
-

traverseCont

-
-
- -
-
fun <R, A, B> Iterable<A>.traverseCont(transform: (A) -> Cont<R, B>): Cont<R, List<B>>
-
-
-

Sources

-
-
-
-
common source -
Link copied to clipboard
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/-continuation/package-list b/docs/-continuation/package-list deleted file mode 100644 index ce9d3bcdcd8..00000000000 --- a/docs/-continuation/package-list +++ /dev/null @@ -1,61 +0,0 @@ -$dokka.format:html-v1 -$dokka.linkExtension:html -$dokka.location:arrow////PointingToDeclaration/-continuation/arrow/index.html -$dokka.location:arrow//cont/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/cont.html -$dokka.location:arrow//either/#kotlin.coroutines.SuspendFunction1[arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/either.html -$dokka.location:arrow//ensureNotNull/arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]#TypeParam(bounds=[kotlin.Any])?#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/ensure-not-null.html -$dokka.location:arrow//ensureNotNull/arrow.ContEffect[arrow.core.None]#TypeParam(bounds=[kotlin.Any])?/PointingToDeclaration/-continuation/arrow/ensure-not-null.html -$dokka.location:arrow//ior/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[arrow.IorEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/ior.html -$dokka.location:arrow//option/#kotlin.Function1[arrow.OptionEffect,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/option.html -$dokka.location:arrow//restrictedCont/#kotlin.coroutines.SuspendFunction1[arrow.RestrictedContEffect[TypeParam(bounds=[kotlin.Any?])],TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/restricted-cont.html -$dokka.location:arrow//sequence/kotlin.collections.Iterable[arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#/PointingToDeclaration/-continuation/arrow/sequence.html -$dokka.location:arrow//toOption/arrow.Cont[arrow.core.None,TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/to-option.html -$dokka.location:arrow//traverseCont/kotlin.collections.Iterable[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/traverse-cont.html -$dokka.location:arrow/Cont///PointingToDeclaration/-continuation/arrow/-cont/index.html -$dokka.location:arrow/Cont/attempt/#/PointingToDeclaration/-continuation/arrow/-cont/attempt.html -$dokka.location:arrow/Cont/flatMap/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/flat-map.html -$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/fold.html -$dokka.location:arrow/Cont/fold/#kotlin.coroutines.SuspendFunction1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/fold.html -$dokka.location:arrow/Cont/handleError/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/handle-error.html -$dokka.location:arrow/Cont/handleErrorWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/handle-error-with.html -$dokka.location:arrow/Cont/map/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/map.html -$dokka.location:arrow/Cont/redeem/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont/redeem.html -$dokka.location:arrow/Cont/redeemWith/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/redeem-with.html -$dokka.location:arrow/Cont/toEither/#/PointingToDeclaration/-continuation/arrow/-cont/to-either.html -$dokka.location:arrow/Cont/toIor/#/PointingToDeclaration/-continuation/arrow/-cont/to-ior.html -$dokka.location:arrow/Cont/toOption/#kotlin.coroutines.SuspendFunction1[TypeParam(bounds=[kotlin.Any?]),arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-cont/to-option.html -$dokka.location:arrow/Cont/toValidated/#/PointingToDeclaration/-continuation/arrow/-cont/to-validated.html -$dokka.location:arrow/ContEffect///PointingToDeclaration/-continuation/arrow/-cont-effect/index.html -$dokka.location:arrow/ContEffect/bind/arrow.Cont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Either[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/arrow.core.Validated[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/bind/kotlin.Result[TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[kotlin.Throwable,TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/bind.html -$dokka.location:arrow/ContEffect/ensure/#kotlin.Boolean#kotlin.Function0[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-cont-effect/ensure.html -$dokka.location:arrow/ContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-cont-effect/shift.html -$dokka.location:arrow/IorEffect///PointingToDeclaration/-continuation/arrow/-ior-effect/index.html -$dokka.location:arrow/IorEffect/IorEffect/#arrow.typeclasses.Semigroup[TypeParam(bounds=[kotlin.Any?])]#arrow.ContEffect[TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-ior-effect/-ior-effect.html -$dokka.location:arrow/IorEffect/bind/arrow.core.Ior[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-ior-effect/bind.html -$dokka.location:arrow/IorEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-ior-effect/shift.html -$dokka.location:arrow/OptionEffect///PointingToDeclaration/-continuation/arrow/-option-effect/index.html -$dokka.location:arrow/OptionEffect/OptionEffect/#arrow.ContEffect[arrow.core.None]/PointingToDeclaration/-continuation/arrow/-option-effect/-option-effect.html -$dokka.location:arrow/OptionEffect/bind/arrow.core.Option[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-option-effect/bind.html -$dokka.location:arrow/OptionEffect/ensure/#kotlin.Boolean/PointingToDeclaration/-continuation/arrow/-option-effect/ensure.html -$dokka.location:arrow/OptionEffect/shift/#arrow.core.None/PointingToDeclaration/-continuation/arrow/-option-effect/shift.html -$dokka.location:arrow/RestrictedCont///PointingToDeclaration/-continuation/arrow/-restricted-cont/index.html -$dokka.location:arrow/RestrictedCont/attempt/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/attempt.html -$dokka.location:arrow/RestrictedCont/flatMap/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/flat-map.html -$dokka.location:arrow/RestrictedCont/fold/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/fold.html -$dokka.location:arrow/RestrictedCont/handleError/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/handle-error.html -$dokka.location:arrow/RestrictedCont/handleErrorWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/handle-error-with.html -$dokka.location:arrow/RestrictedCont/map/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/map.html -$dokka.location:arrow/RestrictedCont/redeem/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]/PointingToDeclaration/-continuation/arrow/-restricted-cont/redeem.html -$dokka.location:arrow/RestrictedCont/redeemWith/#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]#kotlin.Function1[TypeParam(bounds=[kotlin.Any?]),arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]]/PointingToDeclaration/-continuation/arrow/-restricted-cont/redeem-with.html -$dokka.location:arrow/RestrictedCont/toEither/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/to-either.html -$dokka.location:arrow/RestrictedCont/toValidated/#/PointingToDeclaration/-continuation/arrow/-restricted-cont/to-validated.html -$dokka.location:arrow/RestrictedContEffect///PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/index.html -$dokka.location:arrow/RestrictedContEffect/bind/arrow.RestrictedCont[TypeParam(bounds=[kotlin.Any?]),TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/bind.html -$dokka.location:arrow/RestrictedContEffect/shift/#TypeParam(bounds=[kotlin.Any?])/PointingToDeclaration/-continuation/arrow/-restricted-cont-effect/shift.html -$dokka.location:arrow/ShiftCancellationException///PointingToDeclaration/-continuation/arrow/-shift-cancellation-exception/index.html -arrow - diff --git a/docs/images/anchor-copy-button.svg b/docs/images/anchor-copy-button.svg deleted file mode 100644 index bab9d747ff4..00000000000 --- a/docs/images/anchor-copy-button.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/docs/images/arrow_down.svg b/docs/images/arrow_down.svg deleted file mode 100644 index c0388dee2ce..00000000000 --- a/docs/images/arrow_down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/images/copy-icon.svg b/docs/images/copy-icon.svg deleted file mode 100644 index 61440f0a40a..00000000000 --- a/docs/images/copy-icon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/images/copy-successful-icon.svg b/docs/images/copy-successful-icon.svg deleted file mode 100644 index 1865f739b09..00000000000 --- a/docs/images/copy-successful-icon.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/images/docs_logo.svg b/docs/images/docs_logo.svg deleted file mode 100644 index 7c1e3ae8ea4..00000000000 --- a/docs/images/docs_logo.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/docs/images/footer-go-to-link.svg b/docs/images/footer-go-to-link.svg deleted file mode 100644 index 0137e22313f..00000000000 --- a/docs/images/footer-go-to-link.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/images/go-to-top-icon.svg b/docs/images/go-to-top-icon.svg deleted file mode 100644 index d987f3eadcf..00000000000 --- a/docs/images/go-to-top-icon.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/docs/images/logo-icon.svg b/docs/images/logo-icon.svg deleted file mode 100644 index 1fea08773f3..00000000000 --- a/docs/images/logo-icon.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/docs/images/theme-toggle.svg b/docs/images/theme-toggle.svg deleted file mode 100644 index 2a8d750ea98..00000000000 --- a/docs/images/theme-toggle.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 5777ba696b0..00000000000 --- a/docs/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - Cont - - - - -
-
-
-
-
-
- -
-

Cont

-
  • #writing-a-program-with-cont

  • #handling-errors

  • #structured-concurrency

    • #arrow-fx-coroutines

      • #parzip

      • #partraverse

      • #racen

      • #bracketcase--resource

    • #kotlinx

      • #withcontext

      • #async

      • #launch

      • #strange-edge-cases

Cont<R, A> represents a function of suspend () -> A that can fail with R (and Throwable), so it's defined by suspend fun <B> fold(f: suspend (R) -> B, g: suspend (A) -> B): B.

So to construct a Cont<R, A> we simply call the cont<R, A> { } DSL, which exposes a rich syntax through the lambda receiver suspend ContEffect<R>.() -> A.

What is interesting about the Cont<R, A> type is that it doesn't rely on any wrappers such as Either, Ior or Validated. Instead Cont<R, A> represents a suspend function, and only when we call fold it will actually create a Continuation and runs the computation (without intercepting). This makes Cont<R, A> a very efficient generic runtime.

Writing a program with Cont

Let's write a small program to read a file from disk, and instead of having the program work exception based we want to turn it into a polymorphic type-safe program.

We'll start by defining a small function that accepts a String, and does some simply validation to check that the path is not empty. If the path is empty, we want to program to result in EmptyPath. So we're immediately going to see how we can raise an error of any arbitrary type R by using the function shift. The name shift comes shifting (or changing, especially unexpectedly), away from the computation and finishing the Continuation with R.

object EmptyPath

fun readFile(path: String): Cont<EmptyPath, Unit> = cont {
if (path.isNotEmpty()) shift(EmptyPath) else Unit
}

Here we see how we can define a Cont<R, A> which has EmptyPath for the shift type R, and Unit for the success type A.

Patterns like validating a Boolean is very common, and the Cont DSL offers utility functions like kotlin.require and kotlin.requireNotNull. They're named ensure and ensureNotNull to avoid conflicts with the kotlin namespace. So let's rewrite the function from above to use the DSL instead.

fun readFile2(path: String?): Cont<EmptyPath, Unit> = cont {
ensureNotNull(path) { EmptyPath }
ensure(path.isEmpty()) { EmptyPath }
}

You can get the full code guide/example/example-readme-01.kt.

Now that we have the path, we can read from the File and return it as a domain model Content. We also want to take a look at what exceptions reading from a file might occur FileNotFoundException&SecurityError, so lets make some domain errors for those too. Grouping them as a sealed interface is useful since that way we can resolve all errors in a type safe manner.

-
-

Packages

-
-
-
-
-
arrow -
Link copied to clipboard
-
-
-
-
-
-
-
-
- -
-
- - - diff --git a/docs/knit.code.include b/docs/knit.code.include deleted file mode 100644 index e658f50213a..00000000000 --- a/docs/knit.code.include +++ /dev/null @@ -1,15 +0,0 @@ -// This file was automatically generated from ${file.name} by Knit tool. Do not edit. -package ${knit.package}.${knit.name} - -import arrow.* -import arrow.core.* -import arrow.fx.coroutines.* -import kotlinx.coroutines.* -import io.kotest.matchers.collections.* -import io.kotest.assertions.* -import io.kotest.matchers.* -import io.kotest.matchers.types.* -import kotlin.coroutines.cancellation.CancellationException -import io.kotest.property.* -import io.kotest.property.arbitrary.* -import arrow.core.test.generators.* diff --git a/docs/knit.test.template b/docs/knit.test.template deleted file mode 100644 index d7c46cfb236..00000000000 --- a/docs/knit.test.template +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from ${file.name} by Knit tool. Do not edit. -package ${test.package} - -import io.kotest.core.spec.style.StringSpec -import kotlin.time.Duration -import kotlin.time.ExperimentalTime - -@OptIn(ExperimentalTime::class) -class ${test.name} : StringSpec({ -<#list cases as case> - "${case.name}".config(timeout= Duration.seconds(1)) { - ${case.knit.package}.${case.knit.name}.test() - } - - -}) \ No newline at end of file diff --git a/docs/navigation.html b/docs/navigation.html deleted file mode 100644 index c962756a1d9..00000000000 --- a/docs/navigation.html +++ /dev/null @@ -1,49 +0,0 @@ - - diff --git a/docs/scripts/clipboard.js b/docs/scripts/clipboard.js deleted file mode 100644 index b00ce246ef3..00000000000 --- a/docs/scripts/clipboard.js +++ /dev/null @@ -1,52 +0,0 @@ -window.addEventListener('load', () => { - document.querySelectorAll('span.copy-icon').forEach(element => { - element.addEventListener('click', (el) => copyElementsContentToClipboard(element)); - }) - - document.querySelectorAll('span.anchor-icon').forEach(element => { - element.addEventListener('click', (el) => { - if(element.hasAttribute('pointing-to')){ - const location = hrefWithoutCurrentlyUsedAnchor() + '#' + element.getAttribute('pointing-to') - copyTextToClipboard(element, location) - } - }); - }) -}) - -const copyElementsContentToClipboard = (element) => { - const selection = window.getSelection(); - const range = document.createRange(); - range.selectNodeContents(element.parentNode.parentNode); - selection.removeAllRanges(); - selection.addRange(range); - - copyAndShowPopup(element, () => selection.removeAllRanges()) -} - -const copyTextToClipboard = (element, text) => { - var textarea = document.createElement("textarea"); - textarea.textContent = text; - textarea.style.position = "fixed"; - document.body.appendChild(textarea); - textarea.select(); - - copyAndShowPopup(element, () => document.body.removeChild(textarea)) -} - -const copyAndShowPopup = (element, after) => { - try { - document.execCommand('copy'); - element.nextElementSibling.classList.add('active-popup'); - setTimeout(() => { - element.nextElementSibling.classList.remove('active-popup'); - }, 1200); - } catch (e) { - console.error('Failed to write to clipboard:', e) - } - finally { - if(after) after() - } -} - -const hrefWithoutCurrentlyUsedAnchor = () => window.location.href.split('#')[0] - diff --git a/docs/scripts/main.js b/docs/scripts/main.js deleted file mode 100644 index 3141dbe50a2..00000000000 --- a/docs/scripts/main.js +++ /dev/null @@ -1,67 +0,0 @@ -!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=378)}([function(e,t,n){e.exports=n(262)()},function(e,t,n){"use strict";e.exports=n(237)},function(e,t,n){var r; -/*! - Copyright (c) 2017 Jed Watson. - Licensed under the MIT License (MIT), see - http://jedwatson.github.io/classnames -*/!function(){"use strict";var n={}.hasOwnProperty;function o(){for(var e=[],t=0;to;)Q(e,n=r[o++],t[n]);return e},X=function(e){var t=F.call(this,e=x(e,!0));return!(this===W&&o(H,e)&&!o(U,e))&&(!(t||!o(this,e)||!o(H,e)||o(this,N)&&this[N][e])||t)},J=function(e,t){if(e=w(e),t=x(t,!0),e!==W||!o(H,t)||o(U,t)){var n=I(e,t);return!n||!o(H,t)||o(e,N)&&e[N][t]||(n.enumerable=!0),n}},Z=function(e){for(var t,n=z(w(e)),r=[],i=0;n.length>i;)o(H,t=n[i++])||t==N||t==c||r.push(t);return r},ee=function(e){for(var t,n=e===W,r=z(n?U:w(e)),i=[],a=0;r.length>a;)!o(H,t=r[a++])||n&&!o(W,t)||i.push(H[t]);return i};B||(l((R=function(){if(this instanceof R)throw TypeError("Symbol is not a constructor!");var e=p(arguments.length>0?arguments[0]:void 0),t=function(n){this===W&&t.call(U,n),o(this,N)&&o(this[N],e)&&(this[N][e]=!1),K(this,e,S(1,n))};return i&&V&&K(W,e,{configurable:!0,set:t}),q(e)}).prototype,"toString",(function(){return this._k})),E.f=J,C.f=Q,n(111).f=O.f=Z,n(93).f=X,T.f=ee,i&&!n(108)&&l(W,"propertyIsEnumerable",X,!0),h.f=function(e){return q(d(e))}),a(a.G+a.W+a.F*!B,{Symbol:R});for(var te="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),ne=0;te.length>ne;)d(te[ne++]);for(var re=P(d.store),oe=0;re.length>oe;)v(re[oe++]);a(a.S+a.F*!B,"Symbol",{for:function(e){return o(D,e+="")?D[e]:D[e]=R(e)},keyFor:function(e){if(!$(e))throw TypeError(e+" is not a symbol!");for(var t in D)if(D[t]===e)return t},useSetter:function(){V=!0},useSimple:function(){V=!1}}),a(a.S+a.F*!B,"Object",{create:function(e,t){return void 0===t?k(e):Y(k(e),t)},defineProperty:Q,defineProperties:Y,getOwnPropertyDescriptor:J,getOwnPropertyNames:Z,getOwnPropertySymbols:ee});var ie=u((function(){T.f(1)}));a(a.S+a.F*ie,"Object",{getOwnPropertySymbols:function(e){return T.f(_(e))}}),M&&a(a.S+a.F*(!B||u((function(){var e=R();return"[null]"!=A([e])||"{}"!=A({a:e})||"{}"!=A(Object(e))}))),"JSON",{stringify:function(e){for(var t,n,r=[e],o=1;arguments.length>o;)r.push(arguments[o++]);if(n=t=r[1],(y(t)||void 0!==e)&&!$(e))return m(t)||(t=function(e,t){if("function"==typeof n&&(t=n.call(this,e,t)),!$(t))return t}),r[1]=t,A.apply(M,r)}}),R.prototype[L]||n(59)(R.prototype,L,R.prototype.valueOf),f(R,"Symbol"),f(Math,"Math",!0),f(r.JSON,"JSON",!0)},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperty:n(39).f})},function(e,t,n){"use strict";n(255);var r=n(27),o=n(135),i=n(30),a=/./.toString,l=function(e){n(41)(RegExp.prototype,"toString",e,!0)};n(31)((function(){return"/a/b"!=a.call({source:"a",flags:"b"})}))?l((function(){var e=r(this);return"/".concat(e.source,"/","flags"in e?e.flags:!i&&e instanceof RegExp?o.call(e):void 0)})):"toString"!=a.name&&l((function(){return a.call(this)}))},function(e,t,n){var r=Date.prototype,o=r.toString,i=r.getTime;new Date(NaN)+""!="Invalid Date"&&n(41)(r,"toString",(function(){var e=i.call(this);return e==e?o.call(this):"Invalid Date"}))},function(e,t,n){n(178)("asyncIterator")},function(e,t,n){var r=n(32),o=n(78),i=n(59),a=n(41),l=n(79),c=function(e,t,n){var u,s,f,p,d=e&c.F,h=e&c.G,v=e&c.S,g=e&c.P,m=e&c.B,b=h?r:v?r[t]||(r[t]={}):(r[t]||{}).prototype,y=h?o:o[t]||(o[t]={}),_=y.prototype||(y.prototype={});for(u in h&&(n=t),n)f=((s=!d&&b&&void 0!==b[u])?b:n)[u],p=m&&s?l(f,r):g&&"function"==typeof f?l(Function.call,f):f,b&&a(b,u,f,e&c.U),y[u]!=f&&i(y,u,p),g&&_[u]!=f&&(_[u]=f)};r.core=o,c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){for(var r=n(12),o=n(69),i=n(41),a=n(32),l=n(59),c=n(94),u=n(25),s=u("iterator"),f=u("toStringTag"),p=c.Array,d={CSSRuleList:!0,CSSStyleDeclaration:!1,CSSValueList:!1,ClientRectList:!1,DOMRectList:!1,DOMStringList:!1,DOMTokenList:!0,DataTransferItemList:!1,FileList:!1,HTMLAllCollection:!1,HTMLCollection:!1,HTMLFormElement:!1,HTMLSelectElement:!1,MediaList:!0,MimeTypeArray:!1,NamedNodeMap:!1,NodeList:!0,PaintRequestList:!1,Plugin:!1,PluginArray:!1,SVGLengthList:!1,SVGNumberList:!1,SVGPathSegList:!1,SVGPointList:!1,SVGStringList:!1,SVGTransformList:!1,SourceBufferList:!1,StyleSheetList:!0,TextTrackCueList:!1,TextTrackList:!1,TouchList:!1},h=o(d),v=0;v=e.length?(this._t=void 0,o(1)):o(0,"keys"==t?n:"values"==t?e[n]:[n,e[n]])}),"values"),i.Arguments=i.Array,r("keys"),r("values"),r("entries")},function(e,t,n){var r=n(10);r(r.S,"Object",{create:n(82)})},function(e,t,n){var r=n(10),o=n(82),i=n(80),a=n(27),l=n(29),c=n(31),u=n(180),s=(n(32).Reflect||{}).construct,f=c((function(){function e(){}return!(s((function(){}),[],e)instanceof e)})),p=!c((function(){s((function(){}))}));r(r.S+r.F*(f||p),"Reflect",{construct:function(e,t){i(e),a(t);var n=arguments.length<3?e:i(arguments[2]);if(p&&!f)return s(e,t,n);if(e==n){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var r=[null];return r.push.apply(r,t),new(u.apply(e,r))}var c=n.prototype,d=o(l(c)?c:Object.prototype),h=Function.apply.call(e,d,t);return l(h)?h:d}})},function(e,t,n){var r=n(10);r(r.S,"Object",{setPrototypeOf:n(176).set})},function(e,t,n){var r=n(54),o=n(69);n(250)("keys",(function(){return function(e){return o(r(e))}}))},function(e,t,n){"use strict";var r=n(10),o=n(130)(!1),i=[].indexOf,a=!!i&&1/[1].indexOf(1,-0)<0;r(r.P+r.F*(a||!n(71)(i)),"Array",{indexOf:function(e){return a?i.apply(this,arguments)||0:o(this,e,arguments[1])}})},function(e,t,n){var r=n(26),o=n(264);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(10);r(r.S+r.F,"Object",{assign:n(181)})},function(e,t,n){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var n=function(e,t){var n=e[1]||"",r=e[3];if(!r)return n;if(t&&"function"==typeof btoa){var o=(a=r,l=btoa(unescape(encodeURIComponent(JSON.stringify(a)))),c="sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(l),"/*# ".concat(c," */")),i=r.sources.map((function(e){return"/*# sourceURL=".concat(r.sourceRoot||"").concat(e," */")}));return[n].concat(i).concat([o]).join("\n")}var a,l,c;return[n].join("\n")}(t,e);return t[2]?"@media ".concat(t[2]," {").concat(n,"}"):n})).join("")},t.i=function(e,n,r){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(r)for(var i=0;i=t.length?{value:void 0,done:!0}:(e=r(t,n),this._i+=e.length,{value:e,done:!1})}))},function(e,t,n){var r=n(35),o=n(28),i=n(96),a=n(73),l=n(74),c=function(e,t,n){var u,s,f,p=e&c.F,d=e&c.G,h=e&c.S,v=e&c.P,g=e&c.B,m=e&c.W,b=d?o:o[t]||(o[t]={}),y=b.prototype,_=d?r:h?r[t]:(r[t]||{}).prototype;for(u in d&&(n=t),n)(s=!p&&_&&void 0!==_[u])&&l(b,u)||(f=s?_[u]:n[u],b[u]=d&&"function"!=typeof _[u]?n[u]:g&&s?i(f,r):m&&_[u]==f?function(e){var t=function(t,n,r){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,r)}return e.apply(this,arguments)};return t.prototype=e.prototype,t}(f):v&&"function"==typeof f?i(Function.call,f):f,v&&((b.virtual||(b.virtual={}))[u]=f,e&c.R&&y&&!y[u]&&a(y,u,f)))};c.F=1,c.G=2,c.S=4,c.P=8,c.B=16,c.W=32,c.U=64,c.R=128,e.exports=c},function(e,t,n){var r=n(26),o=n(330);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(110),o=Math.min;e.exports=function(e){return e>0?o(r(e),9007199254740991):0}},function(e,t,n){var r=n(70);e.exports=function(e){return Object(r(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(1);r(r.P+r.F*!n(71)([].map,!0),"Array",{map:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(64);e.exports=function(e){if(!r(e))throw TypeError(e+" is not an object!");return e}},function(e,t,n){e.exports=!n(84)((function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a}))},function(e,t,n){"use strict";var r=n(79),o=n(10),i=n(54),a=n(185),l=n(186),c=n(53),u=n(170),s=n(187);o(o.S+o.F*!n(188)((function(e){Array.from(e)})),"Array",{from:function(e){var t,n,o,f,p=i(e),d="function"==typeof this?this:Array,h=arguments.length,v=h>1?arguments[1]:void 0,g=void 0!==v,m=0,b=s(p);if(g&&(v=r(v,h>2?arguments[2]:void 0,2)),null==b||d==Array&&l(b))for(n=new d(t=c(p.length));t>m;m++)u(n,m,g?v(p[m],m):p[m]);else for(f=b.call(p),n=new d;!(o=f.next()).done;m++)u(n,m,g?a(f,v,[o.value,m],!0):o.value);return n.length=m,n}})},function(e,t,n){var r=n(39),o=n(89);e.exports=n(30)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var r=n(109),o=n(70);e.exports=function(e){return r(o(e))}},function(e,t,n){"use strict";var r=n(10),o=n(62)(0),i=n(71)([].forEach,!0);r(r.P+r.F*!i,"Array",{forEach:function(e){return o(this,e,arguments[1])}})},function(e,t,n){var r=n(79),o=n(109),i=n(54),a=n(53),l=n(257);e.exports=function(e,t){var n=1==e,c=2==e,u=3==e,s=4==e,f=6==e,p=5==e||f,d=t||l;return function(t,l,h){for(var v,g,m=i(t),b=o(m),y=r(l,h,3),_=a(b.length),w=0,x=n?d(t,_):c?d(t,0):void 0;_>w;w++)if((p||w in b)&&(g=y(v=b[w],w,m),e))if(n)x[w]=g;else if(g)switch(e){case 3:return!0;case 5:return v;case 6:return w;case 2:x.push(v)}else if(s)return!1;return f?-1:u||s?s:x}}},function(e,t,n){var r=n(56),o=n(196),i=n(147),a=Object.defineProperty;t.f=n(57)?Object.defineProperty:function(e,t,n){if(r(e),t=i(t,!0),r(n),o)try{return a(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){e.exports={default:n(280),__esModule:!0}},function(e,t,n){"use strict";t.__esModule=!0;var r=a(n(302)),o=a(n(306)),i=a(n(201));function a(e){return e&&e.__esModule?e:{default:e}}t.default=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+(void 0===t?"undefined":(0,i.default)(t)));e.prototype=(0,o.default)(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(r.default?(0,r.default)(e,t):e.__proto__=t)}},function(e,t,n){var r=n(26),o=n(333);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(26),o=n(374);"string"==typeof(o=o.__esModule?o.default:o)&&(o=[[e.i,o,""]]);var i={insert:"head",singleton:!1};r(o,i);e.exports=o.locals||{}},function(e,t,n){var r=n(169),o=n(132);e.exports=Object.keys||function(e){return r(e,o)}},function(e,t){e.exports=function(e){if(null==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){"use strict";var r=n(31);e.exports=function(e,t){return!!e&&r((function(){t?e.call(null,(function(){}),1):e.call(null)}))}},function(e,t,n){"use strict";var r=n(27),o=n(54),i=n(53),a=n(110),l=n(138),c=n(139),u=Math.max,s=Math.min,f=Math.floor,p=/\$([$&`']|\d\d?|<[^>]*>)/g,d=/\$([$&`']|\d\d?)/g;n(140)("replace",2,(function(e,t,n,h){return[function(r,o){var i=e(this),a=null==r?void 0:r[t];return void 0!==a?a.call(r,i,o):n.call(String(i),r,o)},function(e,t){var o=h(n,e,this,t);if(o.done)return o.value;var f=r(e),p=String(this),d="function"==typeof t;d||(t=String(t));var g=f.global;if(g){var m=f.unicode;f.lastIndex=0}for(var b=[];;){var y=c(f,p);if(null===y)break;if(b.push(y),!g)break;""===String(y[0])&&(f.lastIndex=l(p,i(f.lastIndex),m))}for(var _,w="",x=0,S=0;S=x&&(w+=p.slice(x,O)+I,x=O+k.length)}return w+p.slice(x)}];function v(e,t,r,i,a,l){var c=r+e.length,u=i.length,s=d;return void 0!==a&&(a=o(a),s=p),n.call(l,s,(function(n,o){var l;switch(o.charAt(0)){case"$":return"$";case"&":return e;case"`":return t.slice(0,r);case"'":return t.slice(c);case"<":l=a[o.slice(1,-1)];break;default:var s=+o;if(0===s)return n;if(s>u){var p=f(s/10);return 0===p?n:p<=u?void 0===i[p-1]?o.charAt(1):i[p-1]+o.charAt(1):n}l=i[s-1]}return void 0===l?"":l}))}}))},function(e,t,n){var r=n(63),o=n(118);e.exports=n(57)?function(e,t,n){return r.f(e,t,o(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var r=n(198),o=n(148);e.exports=function(e){return r(o(e))}},function(e,t,n){(function(t){function n(e){try{if(!t.localStorage)return!1}catch(e){return!1}var n=t.localStorage[e];return null!=n&&"true"===String(n).toLowerCase()}e.exports=function(e,t){if(n("noDeprecation"))return e;var r=!1;return function(){if(!r){if(n("throwDeprecation"))throw new Error(t);n("traceDeprecation")?console.trace(t):console.warn(t),r=!0}return e.apply(this,arguments)}}}).call(this,n(105))},function(e,t,n){var r=n(10);r(r.S+r.F*!n(30),"Object",{defineProperties:n(168)})},function(e,t){var n=e.exports={version:"2.6.11"};"number"==typeof __e&&(__e=n)},function(e,t,n){var r=n(80);e.exports=function(e,t,n){if(r(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,r){return e.call(t,n,r)};case 3:return function(n,r,o){return e.call(t,n,r,o)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var r=n(10),o=n(247),i=n(60),a=n(92),l=n(170);r(r.S,"Object",{getOwnPropertyDescriptors:function(e){for(var t,n,r=i(e),c=a.f,u=o(r),s={},f=0;u.length>f;)void 0!==(n=c(r,t=u[f++]))&&l(s,t,n);return s}})},function(e,t,n){var r=n(27),o=n(168),i=n(132),a=n(131)("IE_PROTO"),l=function(){},c=function(){var e,t=n(167)("iframe"),r=i.length;for(t.style.display="none",n(249).appendChild(t),t.src="javascript:",(e=t.contentWindow.document).open(),e.write("
+
+ + +
+
+
+
+
+
+ +
+

bind

+
+
+ +
+
open suspend fun <B> Cont<R, B>.bind(): B
open suspend fun <B> Either<R, B>.bind(): B
open suspend fun <B> Validated<R, B>.bind(): B
open suspend fun <B> Result<B>.bind(transform: (Throwable) -> R): B
open suspend fun <B> Option<B>.bind(shift: () -> R): B
+
+
+
+ +
+