diff --git a/.github/unused_workflows/publish.yml b/.github/unused_workflows/publish.yml new file mode 100644 index 00000000000..5c7aa999eb9 --- /dev/null +++ b/.github/unused_workflows/publish.yml @@ -0,0 +1,161 @@ +name: "Publish all libs, Arrow-stack and Docs" + +on: + push: + tags: + - '**' + +env: + BASEDIR: ${{github.workspace}}/arrow-libs + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + SONATYPE_USER: ${{ secrets.SONATYPE_USER }} + SONATYPE_PWD: ${{ secrets.SONATYPE_PWD }} + ORG_GRADLE_PROJECT_signingKey: ${{ secrets.ORG_GRADLE_PROJECT_signingKey }} + ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingPassword }} + OSS_USER: '${{ secrets.OSS_USER }}' + OSS_TOKEN: '${{ secrets.OSS_TOKEN }}' + OSS_STAGING_PROFILE_ID: '${{ secrets.OSS_STAGING_PROFILE_ID }}' + SIGNING_KEY_NAME: '${{ secrets.SIGNING_KEY_NAME }}' + SIGNING_KEY_ID: '${{ secrets.SIGNING_KEY_ID }}' + SIGNING_KEY_PASSPHRASE: '${{ secrets.SIGNING_KEY_PASSPHRASE }}' + SIGNING_KEY: '${{ secrets.SIGNING_KEY }}' + GRADLE_PUBLISH_KEY: '${{ secrets.GRADLE_PUBLISH_KEY }}' + GRADLE_PUBLISH_SECRET: '${{ secrets.GRADLE_PUBLISH_SECRET }}' + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_CLOUDFRONT_ID: ${{ secrets.AWS_CLOUDFRONT_ID }} + AWS_DEFAULT_REGION: eu-west-1 + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + JEKYLL_ENV: production + S3_BUCKET: ${{ secrets.S3_BUCKET }} + +jobs: + publish: + timeout-minutes: 90 + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 11 + + - name: assemble + uses: gradle/gradle-build-action@v2 + with: + arguments: assemble -Pkotlin.mpp.enableCompatibilityMetadataVariant=true + + - name: Get Arrow version + id: version + run: echo "::set-output name=arrow::$(head -n 1 build/semver/version.txt)" + + - name: Upload reports + if: failure() + uses: actions/upload-artifact@v3 + with: + name: 'reports-${{ matrix.os }}' + path: '**/build/reports/**' + + - name: Publish alpha/beta/rc version + uses: gradle/gradle-build-action@v2 + if: | + contains(steps.version.outputs.arrow, 'alpha') || + contains(steps.version.outputs.arrow, 'beta') || + contains(steps.version.outputs.arrow, 'rc') + with: + arguments: -Pkotlin.mpp.enableCompatibilityMetadataVariant=true publishToSonatype closeAndReleaseSonatypeStagingRepository + + - name: Publish final version + uses: gradle/gradle-build-action@v2 + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + with: + arguments: -Pkotlin.mpp.enableCompatibilityMetadataVariant=true publishToSonatype closeSonatypeStagingRepository + + - name: Prepare environment + working-directory: arrow-site + run: | + mkdir $BASEDIR/logs + brew install tree + bundle config set --local path 'vendor/bundle' + bundle install --gemfile Gemfile + + - name: Create API doc + uses: gradle/gradle-build-action@v2 + with: + arguments: -Pkotlin.mpp.enableCompatibilityMetadataVariant=true dokkaGfm + + - name: Build release directory (/docs) + working-directory: arrow-site + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + run: | + bundle exec jekyll build -b docs -s docs + tree _site > $BASEDIR/logs/content_docs-${{ steps.version.outputs.arrow }}.log + + - name: Publish documentation (/docs) + working-directory: arrow-site + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + run: | + echo ">>> Latest release" >> $BASEDIR/logs/aws_sync.log + ${GITHUB_WORKSPACE}/.github/scripts/sync-docs-with-aws.sh + + - name: Build release directory (/docs/) + working-directory: arrow-site + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + run: | + bundle exec jekyll build -b docs/${{ steps.version.outputs.arrow }} -s docs + tree _site > $BASEDIR/logs/content_docs-${{ steps.version.outputs.arrow }}.log + + - name: Publish release directory (/docs/) + working-directory: arrow-site + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + run: | + aws s3 sync _site s3://$S3_BUCKET/docs/${{ steps.version.outputs.arrow }} --delete --exclude "/CNAME" --exclude "/code/*" --exclude "/index.html" --exclude "/redirects.json" >> $BASEDIR/logs/aws_sync.log + + - name: Build latest version (/docs/next) + working-directory: arrow-site + run: | + bundle exec jekyll build -b docs/next -s docs + tree _site > $BASEDIR/logs/content_docs-next.log + + - name: Publish latest version (/docs/next) + working-directory: arrow-site + run: | + aws s3 sync _site s3://$S3_BUCKET/docs/next --delete --exclude "/CNAME" --exclude "/code/*" --exclude "/index.html" --exclude "/redirects.json" >> $BASEDIR/logs/aws_sync.log + + - name: Publish sitemap.xml + if: | + !contains(steps.version.outputs.arrow, 'alpha') && + !contains(steps.version.outputs.arrow, 'beta') && + !contains(steps.version.outputs.arrow, 'rc') + run: | + ${GITHUB_WORKSPACE}/.github/scripts/create-sitemap.sh > sitemap.xml + aws s3 cp sitemap.xml s3://$S3_BUCKET/sitemap.xml >> $BASEDIR/logs/aws_sync.log + + - name: Invalidate CloudFront cache + run: aws cloudfront create-invalidation --distribution-id $AWS_CLOUDFRONT_ID --paths "/*" + + - name: List S3 + run: aws s3 ls s3://$S3_BUCKET --recursive --summarize > $BASEDIR/logs/site-content.log + + - uses: actions/upload-artifact@v3 + with: + name: logs + path: arrow-libs/logs. diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 095790b72d8..f4ec030fb4d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,13 +1,17 @@ name: "Publish all libs, Arrow-stack and Docs" on: - workflow_dispatch: - branches: [main] - inputs: - version: - description: 'Version' - required: true - type: string + push: + branch: + - 'arrow-2' +#on: +# workflow_dispatch: +# branches: [main] +# inputs: +# version: +# description: 'Version' +# required: true +# type: string env: BASEDIR: ${{github.workspace}}/arrow-libs @@ -50,5 +54,5 @@ jobs: name: 'reports-${{ matrix.os }}' path: '**/build/reports/**' - - name: Publish final version + - name: Publish next major SNAPSHOT version run: ./gradlew -Pversion=${{ inputs.version }} publishToSonatype closeSonatypeStagingRepository diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 62de62a8544..a80b6fcb494 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -265,7 +265,7 @@ jobs: js: runs-on: ubuntu-latest - timeout-minutes: 60 + timeout-minutes: 30 steps: - uses: actions/checkout@v4 @@ -327,32 +327,32 @@ jobs: name: 'reports-linux' path: '**/build/reports/**' -# wasm: -# runs-on: ubuntu-latest -# timeout-minutes: 60 -# -# steps: -# - uses: actions/checkout@v4 -# with: -# fetch-depth: 0 -# -# - name: Set up Java -# uses: actions/setup-java@v4 -# with: -# distribution: 'temurin' -# java-version: 17 -# -# - name: Setup Gradle -# uses: gradle/actions/setup-gradle@v3 -# with: -# cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/arrow-2' }} -# -# - name: Compile WebAssembly -# run: ./gradlew compileKotlinWasmJs --scan -# -# - name: Upload reports -# if: failure() -# uses: actions/upload-artifact@v4 -# with: -# name: 'reports-wasm' -# path: '**/build/reports/**' + wasm: + runs-on: ubuntu-latest + timeout-minutes: 60 + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 17 + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + with: + cache-read-only: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/arrow-2' }} + + - name: Compile WebAssembly + run: ./gradlew wasmJsTest -Penable_wasm=true --scan + + - name: Upload reports + if: failure() + uses: actions/upload-artifact@v4 + with: + name: 'reports-wasm' + path: '**/build/reports/**' diff --git a/arrow-libs/core/arrow-atomic/build.gradle.kts b/arrow-libs/core/arrow-atomic/build.gradle.kts index 76f8226ae19..3db0034dcf0 100644 --- a/arrow-libs/core/arrow-atomic/build.gradle.kts +++ b/arrow-libs/core/arrow-atomic/build.gradle.kts @@ -1,5 +1,7 @@ @file:Suppress("DSL_SCOPE_VIOLATION") +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + plugins { id(libs.plugins.kotlin.multiplatform.get().pluginId) alias(libs.plugins.arrowGradleConfig.kotlin) @@ -34,9 +36,9 @@ kotlin { dependencies { implementation(projects.arrowFxCoroutines) implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) - implementation(libs.coroutines.test) } } } @@ -49,3 +51,11 @@ kotlin { } } } + +tasks.withType().configureEach { + kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes" +} + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Effect.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Effect.kt deleted file mode 100644 index 798141bbe30..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Effect.kt +++ /dev/null @@ -1,27 +0,0 @@ -package arrow.continuations - -import arrow.continuations.generic.DelimitedScope -import arrow.continuations.generic.deprecateArrowContinuation - -@Deprecated(deprecateArrowContinuation) -public fun interface Effect { - public fun control(): DelimitedScope - - public companion object { - @Deprecated("$deprecateArrowContinuation Here one can use effect { } directly") - public suspend inline fun , F, A> suspended( - crossinline eff: (DelimitedScope) -> Eff, - crossinline just: (A) -> F, - crossinline f: suspend Eff.() -> A, - ): F = - Reset.suspended { just(f(eff(this))) } - - @Deprecated("$deprecateArrowContinuation Here one can use eagerEffect { } directly") - public inline fun , F, A> restricted( - crossinline eff: (DelimitedScope) -> Eff, - crossinline just: (A) -> F, - crossinline f: suspend Eff.() -> A, - ): F = - Reset.restricted { just(f(eff(this))) } - } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Reset.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Reset.kt deleted file mode 100644 index 8adfe743d3d..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/Reset.kt +++ /dev/null @@ -1,42 +0,0 @@ -package arrow.continuations - -import arrow.continuations.generic.ShortCircuit -import arrow.continuations.generic.ControlThrowable -import arrow.continuations.generic.DelimContScope -import arrow.continuations.generic.RestrictedScope -import arrow.continuations.generic.SuspendMonadContinuation -import arrow.continuations.generic.SuspendedScope -import arrow.continuations.generic.deprecateArrowContinuation -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn - -@PublishedApi -@Deprecated(deprecateArrowContinuation) -internal object Reset { - /** - * Allows for building suspending single-shot computation blocks. - * For short-circuiting, or shifting, a [ShortCircuit] [ControlThrowable] is used. - * This ensures that any concurrent nested scopes are correctly closed. - * - * The usage of `try { ... } catch(e: Throwable) { ... }` will catch the [ShortCircuit] error, - * and will lead to recover of short-circuiting. - * You should always prefer to catch the most specific exception class, or - * use `Either.catch`, `Raise.catch`, or `e.nonFatalOrThrow()` - * to ensure you're not catching `ShortCircuit`. - */ - @Deprecated(deprecateArrowContinuation) - public suspend fun suspended(block: suspend SuspendedScope.() -> A): A = - suspendCoroutineUninterceptedOrReturn { cont -> - SuspendMonadContinuation(cont, block) - .startCoroutineUninterceptedOrReturn() - } - - /** - * Allows for building eager single-shot computation blocks. - * For short-circuiting, or shifting, `@RestrictSuspension` state machine is used. - * This doesn't allow nesting of computation blocks, or foreign suspension. - */ - @Deprecated(deprecateArrowContinuation) - // TODO This should be @RestrictSuspension but that breaks because a superclass is not considered to be correct scope - fun restricted(block: suspend RestrictedScope.() -> A): A = - DelimContScope(block).invoke() -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/AtomicRef.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/AtomicRef.kt deleted file mode 100644 index 8b4c0433661..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/AtomicRef.kt +++ /dev/null @@ -1,57 +0,0 @@ -package arrow.continuations.generic - -@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("AtomicRef", "arrow.core.generic.AtomicRef")) -public expect class AtomicRef(initialValue: V) { - public fun get(): V - public fun set(value: V) - public fun getAndSet(value: V): V - - /** - * Compare current value with expected and set to new if they're the same. Note, 'compare' is checking - * the actual object id, not 'equals'. - */ - public fun compareAndSet(expected: V, new: V): Boolean -} - -/** - * Infinite loop that reads this atomic variable and performs the specified [action] on its value. - */ -@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("loop(action)", "arrow.core.generic.loop")) -public inline fun AtomicRef.loop(action: (V) -> Unit): Nothing { - while (true) { - action(get()) - } -} - -@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("update(function)", "arrow.core.generic.update")) -public inline fun AtomicRef.update(function: (V) -> V) { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return - } -} - -/** - * Updates variable atomically using the specified [function] of its value and returns its old value. - */ -@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("getAndUpdate(function)", "arrow.core.generic.getAndUpdate")) -public inline fun AtomicRef.getAndUpdate(function: (V) -> V): V { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return cur - } -} - -/** - * Updates variable atomically using the specified [function] of its value and returns its new value. - */ -@Deprecated("$deprecateArrowContinuation The AtomicRef APIs have been moved to arrow.core.generic", ReplaceWith("updateAndGet", "arrow.core.generic.updateAndGet")) -public inline fun AtomicRef.updateAndGet(function: (V) -> V): V { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return upd - } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ControlThrowable.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ControlThrowable.kt deleted file mode 100644 index 62420ca41df..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ControlThrowable.kt +++ /dev/null @@ -1,13 +0,0 @@ -package arrow.continuations.generic - -/** - * A [Throwable] class intended for control flow. - * Instance of [ControlThrowable] should **not** be caught, - * and `arrow.core.NonFatal` does not catch this [Throwable]. - * By extension, `Either.catch` and `Raise.catch` also don't catch [ControlThrowable]. - */ -@Deprecated(deprecateArrowContinuation) -public expect open class ControlThrowable() : Throwable - -@PublishedApi internal const val deprecateArrowContinuation: String = - "arrow.continuation is being discontinued and will be removed in the next version in favor of the Effect/ EagerEffect Runtime. If you depend on low-level APIs as in arrow.continuation, feel free to write us in the Kotlin Slack channel for guidance." diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimContScope.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimContScope.kt deleted file mode 100644 index 4ce2b6bea2a..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimContScope.kt +++ /dev/null @@ -1,133 +0,0 @@ -package arrow.continuations.generic - -import kotlin.coroutines.Continuation -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn -import kotlin.coroutines.resume - -/** - * Implements delimited continuations with with no multi shot support (apart from shiftCPS which trivially supports it). - * - * For a version that simulates multishot (albeit with drawbacks) see [MultiShotDelimContScope]. - * For a version that allows nesting [reset] and calling parent scopes inside inner scopes see [NestedDelimContScope]. - * - * The basic concept here is appending callbacks and polling for a result. - * Every shift is evaluated until it either finishes (short-circuit) or suspends (called continuation). When it suspends its - * continuation is appended to a list waiting to be invoked with the final result of the block. - * When running a function we jump back and forth between the main function and every function inside shift via their continuations. - */ -internal open class DelimContScope(private val f: suspend RestrictedScope.() -> R) : RestrictedScope { - - /** - * Variable used for polling the result after suspension happened. - */ - private var resultVar: Any? = EMPTY_VALUE - - /** - * Variable for the next shift block to (partially) run, if it is empty that usually means we are done. - */ - private var nextShift: (suspend () -> R)? = null - - /** - * "Callbacks"/partially evaluated shift blocks which now wait for the final result - */ - // TODO This can be append only, but needs fast reversed access - private val shiftFnContinuations = mutableListOf>() - - /** - * Small wrapper that handles invoking the correct continuations and appending continuations from shift blocks - */ - public data class SingleShotCont( - private val continuation: Continuation, - private val shiftFnContinuations: MutableList> - ) : DelimitedContinuation { - public override suspend fun invoke(a: A): R = suspendCoroutineUninterceptedOrReturn { resumeShift -> - shiftFnContinuations.add(resumeShift) - continuation.resume(a) - COROUTINE_SUSPENDED - } - } - - /** - * Wrapper that handles invoking manually cps transformed continuations - */ - public data class CPSCont( - private val runFunc: suspend DelimitedScope.(A) -> R - ) : DelimitedContinuation { - public override suspend fun invoke(a: A): R = DelimContScope { runFunc(a) }.invoke() - } - - /** - * Captures the continuation and set [f] with the continuation to be executed next by the runloop. - */ - public override suspend fun shift(f: suspend RestrictedScope.(DelimitedContinuation) -> R): A = - suspendCoroutineUninterceptedOrReturn { continueMain -> - val delCont = SingleShotCont(continueMain, shiftFnContinuations) - require(nextShift == null) - nextShift = suspend { this.f(delCont) } - COROUTINE_SUSPENDED - } - - /** - * Same as [shift] except we never resume execution because we only continue in [c]. - */ - public suspend fun shiftCPS(f: suspend (DelimitedContinuation) -> R, c: suspend DelimitedScope.(A) -> B): Nothing = - suspendCoroutineUninterceptedOrReturn { - require(nextShift == null) - nextShift = suspend { f(CPSCont(c)) } - COROUTINE_SUSPENDED - } - - /** - * Unsafe if [f] calls [shift] on this scope! Use [NestedDelimContScope] instead if this is a problem. - */ - fun reset(f: suspend DelimitedScope.() -> A): A = - DelimContScope(f).invoke() - - @Suppress("UNCHECKED_CAST") - fun invoke(): R { - f.startCoroutineUninterceptedOrReturn( - this, - Continuation(EmptyCoroutineContext) { result -> - resultVar = result.getOrThrow() - } - ).let { - if (it == COROUTINE_SUSPENDED) { - // we have a call to shift so we must start execution the blocks there - while (true) { - if (resultVar === EMPTY_VALUE) { - val nextShiftFn = requireNotNull(nextShift) { "No further work to do but also no result!" } - nextShift = null - nextShiftFn.startCoroutineUninterceptedOrReturn( - Continuation(EmptyCoroutineContext) { result -> - resultVar = result.getOrThrow() - } - ).let { nextRes -> - // If we suspended here we can just continue to loop because we should now have a new function to run - // If we did not suspend we short-circuited and are thus done with looping - if (nextRes != COROUTINE_SUSPENDED) resultVar = nextRes as R - } - // Break out of the infinite loop if we have a result - } else return@let - } - } - // we can return directly if we never suspended/called shift - else return@invoke it as R - } - require(resultVar !== EMPTY_VALUE) - // We need to finish the partially evaluated shift blocks by passing them our result. - // This will update the result via the continuations that now finish up - for (c in shiftFnContinuations.asReversed()) c.resume(resultVar as R) - // Return the final result - return resultVar as R - } -} - -@Suppress("ClassName") -internal object EMPTY_VALUE { - @Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") - public inline fun unbox(value: Any?): T = - if (value === this) null as T else value as T -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimitedCont.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimitedCont.kt deleted file mode 100644 index a84f969fcd9..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/DelimitedCont.kt +++ /dev/null @@ -1,34 +0,0 @@ -package arrow.continuations.generic - -/** - * Base interface for a continuation - */ -@Deprecated(deprecateArrowContinuation) -public interface DelimitedContinuation { - public suspend operator fun invoke(a: A): R -} - -/** - * Base interface for our scope. - */ -@Deprecated(deprecateArrowContinuation) -public interface DelimitedScope { - - /** - * Exit the [DelimitedScope] with [R] - */ - public suspend fun shift(r: R): A -} - -@Deprecated(deprecateArrowContinuation) -public interface RestrictedScope : DelimitedScope { - /** - * Capture the continuation and pass it to [f]. - */ - public suspend fun shift(f: suspend RestrictedScope.(DelimitedContinuation) -> R): A - - public override suspend fun shift(r: R): A = shift { r } -} - -@Deprecated(deprecateArrowContinuation) -public interface SuspendedScope : DelimitedScope diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/MultiShotDelimCont.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/MultiShotDelimCont.kt deleted file mode 100644 index 32a8824b8f8..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/MultiShotDelimCont.kt +++ /dev/null @@ -1,140 +0,0 @@ -package arrow.continuations.generic - -import kotlin.coroutines.Continuation -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn -import kotlin.coroutines.resume -import kotlin.coroutines.suspendCoroutine - -/** - * (Simulated) Multishot capable delimited control scope - * - * This has several drawbacks: - * - f will rerun completely on multishot and only the results of [shift] are cached so any sideeffects outside of - * [shift] will rerun! - * - This accumulates all results of [shift] (every argument passed when invoking the continuation) so on long running computations - * this may keep quite a bit of memory - * - If the pure part before a multishot is expensive the multishot itself will have to rerun that, which makes it somewhat slow - * - This is terribly hard to implement properly with nested scopes (which this one does not support) - * - * As per usual understanding of [DelimContScope] is required as I will only be commenting differences for now. - */ -internal open class MultiShotDelimContScope(val f: suspend RestrictedScope.() -> R) : RestrictedScope { - - // TODO Since runs blocking these don't need to be atomic - private val resultVar = AtomicRef(null) - private val nextShift = AtomicRef<(suspend RestrictedScope.() -> R)?>(null) - - // TODO This can be append only and needs fast reversed access - private val shiftFnContinuations = mutableListOf>() - - /** - * Keep the arguments passed to [DelimitedContinuation.invoke] to be able to replay the scope if necessary - */ - // TODO This can be append only and needs fast random access and slicing - internal open val stack = mutableListOf() - - /** - * Our continuation now includes the function [f] to rerun on multishot, the current live (single-shot) continuation, - * the current stack and the offset from that stack when this is created which is used to know when to resume normal - * execution again on a replay. - */ - public class MultiShotCont( - liveContinuation: Continuation, - private val f: suspend RestrictedScope.() -> R, - private val stack: MutableList, - private val shiftFnContinuations: MutableList> - ) : DelimitedContinuation { - // To make sure the continuation is only invoked once we put it in a nullable atomic and only access it through getAndSet - private val liveContinuation = AtomicRef?>(liveContinuation) - private val stackOffset = stack.size - - public override suspend fun invoke(a: A): R = - when (val cont = liveContinuation.getAndSet(null)) { - // On multishot we replay with a prefilled stack from start to the point at which this object was created - // (when the shift block this runs in was first called) - null -> PrefilledDelimContScope((stack.subList(0, stackOffset).toList() + a).toMutableList(), f).invoke() - // on the first pass we operate like a normal delimited scope but we also save the argument to the stack before resuming - else -> suspendCoroutine { resumeShift -> - shiftFnContinuations.add(resumeShift) - stack.add(a) - cont.resume(a) - } - } - } - - public data class CPSCont( - private val runFunc: suspend DelimitedScope.(A) -> R - ) : DelimitedContinuation { - public override suspend fun invoke(a: A): R = DelimContScope { runFunc(a) }.invoke() - } - - public override suspend fun shift(func: suspend RestrictedScope.(DelimitedContinuation) -> R): A = - suspendCoroutineUninterceptedOrReturn { continueMain -> - val c = MultiShotCont(continueMain, f, stack, shiftFnContinuations) - val s: suspend RestrictedScope.() -> R = { this.func(c) } - require(nextShift.compareAndSet(null, s)) - COROUTINE_SUSPENDED - } - - public suspend fun shiftCPS(func: suspend DelimitedScope.(DelimitedContinuation) -> R, c: suspend DelimitedScope.(A) -> B): Nothing = - suspendCoroutine { - val s: suspend DelimitedScope.() -> R = { func(CPSCont(c)) } - require(nextShift.compareAndSet(null, s)) - } - - // This assumes RestrictSuspension or at least assumes the user to never reference the parent scope in f. - public suspend fun reset(f: suspend DelimitedScope.() -> A): A = - MultiShotDelimContScope(f).invoke() - - fun invoke(): R { - f.startCoroutineUninterceptedOrReturn( - this, - Continuation(EmptyCoroutineContext) { result -> - resultVar.set(result.getOrThrow()) - } - ).let { - if (it == COROUTINE_SUSPENDED) { - resultVar.loop { mRes -> - if (mRes == null) { - val nextShiftFn = nextShift.getAndSet(null) - ?: throw IllegalStateException("No further work to do but also no result!") - nextShiftFn.startCoroutineUninterceptedOrReturn( - this, - Continuation(EmptyCoroutineContext) { result -> - resultVar.set(result.getOrThrow()) - } - ).let { - if (it != COROUTINE_SUSPENDED) resultVar.set(it as R) - } - } else return@let - } - } else return@invoke it as R - } - require(resultVar.get() != null) - for (c in shiftFnContinuations.asReversed()) c.resume(resultVar.get()!!) - return resultVar.get()!! - } - - public companion object { - internal fun reset(f: suspend RestrictedScope.() -> R): R = MultiShotDelimContScope(f).invoke() - } -} - -private class PrefilledDelimContScope( - override val stack: MutableList, - f: suspend RestrictedScope.() -> R -) : MultiShotDelimContScope(f) { - var depth = 0 - - // Here we first check if we still have values in our local stack and if so we use those first - // if not we delegate to the normal delimited control implementation - public override suspend fun shift(func: suspend RestrictedScope.(DelimitedContinuation) -> R): A = - if (stack.size > depth) stack[depth++] as A - else { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - super.shift(func).also { depth++ } - } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ShortCircuit.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ShortCircuit.kt deleted file mode 100644 index 66b2c445979..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/ShortCircuit.kt +++ /dev/null @@ -1,4 +0,0 @@ -package arrow.continuations.generic - -@Deprecated(deprecateArrowContinuation) -public class ShortCircuit internal constructor(internal val token: Token, public val raiseValue: Any?) : ControlThrowable() diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/SuspendingComputation.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/SuspendingComputation.kt deleted file mode 100644 index 88e8b5c13c5..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/SuspendingComputation.kt +++ /dev/null @@ -1,97 +0,0 @@ -package arrow.continuations.generic - -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.resumeWithException - -internal const val UNDECIDED = 0 -internal const val SUSPENDED = 1 - -@Suppress("UNCHECKED_CAST") -internal open class SuspendMonadContinuation( - private val parent: Continuation, - val f: suspend SuspendedScope.() -> R -) : Continuation, SuspendedScope { - - /** - * State is either - * 0 - UNDECIDED - * 1 - SUSPENDED - * Any? (3) `resumeWith` always stores it upon UNDECIDED, and `getResult` can atomically get it. - */ - private val _decision = AtomicRef(UNDECIDED) - private val token: Token = Token() - - override val context: CoroutineContext = parent.context - - override fun resumeWith(result: Result) { - _decision.loop { decision -> - when (decision) { - UNDECIDED -> { - val r: R? = result.fold({ it }) { EMPTY_VALUE.unbox(it.shiftedOrNull()) } - when { - r == null -> { - parent.resumeWithException(result.exceptionOrNull()!!) - return - } - _decision.compareAndSet(UNDECIDED, r) -> { - return - } - else -> Unit // loop again - } - } - else -> { // If not `UNDECIDED` then we need to pass result to `parent` - val res: Result = result.fold( - { Result.success(it) }, - { t -> - val x = t.shiftedOrNull() - if (x === EMPTY_VALUE) Result.failure(t) - else Result.success(EMPTY_VALUE.unbox(x)) - } - ) - parent.resumeWith(res) - return - } - } - } - } - - @PublishedApi // return the result - internal fun getResult(): Any? = - _decision.loop { decision -> - when (decision) { - UNDECIDED -> if (this._decision.compareAndSet(UNDECIDED, SUSPENDED)) return COROUTINE_SUSPENDED - else -> return decision - } - } - - // If ShortCircuit causes CancellationException, we also want to shift back to R - private tailrec fun Throwable.shortCircuitCause(): ShortCircuit? = - when (val cause = this.cause) { - null -> null - is ShortCircuit -> cause - else -> cause.shortCircuitCause() - } - - private fun Throwable.shiftedOrNull(): Any? { - val shortCircuit = if (this is ShortCircuit) this else shortCircuitCause() - return if (shortCircuit != null && shortCircuit.token === token) shortCircuit.raiseValue as R - else EMPTY_VALUE - } - - public override suspend fun shift(r: R): A = - throw ShortCircuit(token, r) - - fun startCoroutineUninterceptedOrReturn(): Any? = - try { - f.startCoroutineUninterceptedOrReturn(this, this)?.let { - if (it == COROUTINE_SUSPENDED) getResult() - else it - } - } catch (e: Throwable) { - val x = e.shiftedOrNull() - if (x === EMPTY_VALUE) throw e else x - } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/Token.kt b/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/Token.kt deleted file mode 100644 index 511f90b1fef..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonMain/kotlin/arrow/continuations/generic/Token.kt +++ /dev/null @@ -1,7 +0,0 @@ -package arrow.continuations.generic - -/** Represents a unique identifier using object equality. */ -@Deprecated(deprecateArrowContinuation) -internal class Token { - override fun toString(): String = "Token(${hashCode().toString(16)})" -} diff --git a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/Maybe.kt b/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/Maybe.kt deleted file mode 100644 index fa0b12cbede..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/Maybe.kt +++ /dev/null @@ -1,15 +0,0 @@ -package generic - -import arrow.continuations.Reset - -sealed class Maybe -data class Just(val a: A) : Maybe() -object None : Maybe() - -object maybeEff { // if you change the name to maybe it breaks the tests in 1.4.10 - inline fun restricted(crossinline c: suspend MaybeEffect<*>.() -> A): Maybe = - Reset.restricted { Just(c(MaybeEffect { this })) } - - suspend inline operator fun invoke(crossinline c: suspend MaybeEffect<*>.() -> A): Maybe = - Reset.suspended { Just(c(MaybeEffect { this })) } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/MaybeEffect.kt b/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/MaybeEffect.kt deleted file mode 100644 index c082f7f5bff..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/MaybeEffect.kt +++ /dev/null @@ -1,11 +0,0 @@ -package generic - -import arrow.continuations.Effect - -fun interface MaybeEffect : Effect> { - suspend fun Maybe.bind(): B = - when (this) { - is Just -> a - is None -> control().shift(None) - } -} diff --git a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/SuspendingComputationTest.kt b/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/SuspendingComputationTest.kt deleted file mode 100644 index 128a4f351e5..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/SuspendingComputationTest.kt +++ /dev/null @@ -1,221 +0,0 @@ -package arrow.continuations - -import arrow.core.Either -import arrow.core.computations.either -import arrow.core.Either.Right -import arrow.core.Either.Left -import arrow.core.Eval -import arrow.core.computations.ensureNotNull -import arrow.core.computations.eval -import arrow.core.left -import arrow.core.right -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -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 kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.suspendCancellableCoroutine -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 - -class SuspendingComputationTest : StringSpec({ - - "immediate values" { - either { - Right(1).bind() - } shouldBe Right(1) - } - - "suspended value" { - either { - Right(1).suspend().bind() - } shouldBe Right(1) - } - - "immediate short-circuit" { - either { - Left("hello").bind() - } shouldBe Left("hello") - } - - "suspended short-circuit" { - either { - Left("hello").suspend().bind() - } shouldBe Left("hello") - } - - "Rethrows immediate exceptions" { - val e = RuntimeException("test") - Either.catch { - either { - Right(1).bind() - Right(1).suspend().bind() - throw e - } - } shouldBe Left(e) - } - - "Rethrows suspended exceptions" { - val e = RuntimeException("test") - Either.catch { - either { - Right(1).bind() - Right(1).suspend().bind() - e.suspend() - } - } shouldBe Either.Left(e) - } - - "Can short-circuit immediately from nested blocks" { - either { - val x = eval { - Left("test").bind() - 5L - } - - println(x) - 1 - } shouldBe Left("test") - } - - "Can short-circuit suspended from nested blocks" { - either { - val x = eval { - Left("test").suspend().bind() - 5L - } - - println(x) - 1 - } shouldBe Left("test") - } - - "Can short-circuit immediately after suspending from nested blocks" { - either { - val x = eval { - Eval.Now(1L).suspend().bind() - Left("test").suspend().bind() - 5L - } - - println(x) - 1 - } shouldBe Left("test") - } - - "Can short-circuit suspended after suspending from nested blocks" { - either { - val x = eval { - Eval.Now(1L).suspend().bind() - Left("test").suspend().bind() - 5L - } - - println(x) - 1 - } shouldBe Left("test") - } - - "ensure null in either computation" { - checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, rValue, lValue -> - either { - ensure(predicate) { lValue } - rValue - } shouldBe if (predicate) rValue.right() else lValue.left() - } - } - - "ensureNotNull in either computation" { - fun square(i: Int): Int = i * i - - checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, lValue: String -> - val res = either { - val ii = i - ensureNotNull(ii) { lValue } - square(ii) // Smart-cast by contract - } - val expected = i?.let(::square)?.right() ?: lValue.left() - res shouldBe expected - } - } - - "Short-circuiting cancels KotlinX Coroutines" { - val scope = CoroutineScope(Dispatchers.Default) - val latch = CompletableDeferred() - val cancelled = CompletableDeferred() - - either { - val deferreds: List> = listOf( - scope.async { - completeOnCancellation(latch, cancelled) - 1 - }, - scope.async { - latch.await() - Left("hello").bind() - } - ) - - deferreds.awaitAll().sum() - } shouldBe Left("hello") - - cancelled.await() - } - - "Computation blocks run on parent context" { - val parentCtx = currentContext() - either { - currentContext() shouldBe parentCtx - } - } -}) - -suspend fun currentContext(): CoroutineContext = - kotlin.coroutines.coroutineContext - -suspend fun completeOnCancellation(latch: CompletableDeferred, cancelled: CompletableDeferred): Unit = - suspendCancellableCoroutine { cont -> - cont.invokeOnCancellation { - if (!cancelled.complete(Unit)) fail("cancelled latch was completed twice") - else Unit - } - - if (!latch.complete(Unit)) fail("latch was completed twice") - else Unit - } - -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 - } diff --git a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/TestSuite.kt b/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/TestSuite.kt deleted file mode 100644 index 12314a24a27..00000000000 --- a/arrow-libs/core/arrow-continuations/src/commonTest/kotlin/generic/TestSuite.kt +++ /dev/null @@ -1,24 +0,0 @@ -package generic - -import arrow.continuations.Reset -import arrow.continuations.generic.RestrictedScope -import arrow.core.Either -import arrow.core.Either.Left -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe - -class SingleShotContTestSuite : StringSpec({ - "yield a list (also verifies stacksafety)" { - Reset.restricted { - suspend fun RestrictedScope>.yield(a: A): Unit = shift { k -> listOf(a) + k(Unit) } - for (i in 0..10_000) yield(i) - emptyList() - } shouldBe (0..10_000).toList() - } - "short circuit" { - Reset.restricted> { - val no: Int = shift { Left("No thank you") } - throw IllegalStateException("This should not be executed") - } shouldBe Left("No thank you") - } -}) diff --git a/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/AtomicRef.kt b/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/AtomicRef.kt deleted file mode 100644 index 9b845acb0a9..00000000000 --- a/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/AtomicRef.kt +++ /dev/null @@ -1,31 +0,0 @@ -package arrow.continuations.generic - -@Deprecated(deprecateArrowContinuation) -public actual class AtomicRef actual constructor(initialValue: V) { - private var internalValue: V = initialValue - - /** - * Compare current value with expected and set to new if they're the same. Note, 'compare' is checking - * the actual object id, not 'equals'. - */ - public actual fun compareAndSet(expected: V, new: V): Boolean { - return if (expected === internalValue) { - internalValue = new - true - } else { - false - } - } - - public actual fun getAndSet(value: V): V { - val oldValue = internalValue - internalValue = value - return oldValue - } - - public actual fun get(): V = internalValue - - public actual fun set(value: V) { - internalValue = value - } -} diff --git a/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/ControlThrowable.kt b/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/ControlThrowable.kt deleted file mode 100644 index 3ba52914bac..00000000000 --- a/arrow-libs/core/arrow-continuations/src/jsMain/kotlin/arrow/continuations/generic/ControlThrowable.kt +++ /dev/null @@ -1,10 +0,0 @@ -package arrow.continuations.generic - -/** - * A [Throwable] class intended for control flow. - * Instance of [ControlThrowable] should **not** be caught, - * and `arrow.core.NonFatal` does not catch this [Throwable]. - * By extension, `Either.catch` and `Raise.catch` also don't catch [ControlThrowable]. - */ -@Deprecated(deprecateArrowContinuation) -public actual open class ControlThrowable : Throwable() diff --git a/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/AtomicRef.kt b/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/AtomicRef.kt deleted file mode 100644 index 2a6268230d7..00000000000 --- a/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/AtomicRef.kt +++ /dev/null @@ -1,8 +0,0 @@ -@file:JvmName("AtomicReferenceActual") - -package arrow.continuations.generic - -import java.util.concurrent.atomic.AtomicReference - -@Deprecated(deprecateArrowContinuation) -public actual typealias AtomicRef = AtomicReference diff --git a/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/ControlThrowable.kt b/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/ControlThrowable.kt deleted file mode 100644 index 31b7b028203..00000000000 --- a/arrow-libs/core/arrow-continuations/src/jvmMain/kotlin/arrow/continuations/generic/ControlThrowable.kt +++ /dev/null @@ -1,13 +0,0 @@ - -package arrow.continuations.generic - -/** - * A [Throwable] class intended for control flow. - * Instance of [ControlThrowable] should **not** be caught, - * and `arrow.core.NonFatal` does not catch this [Throwable]. - * By extension, `Either.catch` and `Raise.catch` also don't catch [ControlThrowable]. - */ -@Deprecated(deprecateArrowContinuation) -public actual open class ControlThrowable : Throwable() { - override fun fillInStackTrace(): Throwable = this -} diff --git a/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/AtomicRef.kt b/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/AtomicRef.kt deleted file mode 100644 index 9b3aaef946b..00000000000 --- a/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/AtomicRef.kt +++ /dev/null @@ -1,30 +0,0 @@ -package arrow.continuations.generic - -import kotlin.concurrent.AtomicReference -import kotlin.native.concurrent.freeze -import kotlin.native.concurrent.isFrozen - -@Deprecated(deprecateArrowContinuation) -public actual class AtomicRef actual constructor(initialValue: V) { - private val atom = AtomicReference(initialValue.freeze()) - public actual fun get(): V = atom.value - - public actual fun set(value: V) { - atom.value = value.freeze() - } - - public actual fun getAndSet(value: V): V { - if (atom.isFrozen) value.freeze() - while (true) { - val cur = atom.value - if (cur === value) return cur - if (atom.compareAndExchange(cur, value) === cur) return cur - } - } - - /** - * Compare current value with expected and set to new if they're the same. Note, 'compare' is checking - * the actual object id, not 'equals'. - */ - public actual fun compareAndSet(expected: V, new: V): Boolean = atom.compareAndSet(expected, new.freeze()) -} diff --git a/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/ControlThrowable.kt b/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/ControlThrowable.kt deleted file mode 100644 index 3ba52914bac..00000000000 --- a/arrow-libs/core/arrow-continuations/src/nativeMain/kotlin/arrow.continuations/generic/ControlThrowable.kt +++ /dev/null @@ -1,10 +0,0 @@ -package arrow.continuations.generic - -/** - * A [Throwable] class intended for control flow. - * Instance of [ControlThrowable] should **not** be caught, - * and `arrow.core.NonFatal` does not catch this [Throwable]. - * By extension, `Either.catch` and `Raise.catch` also don't catch [ControlThrowable]. - */ -@Deprecated(deprecateArrowContinuation) -public actual open class ControlThrowable : Throwable() diff --git a/arrow-libs/core/arrow-core-high-arity/api/arrow-core-high-arity.api b/arrow-libs/core/arrow-core-high-arity/api/arrow-core-high-arity.api index b2bf4d35316..c32fffb5af9 100644 --- a/arrow-libs/core/arrow-core-high-arity/api/arrow-core-high-arity.api +++ b/arrow-libs/core/arrow-core-high-arity/api/arrow-core-high-arity.api @@ -28,17 +28,17 @@ public final class arrow/core/MapKt { } public final class arrow/core/NonEmptyListKt { - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function21;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function20;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function19;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function18;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function17;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function16;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function15;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function14;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function13;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function12;)Larrow/core/NonEmptyList; - public static final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function11;)Larrow/core/NonEmptyList; + public static final fun zip-7nYrSoo (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function13;)Ljava/util/List; + public static final fun zip-CK6xqJ4 (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function19;)Ljava/util/List; + public static final fun zip-Iv5n_ic (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function20;)Ljava/util/List; + public static final fun zip-OSb0L0c (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function16;)Ljava/util/List; + public static final fun zip-RBKpiuQ (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function18;)Ljava/util/List; + public static final fun zip-SjcCNJ8 (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function17;)Ljava/util/List; + public static final fun zip-lQUGZdQ (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function15;)Ljava/util/List; + public static final fun zip-rJAuem8 (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function11;)Ljava/util/List; + public static final fun zip-wsSf-TI (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function21;)Ljava/util/List; + public static final fun zip-ydVqlZo (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function12;)Ljava/util/List; + public static final fun zip-zlBFgWs (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function14;)Ljava/util/List; } public final class arrow/core/SequenceKt { diff --git a/arrow-libs/core/arrow-core-high-arity/build.gradle.kts b/arrow-libs/core/arrow-core-high-arity/build.gradle.kts index 8d67619bc72..f074a6c5b2d 100644 --- a/arrow-libs/core/arrow-core-high-arity/build.gradle.kts +++ b/arrow-libs/core/arrow-core-high-arity/build.gradle.kts @@ -7,7 +7,6 @@ plugins { alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.spotless) } @@ -24,27 +23,9 @@ kotlin { commonMain { dependencies { api(projects.arrowCore) - api(projects.arrowAtomic) - api(projects.arrowContinuations) - api(projects.arrowAnnotations) api(libs.kotlin.stdlib) } } - - commonTest { - dependencies { - implementation(projects.arrowFxCoroutines) - implementation(libs.kotest.frameworkEngine) - implementation(libs.kotest.assertionsCore) - implementation(libs.kotest.property) - } - } - - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) - } - } } jvm { @@ -55,8 +36,3 @@ kotlin { } } } - -// enables context receivers for Jvm Tests -tasks.named("compileTestKotlinJvm") { - kotlinOptions.freeCompilerArgs += "-Xcontext-receivers" -} diff --git a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/MemoizationTest.kt b/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/MemoizationTest.kt deleted file mode 100644 index 5dc5ce2cbf3..00000000000 --- a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/MemoizationTest.kt +++ /dev/null @@ -1,3 +0,0 @@ -package arrow.core - -private fun consecSumResult(n: Int): Int = (n * (n + 1)) / 2 diff --git a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/OptionTest.kt b/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/OptionTest.kt deleted file mode 100755 index abdb08c5884..00000000000 --- a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/OptionTest.kt +++ /dev/null @@ -1,5 +0,0 @@ -package arrow.core - -// Utils - -private fun iterableOf(vararg elements: T): Iterable = Iterable { iterator { yieldAll(elements.toList()) } } diff --git a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/TupleTest.kt b/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/TupleTest.kt deleted file mode 100644 index 466e1314e96..00000000000 --- a/arrow-libs/core/arrow-core-high-arity/src/commonTest/kotlin/arrow/core/TupleTest.kt +++ /dev/null @@ -1,6 +0,0 @@ -package arrow.core - -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int - -private fun Arb.Companion.intOpenEnded() = Arb.int(Int.MIN_VALUE + 1, Int.MAX_VALUE - 1) diff --git a/arrow-libs/core/arrow-core-retrofit/build.gradle.kts b/arrow-libs/core/arrow-core-retrofit/build.gradle.kts index 12d6b301d0b..3b632457569 100644 --- a/arrow-libs/core/arrow-core-retrofit/build.gradle.kts +++ b/arrow-libs/core/arrow-core-retrofit/build.gradle.kts @@ -4,7 +4,6 @@ plugins { id(libs.plugins.kotlin.jvm.get().pluginId) alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) - alias(libs.plugins.kotlinx.serialization) // Needed for testing only alias(libs.plugins.kotlinx.kover) alias(libs.plugins.spotless) @@ -24,11 +23,11 @@ dependencies { compileOnly(libs.squareup.retrofit.lib) testImplementation(projects.arrowCore) - testImplementation(libs.kotest.frameworkEngine) + testImplementation(libs.kotlin.test) + testImplementation(libs.coroutines.test) testImplementation(libs.kotest.assertionsCore) testImplementation(libs.kotest.property) testCompileOnly(libs.kotlin.reflect) - testRuntimeOnly(libs.kotest.runnerJUnit5) testImplementation(libs.squareup.okhttpMockWebServer) testImplementation(libs.squareup.retrofit.converter.gson) testImplementation(libs.squareup.retrofit.converter.moshi) @@ -42,3 +41,7 @@ tasks.jar { attributes["Automatic-Module-Name"] = "arrow.core.retrofit" } } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/core/arrow-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/EitherCallAdapterFactory.kt b/arrow-libs/core/arrow-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/EitherCallAdapterFactory.kt index e6e7a910e13..b277e0ee2ad 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/EitherCallAdapterFactory.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/main/kotlin/arrow/retrofit/adapter/either/EitherCallAdapterFactory.kt @@ -110,7 +110,7 @@ public class EitherCallAdapterFactory : CallAdapter.Factory() { } } - private inline fun extractErrorAndReturnType(wrapperType: Type, returnType: ParameterizedType): Pair { + private fun extractErrorAndReturnType(wrapperType: Type, returnType: ParameterizedType): Pair { if (wrapperType !is ParameterizedType) { val name = parseTypeName(returnType) throw IllegalArgumentException( diff --git a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt index b6f8f902f18..1c481385ab6 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowEitherCallAdapterTest.kt @@ -5,20 +5,23 @@ import arrow.core.right import arrow.retrofit.adapter.mock.ErrorMock import arrow.retrofit.adapter.mock.ResponseMock import arrow.retrofit.adapter.retrofit.SuspendApiTestClient -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer import okhttp3.mockwebserver.SocketPolicy import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test -class ArrowEitherCallAdapterTest : StringSpec({ +class ArrowEitherCallAdapterTest { lateinit var server: MockWebServer lateinit var service: SuspendApiTestClient - beforeAny { + @BeforeTest fun initialize() { server = MockWebServer() server.start() service = Retrofit.Builder() @@ -29,9 +32,11 @@ class ArrowEitherCallAdapterTest : StringSpec({ .create(SuspendApiTestClient::class.java) } - afterAny { server.shutdown() } + @AfterTest fun shutdown() { + server.shutdown() + } - "should return ResponseMock for 200 with valid JSON" { + @Test fun shouldReturnResponseMockFor200WithValidJson() = runTest { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val body = service.getEither() @@ -39,7 +44,7 @@ class ArrowEitherCallAdapterTest : StringSpec({ body shouldBe ResponseMock("Arrow rocks").right() } - "should return Unit when service method returns Unit and null body received" { + @Test fun shouldReturnUnitWhenServiceMethodReturnsUnitAndNullBodyReceived() = runTest { server.enqueue(MockResponse().setResponseCode(204)) val body = service.postSomething("Sample string") @@ -47,7 +52,7 @@ class ArrowEitherCallAdapterTest : StringSpec({ body shouldBe Unit.right() } - "should return Unit when service method returns Unit and JSON body received" { + @Test fun shouldReturnUnitWhenServiceMethodReturnsUnitAndJsonBodyReceived() = runTest { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val body = service.postSomething("Sample string") @@ -55,7 +60,7 @@ class ArrowEitherCallAdapterTest : StringSpec({ body shouldBe Unit.right() } - "should return ErrorMock for 400 with valid JSON" { + @Test fun shouldReturnErrorMockFor400WithvalidJson() = runTest { server.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400)) val body = service.getEither() @@ -63,7 +68,7 @@ class ArrowEitherCallAdapterTest : StringSpec({ body shouldBe ErrorMock(666).left() } - "should throw for 200 with invalid JSON" { + @Test fun shouldThrowFor200WithInvalidJson() = runTest { server.enqueue(MockResponse().setBody("""not a valid JSON""")) val body = runCatching { service.getEither() } @@ -71,7 +76,7 @@ class ArrowEitherCallAdapterTest : StringSpec({ body.isFailure shouldBe true } - "should throw for 400 and invalid JSON" { + @Test fun shouldThrowFor400AndInvalidJson() = runTest { server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400)) val body = runCatching { service.getEither() } @@ -79,11 +84,11 @@ class ArrowEitherCallAdapterTest : StringSpec({ body.isFailure shouldBe true } - "should throw when server disconnects" { + @Test fun shouldThrowWhenServerDisconnects() = runTest { server.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AFTER_REQUEST }) val body = runCatching { service.getEither() } body.isFailure shouldBe true } -}) +} diff --git a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt index cc43ff7d359..43b4a184cfa 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/ArrowResponseEAdapterTest.kt @@ -5,20 +5,24 @@ import arrow.core.right import arrow.retrofit.adapter.mock.ErrorMock import arrow.retrofit.adapter.mock.ResponseMock import arrow.retrofit.adapter.retrofit.SuspendApiTestClient -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.MockWebServer import okhttp3.mockwebserver.SocketPolicy import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test -class ArrowResponseEAdapterTest : StringSpec({ +class ArrowResponseEAdapterTest { lateinit var server: MockWebServer lateinit var service: SuspendApiTestClient - beforeAny { + @BeforeTest + fun initialize() { server = MockWebServer() server.start() service = Retrofit.Builder() @@ -29,9 +33,13 @@ class ArrowResponseEAdapterTest : StringSpec({ .create(SuspendApiTestClient::class.java) } - afterAny { server.shutdown() } + @AfterTest + fun shutdown() { + server.shutdown() + } - "should return ResponseMock for 200 with valid JSON" { + @Test + fun shouldReturnResponseMockFor200WithValidJson() = runTest { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val responseE = service.getResponseE() @@ -42,7 +50,8 @@ class ArrowResponseEAdapterTest : StringSpec({ } } - "should return Unit when service method returns Unit and null body received" { + @Test + fun shouldReturnUnitWhenServiceMethodReturnsUnitAndNullBodyReceived() = runTest { server.enqueue(MockResponse().setResponseCode(204)) val responseE = service.postSomethingResponseE("Sample string") @@ -53,7 +62,8 @@ class ArrowResponseEAdapterTest : StringSpec({ } } - "should return Unit when service method returns Unit and JSON body received" { + @Test + fun shouldReturnUnitWhenServiceMethodReturnsUnitAndJsonBodyReceived() = runTest { server.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val responseE = service.postSomethingResponseE("Sample string") @@ -64,7 +74,8 @@ class ArrowResponseEAdapterTest : StringSpec({ } } - "should return ErrorMock for 400 with valid JSON" { + @Test + fun shouldReturnErrorMockFor400WithValidJson() = runTest { server.enqueue(MockResponse().setBody("""{"errorCode":42}""").setResponseCode(400)) val responseE = service.getResponseE() @@ -75,7 +86,8 @@ class ArrowResponseEAdapterTest : StringSpec({ } } - "should throw for 200 with invalid JSON" { + @Test + fun shouldThrowFor200WithInvalidJson() = runTest { server.enqueue(MockResponse().setBody("""not a valid JSON""")) val responseE = runCatching { service.getResponseE() } @@ -83,7 +95,8 @@ class ArrowResponseEAdapterTest : StringSpec({ responseE.isFailure shouldBe true } - "should throw for 400 and invalid JSON" { + @Test + fun shouldThrowFor400AndInvalidJson() = runTest { server.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400)) val responseE = runCatching { service.getResponseE() } @@ -91,11 +104,12 @@ class ArrowResponseEAdapterTest : StringSpec({ responseE.isFailure shouldBe true } - "should throw when server disconnects" { + @Test + fun shouldThrowWhenServerDisconnects() = runTest { server.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AFTER_REQUEST }) val responseE = runCatching { service.getResponseE() } responseE.isFailure shouldBe true } -}) +} diff --git a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapterTest.kt b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapterTest.kt index d6c3286512c..c70e17cbadc 100644 --- a/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapterTest.kt +++ b/arrow-libs/core/arrow-core-retrofit/src/test/kotlin/arrow/retrofit/adapter/either/networkhandling/NetworkEitherCallAdapterTest.kt @@ -7,11 +7,9 @@ import arrow.retrofit.adapter.either.EitherCallAdapterFactory import arrow.retrofit.adapter.mock.ResponseMock import com.squareup.moshi.Moshi import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import io.kotest.core.spec.style.StringSpec -import io.kotest.core.spec.style.stringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf -import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.coroutines.test.runTest import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient @@ -26,22 +24,17 @@ import retrofit2.converter.moshi.MoshiConverterFactory import java.net.SocketException import java.net.SocketTimeoutException import java.util.concurrent.TimeUnit +import kotlin.test.AfterTest +import kotlin.test.BeforeTest +import kotlin.test.Test -@ExperimentalSerializationApi -class NetworkEitherCallAdapterTestSuite : StringSpec({ - include(networkEitherCallAdapterTests(GsonConverterFactory.create())) - include(networkEitherCallAdapterTests(Json.asConverterFactory("application/json".toMediaType()))) - val moshi = Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build() - include(networkEitherCallAdapterTests(MoshiConverterFactory.create(moshi))) -}) - -private fun networkEitherCallAdapterTests( - jsonConverterFactory: Converter.Factory, -) = stringSpec { - var server: MockWebServer? = null - var service: CallErrorTestClient? = null - - beforeAny { +abstract class NetworkEitherCallAdapterTest( + private val jsonConverterFactory: Converter.Factory, +) { + private var server: MockWebServer? = null + private var service: CallErrorTestClient? = null + + open fun initialize() { server = MockWebServer() server!!.start() val client = OkHttpClient.Builder() @@ -55,9 +48,12 @@ private fun networkEitherCallAdapterTests( .build() .create(CallErrorTestClient::class.java) } - afterAny { server!!.shutdown() } - "should return ResponseMock for 200 with valid JSON" { + open fun shutdown() { + server!!.shutdown() + } + + open fun shouldReturn200ForValidJson() = runTest { server!!.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val body = service!!.getEither() @@ -65,7 +61,7 @@ private fun networkEitherCallAdapterTests( body shouldBe ResponseMock("Arrow rocks").right() } - "should return HttpError for 400" { + open fun shouldReturnHttpErrorFor404() = runTest { server!!.enqueue(MockResponse().setBody("""{"errorCode":666}""").setResponseCode(400)) val body = service!!.getEither() @@ -77,7 +73,7 @@ private fun networkEitherCallAdapterTests( ).left() } - "should return CallError for 200 with invalid JSON" { + open fun shouldReturnCallErrorFor200InvalidJson() = runTest { server!!.enqueue(MockResponse().setBody("""not a valid JSON""")) val body = service!!.getEither() @@ -86,7 +82,7 @@ private fun networkEitherCallAdapterTests( .value.shouldBeInstanceOf() } - "should return HttpError for 400 and invalid JSON" { + open fun shouldReturnHttpErrorFor404InvalidJson() = runTest { server!!.enqueue(MockResponse().setBody("""not a valid JSON""").setResponseCode(400)) val body = service!!.getEither() @@ -98,7 +94,7 @@ private fun networkEitherCallAdapterTests( ).left() } - "should return IOError when server disconnects" { + open fun shouldReturnIOErrorDisconnect() = runTest { server!!.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.DISCONNECT_AT_START }) val body = service!!.getEither() @@ -108,7 +104,7 @@ private fun networkEitherCallAdapterTests( .cause.shouldBeInstanceOf() } - "should return IOError when no response" { + open fun shouldReturnIOErrorNoResponse() = runTest { server!!.enqueue(MockResponse().apply { socketPolicy = SocketPolicy.NO_RESPONSE }) val body = service!!.getEither() @@ -118,7 +114,7 @@ private fun networkEitherCallAdapterTests( .cause.shouldBeInstanceOf() } - "should return Unit when service method returns Unit and null body received" { + open fun shouldReturnUnitForNullBody() = runTest { server!!.enqueue(MockResponse().setResponseCode(204)) val body = service!!.postSomething("Sample string") @@ -126,7 +122,7 @@ private fun networkEitherCallAdapterTests( body shouldBe Unit.right() } - "should return Unit when service method returns Unit and JSON body received" { + open fun shouldReturnUnitForUnitBody() = runTest { server!!.enqueue(MockResponse().setBody("""{"response":"Arrow rocks"}""")) val body = service!!.postSomething("Sample string") @@ -134,7 +130,7 @@ private fun networkEitherCallAdapterTests( body shouldBe Unit.right() } - "should return CallError when service method returns type other than Unit but null body received" { + open fun shouldReturnCallErrorWithUnitForNonNullBody() = runTest { server!!.enqueue(MockResponse()) val body = service!!.getEither() @@ -143,3 +139,87 @@ private fun networkEitherCallAdapterTests( .value.shouldBeInstanceOf() } } + +class NetworkEitherCallAdapterTestGson : NetworkEitherCallAdapterTest(GsonConverterFactory.create()) { + @BeforeTest override fun initialize() { + super.initialize() + } + + @AfterTest override fun shutdown() { + super.shutdown() + } + + @Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson() + + @Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404() + + @Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson() + + @Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson() + + @Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect() + + @Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse() + + @Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody() + + @Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody() + + @Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody() +} + +class NetworkEitherCallAdapterTestMoshi : NetworkEitherCallAdapterTest(MoshiConverterFactory.create(Moshi.Builder().addLast(KotlinJsonAdapterFactory()).build())) { + @BeforeTest override fun initialize() { + super.initialize() + } + + @AfterTest override fun shutdown() { + super.shutdown() + } + + @Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson() + + @Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404() + + @Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson() + + @Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson() + + @Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect() + + @Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse() + + @Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody() + + @Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody() + + @Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody() +} + +class NetworkEitherCallAdapterTestKotlinxSerialization : NetworkEitherCallAdapterTest(Json.asConverterFactory("application/json".toMediaType())) { + @BeforeTest override fun initialize() { + super.initialize() + } + + @AfterTest override fun shutdown() { + super.shutdown() + } + + @Test override fun shouldReturn200ForValidJson() = super.shouldReturn200ForValidJson() + + @Test override fun shouldReturnHttpErrorFor404() = super.shouldReturnHttpErrorFor404() + + @Test override fun shouldReturnCallErrorFor200InvalidJson() = super.shouldReturnCallErrorFor200InvalidJson() + + @Test override fun shouldReturnHttpErrorFor404InvalidJson() = super.shouldReturnHttpErrorFor404InvalidJson() + + @Test override fun shouldReturnIOErrorDisconnect() = super.shouldReturnIOErrorDisconnect() + + @Test override fun shouldReturnIOErrorNoResponse() = super.shouldReturnIOErrorNoResponse() + + @Test override fun shouldReturnUnitForNullBody() = super.shouldReturnUnitForNullBody() + + @Test override fun shouldReturnUnitForUnitBody() = super.shouldReturnUnitForUnitBody() + + @Test override fun shouldReturnCallErrorWithUnitForNonNullBody() = super.shouldReturnCallErrorWithUnitForNonNullBody() +} diff --git a/arrow-libs/core/arrow-core-serialization/api/arrow-core-serialization.api b/arrow-libs/core/arrow-core-serialization/api/arrow-core-serialization.api index bc822411c11..2471e2079cd 100644 --- a/arrow-libs/core/arrow-core-serialization/api/arrow-core-serialization.api +++ b/arrow-libs/core/arrow-core-serialization/api/arrow-core-serialization.api @@ -18,11 +18,11 @@ public final class arrow/core/serialization/IorSerializer : kotlinx/serializatio public final class arrow/core/serialization/NonEmptyListSerializer : kotlinx/serialization/KSerializer { public fun (Lkotlinx/serialization/KSerializer;)V - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Larrow/core/NonEmptyList; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize-0-xjo5U (Lkotlinx/serialization/encoding/Decoder;)Ljava/util/List; public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Larrow/core/NonEmptyList;)V public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize-EgRvm48 (Lkotlinx/serialization/encoding/Encoder;Ljava/util/List;)V } public final class arrow/core/serialization/NonEmptySetSerializer : kotlinx/serialization/KSerializer { @@ -43,12 +43,3 @@ public final class arrow/core/serialization/OptionSerializer : kotlinx/serializa public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V } -public final class arrow/core/serialization/ValidatedSerializer : kotlinx/serialization/KSerializer { - public fun (Lkotlinx/serialization/KSerializer;Lkotlinx/serialization/KSerializer;)V - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Larrow/core/Validated; - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Larrow/core/Validated;)V - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V -} - diff --git a/arrow-libs/core/arrow-core-serialization/build.gradle.kts b/arrow-libs/core/arrow-core-serialization/build.gradle.kts index d3fadb85f3b..6ba4450f34f 100644 --- a/arrow-libs/core/arrow-core-serialization/build.gradle.kts +++ b/arrow-libs/core/arrow-core-serialization/build.gradle.kts @@ -5,7 +5,7 @@ plugins { alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) + alias(libs.plugins.spotless) id(libs.plugins.kotlinx.serialization.get().pluginId) } @@ -24,17 +24,12 @@ kotlin { commonTest { dependencies { implementation(libs.kotlinx.serializationJson) - implementation(libs.kotest.frameworkEngine) + implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } } - - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) - } - } } jvm { @@ -45,3 +40,7 @@ kotlin { } } } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/core/arrow-core-serialization/src/commonMain/kotlin/arrow/core/serialization/ValidatedSerializer.kt b/arrow-libs/core/arrow-core-serialization/src/commonMain/kotlin/arrow/core/serialization/ValidatedSerializer.kt deleted file mode 100644 index 279e93f4759..00000000000 --- a/arrow-libs/core/arrow-core-serialization/src/commonMain/kotlin/arrow/core/serialization/ValidatedSerializer.kt +++ /dev/null @@ -1,63 +0,0 @@ -package arrow.core.serialization - -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.Validated -import arrow.core.invalid -import arrow.core.none -import arrow.core.some -import arrow.core.valid -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerializationException -import kotlinx.serialization.descriptors.buildClassSerialDescriptor -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.CompositeDecoder -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import kotlinx.serialization.encoding.decodeStructure -import kotlinx.serialization.encoding.encodeStructure - -public class ValidatedSerializer( - private val errorSerializer: KSerializer, - private val elementSerializer: KSerializer, -) : KSerializer> { - - override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Validated") { - element("invalid", errorSerializer.descriptor, isOptional = true) - element("valid", elementSerializer.descriptor, isOptional = true) - } - override fun serialize(encoder: Encoder, value: Validated) { - encoder.encodeStructure(descriptor) { - when (value) { - is Validated.Invalid -> encodeSerializableElement(descriptor, 0, errorSerializer, value.value) - is Validated.Valid -> encodeSerializableElement(descriptor, 1, elementSerializer, value.value) - } - } - } - override fun deserialize(decoder: Decoder): Validated { - var invalidValue: Option = none() - var validValue: Option = none() - decoder.decodeStructure(descriptor) { - while (true) { - when (val index = decodeElementIndex(descriptor)) { - 0 -> { - invalidValue = decodeSerializableElement(descriptor, 0, errorSerializer).some() - } - 1 -> { - validValue = decodeSerializableElement(descriptor, 1, elementSerializer).some() - } - CompositeDecoder.DECODE_DONE -> break - else -> error("unexpected index: $index") - } - } - } - return when { - invalidValue is None && validValue is None -> throw SerializationException("No information found for this Either") - invalidValue is Some && validValue is Some -> throw SerializationException("Both Left and Right specified for Either") - invalidValue is Some -> (invalidValue as Some).value.invalid() - validValue is Some -> (validValue as Some).value.valid() - else -> error("this should never happen") - } - } -} diff --git a/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/BackAgainTest.kt b/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/BackAgainTest.kt index 889443e7ed1..f76c7c0c804 100644 --- a/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/BackAgainTest.kt +++ b/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/BackAgainTest.kt @@ -1,7 +1,6 @@ @file:UseSerializers( EitherSerializer::class, IorSerializer::class, - ValidatedSerializer::class, OptionSerializer::class, NonEmptyListSerializer::class, NonEmptySetSerializer::class @@ -14,18 +13,18 @@ import arrow.core.Ior import arrow.core.NonEmptyList import arrow.core.NonEmptySet import arrow.core.Option -import arrow.core.Validated -import io.kotest.core.spec.style.StringSpec +import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.checkAll +import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.map +import io.kotest.property.arbitrary.string +import kotlin.test.Test +import kotlinx.coroutines.test.runTest import kotlinx.serialization.UseSerializers import kotlinx.serialization.json.Json import kotlinx.serialization.json.encodeToJsonElement import kotlinx.serialization.json.decodeFromJsonElement -import io.kotest.matchers.shouldBe -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.map -import io.kotest.property.arbitrary.string import kotlinx.serialization.Serializable /* @@ -39,9 +38,6 @@ data class EitherInside(val thing: Either) @Serializable data class IorInside(val thing: Ior) -@Serializable -data class ValidatedInside(val thing: Validated) - @Serializable data class OptionInside(val thing: Option) @@ -51,25 +47,28 @@ data class NonEmptyListInside(val thing: NonEmptyList) @Serializable data class NonEmptySetInside(val thing: NonEmptySet) -inline fun StringSpec.backAgain(generator: Arb) { - "there and back again, ${T::class.simpleName}" { +inline fun backAgain(generator: Arb) = + runTest { checkAll(generator) { e -> val result = Json.encodeToJsonElement(e) val back = Json.decodeFromJsonElement(result) back shouldBe e } } -} /** * Checks that the result of serializing a value into JSON, * and then deserializing it, gives back the original. */ -class BackAgainTest : StringSpec({ - backAgain(Arb.either(Arb.string(), Arb.int()).map(::EitherInside)) - backAgain(Arb.ior(Arb.string(), Arb.int()).map(::IorInside)) - backAgain(Arb.validated(Arb.string(), Arb.int()).map(::ValidatedInside)) - backAgain(Arb.option(Arb.string()).map(::OptionInside)) - backAgain(Arb.nonEmptyList(Arb.int()).map(::NonEmptyListInside)) - backAgain(Arb.nonEmptySet(Arb.int()).map(::NonEmptySetInside)) -}) +class BackAgainTest { + @Test fun backAgainEither() = + backAgain(Arb.either(Arb.string(), Arb.int()).map(::EitherInside)) + @Test fun backAgainIor() = + backAgain(Arb.ior(Arb.string(), Arb.int()).map(::IorInside)) + @Test fun backAgainOption() = + backAgain(Arb.option(Arb.string()).map(::OptionInside)) + @Test fun backAgainNonEmptyList() = + backAgain(Arb.nonEmptyList(Arb.int()).map(::NonEmptyListInside)) + @Test fun backAgainNonEmptySet() = + backAgain(Arb.nonEmptySet(Arb.int()).map(::NonEmptySetInside)) +} diff --git a/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/Generators.kt b/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/Generators.kt index 7d2691b15e2..b64bb0195dd 100644 --- a/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/Generators.kt +++ b/arrow-libs/core/arrow-core-serialization/src/commonTest/kotlin/arrow/core/serialization/Generators.kt @@ -1,13 +1,6 @@ package arrow.core.serialization -import arrow.core.Either -import arrow.core.Ior -import arrow.core.NonEmptyList -import arrow.core.NonEmptySet -import arrow.core.Option -import arrow.core.Validated -import arrow.core.toNonEmptySetOrNull -import arrow.core.toOption +import arrow.core.* import io.kotest.property.Arb import io.kotest.property.arbitrary.bind import io.kotest.property.arbitrary.choice @@ -18,12 +11,12 @@ import io.kotest.property.arbitrary.set import kotlin.math.max fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.bind(arb, Arb.list(arb, range), ::NonEmptyList) + Arb.bind(arb, Arb.list(arb, range)) { head, tail -> NonEmptyList(head, tail) } fun Arb.Companion.nonEmptySet(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.set(arb, max(range.first, 1) .. range.last).map { it.toNonEmptySetOrNull()!! } -fun Arb.Companion.option(arb: Arb): Arb> = +fun Arb.Companion.option(arb: Arb): Arb> = arb.orNull().map { it.toOption() } fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { @@ -32,9 +25,6 @@ fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { return Arb.choice(arbLeft, arbRight) } -fun Arb.Companion.validated(arbE: Arb, arbA: Arb): Arb> = - Arb.either(arbE, arbA).map { Validated.fromEither(it) } - fun Arb.Companion.ior(arbA: Arb, arbB: Arb): Arb> = arbA.alignWith(arbB) { it } diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index cb2dc667993..5ad4961fbb0 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -42,13 +42,6 @@ public final class arrow/core/ComparisonKt { public static final fun sort (S[S)Ljava/util/List; } -public final class arrow/core/Composition { - public static final fun andThen (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0; - public static final fun andThen (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun andThen (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; - public static final fun compose (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; -} - public final class arrow/core/ConcurrentMapMemoizationCache : arrow/core/MemoizationCache { public static final synthetic fun box-impl (Ljava/util/concurrent/ConcurrentMap;)Larrow/core/ConcurrentMapMemoizationCache; public static fun constructor-impl (Ljava/util/concurrent/ConcurrentMap;)Ljava/util/concurrent/ConcurrentMap; @@ -67,192 +60,28 @@ public final class arrow/core/ConcurrentMapMemoizationCache : arrow/core/Memoiza public final synthetic fun unbox-impl ()Ljava/util/concurrent/ConcurrentMap; } -public final class arrow/core/Const { - public static final field Companion Larrow/core/Const$Companion; - public fun (Ljava/lang/Object;)V - public final fun copy (Ljava/lang/Object;)Larrow/core/Const; - public static synthetic fun copy$default (Larrow/core/Const;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Const; - public fun equals (Ljava/lang/Object;)Z - public fun hashCode ()I - public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Const; - public final fun retag ()Larrow/core/Const; - public fun toString ()Ljava/lang/String; - public final fun value ()Ljava/lang/Object; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function10;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function9;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function8;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function7;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function6;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function5;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function4;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Larrow/core/Const;Lkotlin/jvm/functions/Function3;)Larrow/core/Const; - public final fun zip (Larrow/typeclasses/Semigroup;Larrow/core/Const;Lkotlin/jvm/functions/Function2;)Larrow/core/Const; -} - -public final class arrow/core/Const$Companion { -} - -public final class arrow/core/ConstKt { - public static final field ConstDeprecation Ljava/lang/String; - public static final fun combine (Larrow/core/Const;Larrow/typeclasses/Semigroup;Larrow/core/Const;)Larrow/core/Const; - public static final fun compareTo (Larrow/core/Const;Larrow/core/Const;)I - public static final fun const (Ljava/lang/Object;)Larrow/core/Const; - public static final fun contramap (Larrow/core/Const;Lkotlin/jvm/functions/Function1;)Larrow/core/Const; -} - -public final class arrow/core/Currying { - public static final fun curried (Lkotlin/jvm/functions/Function10;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function11;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function12;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function13;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function14;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function15;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function16;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function17;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function18;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function19;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function20;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function21;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function22;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function6;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function7;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function8;)Lkotlin/jvm/functions/Function1; - public static final fun curried (Lkotlin/jvm/functions/Function9;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function10;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function11;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function12;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function13;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function14;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function15;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function16;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function17;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function18;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function19;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function20;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function21;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function22;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function6;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function7;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function8;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/Function9;)Lkotlin/jvm/functions/Function1; - public static final fun curriedEffect (Lkotlin/jvm/functions/FunctionN;)Lkotlin/jvm/functions/Function1; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function10; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function11; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function12; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function13; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function14; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function15; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function16; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function17; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function18; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function19; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function20; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function21; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function22; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function4; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function5; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function6; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function7; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function8; - public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function9; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function10; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function11; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function12; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function13; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function14; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function15; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function16; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function17; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function18; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function19; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function20; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function21; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function22; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function4; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function5; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function6; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function7; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function8; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function9; - public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/FunctionN; -} - public abstract class arrow/core/Either { public static final field Companion Larrow/core/Either$Companion; - public final fun all (Lkotlin/jvm/functions/Function1;)Z - public final fun bifoldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun bifoldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun bimap (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun bitraverse (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun bitraverseNullable (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun bitraverseOption (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun bitraverseValidated (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun conditionally (ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public final fun exist (Lkotlin/jvm/functions/Function1;)Z - public final fun exists (Lkotlin/jvm/functions/Function1;)Z - public final fun findOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun catch (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; public final fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun foldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun fromNullable (Ljava/lang/Object;)Larrow/core/Either; public final fun getOrNone ()Larrow/core/Option; public final fun getOrNull ()Ljava/lang/Object; - public final fun isEmpty ()Z public final fun isLeft ()Z public final fun isLeft (Lkotlin/jvm/functions/Function1;)Z - public final fun isNotEmpty ()Z public final fun isRight ()Z public final fun isRight (Lkotlin/jvm/functions/Function1;)Z public final fun leftOrNull ()Ljava/lang/Object; - public static final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public final fun mapLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public final fun onLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public final fun onRight (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun orNone ()Larrow/core/Option; - public final fun orNull ()Ljava/lang/Object; - public final fun replicate (I)Larrow/core/Either; - public static final fun resolve (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public final fun swap ()Larrow/core/Either; - public final fun tap (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun tapLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun toEither ()Larrow/core/Either; public final fun toIor ()Larrow/core/Ior; public fun toString ()Ljava/lang/String; - public final fun toValidated ()Larrow/core/Validated; - public final fun toValidatedNel ()Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun traverseNullable (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverseOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun traverseValidated (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun tryCatch (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public static final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public static final fun tryCatchAndFlatten (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public final fun void ()Larrow/core/Either; } public final class arrow/core/Either$Companion { - public final fun conditionally (ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public final fun fromNullable (Ljava/lang/Object;)Larrow/core/Either; - public final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun resolve (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun tryCatch (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public final fun tryCatchAndFlatten (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; + public final fun catch (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; public final fun zipOrAccumulate (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function10;)Larrow/core/Either; public final fun zipOrAccumulate (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function9;)Larrow/core/Either; public final fun zipOrAccumulate (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function8;)Larrow/core/Either; @@ -295,7 +124,6 @@ public final class arrow/core/Either$Left : arrow/core/Either { } public final class arrow/core/Either$Left$Companion { - public final fun getLeftUnit ()Larrow/core/Either; } public final class arrow/core/Either$Right : arrow/core/Either { @@ -317,58 +145,17 @@ public final class arrow/core/Either$Right$Companion { public final class arrow/core/EitherKt { public static final field NicheAPI Ljava/lang/String; public static final field RedundantAPI Ljava/lang/String; - public static final fun bisequence (Larrow/core/Either;)Ljava/util/List; - public static final fun bisequenceNullable (Larrow/core/Either;)Larrow/core/Either; - public static final fun bisequenceOption (Larrow/core/Either;)Larrow/core/Option; - public static final fun bisequenceValidated (Larrow/core/Either;)Larrow/core/Validated; public static final fun combine (Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public static final fun combine (Larrow/core/Either;Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;Larrow/core/Either;)Larrow/core/Either; - public static final fun combineAll (Ljava/lang/Iterable;Larrow/typeclasses/Monoid;Larrow/typeclasses/Monoid;)Larrow/core/Either; - public static final fun combineK (Larrow/core/Either;Larrow/core/Either;)Larrow/core/Either; public static final fun compareTo (Larrow/core/Either;Larrow/core/Either;)I - public static final fun contains (Larrow/core/Either;Ljava/lang/Object;)Z - public static final fun ensure (Larrow/core/Either;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun filterOrElse (Larrow/core/Either;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public static final fun filterOrOther (Larrow/core/Either;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun flatMap (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun flatten (Larrow/core/Either;)Larrow/core/Either; - public static final synthetic fun getOrElse (Larrow/core/Either;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; public static final fun getOrElse (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun getOrHandle (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun handleError (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun handleErrorWith (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun left (Ljava/lang/Object;)Larrow/core/Either; - public static final fun leftIfNull (Larrow/core/Either;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; public static final fun leftNel (Ljava/lang/Object;)Larrow/core/Either; - public static final fun leftWiden (Larrow/core/Either;)Larrow/core/Either; public static final fun merge (Larrow/core/Either;)Ljava/lang/Object; - public static final fun orNull (Larrow/core/Either;)Ljava/lang/Object; public static final fun recover (Larrow/core/Either;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public static final fun redeem (Larrow/core/Either;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun redeemWith (Larrow/core/Either;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun replicate (Larrow/core/Either;ILarrow/typeclasses/Monoid;)Larrow/core/Either; public static final fun right (Ljava/lang/Object;)Larrow/core/Either; - public static final fun rightIfNotNull (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public static final fun rightIfNull (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; - public static final fun sequence (Larrow/core/Either;)Larrow/core/Either; - public static final fun sequence (Larrow/core/Either;)Larrow/core/Option; - public static final fun sequence (Larrow/core/Either;)Larrow/core/Validated; - public static final fun sequence (Larrow/core/Either;)Ljava/util/List; - public static final fun sequenceNullable (Larrow/core/Either;)Larrow/core/Either; - public static final fun sequenceOption (Larrow/core/Either;)Larrow/core/Option; - public static final fun sequenceValidated (Larrow/core/Either;)Larrow/core/Validated; public static final fun toEitherNel (Larrow/core/Either;)Larrow/core/Either; - public static final fun widen (Larrow/core/Either;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function10;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function9;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function8;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function7;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function6;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function5;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function4;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function3;)Larrow/core/Either; - public static final fun zip (Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; } public final class arrow/core/EmptyValue { @@ -378,183 +165,27 @@ public final class arrow/core/EmptyValue { public final fun unbox (Ljava/lang/Object;)Ljava/lang/Object; } -public final class arrow/core/Endo { - public static final field Companion Larrow/core/Endo$Companion; - public fun (Lkotlin/jvm/functions/Function1;)V - public final fun combine (Larrow/core/Endo;)Larrow/core/Endo; - public final fun component1 ()Lkotlin/jvm/functions/Function1; - public final fun copy (Lkotlin/jvm/functions/Function1;)Larrow/core/Endo; - public static synthetic fun copy$default (Larrow/core/Endo;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Larrow/core/Endo; - public fun equals (Ljava/lang/Object;)Z - public final fun getF ()Lkotlin/jvm/functions/Function1; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Endo$Companion { -} - -public abstract class arrow/core/Eval { - public static final field Companion Larrow/core/Eval$Companion; - public static final fun always (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Always; - public final fun coflatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/Eval; - public static final fun defer (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval; - public final fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/Eval; - public static final fun later (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Later; - public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Eval; - public abstract fun memoize ()Larrow/core/Eval; - public static final fun now (Ljava/lang/Object;)Larrow/core/Eval; - public static final fun raise (Ljava/lang/Throwable;)Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public abstract fun value ()Ljava/lang/Object; -} - -public final class arrow/core/Eval$Always : arrow/core/Eval { - public fun (Lkotlin/jvm/functions/Function0;)V - public final fun copy (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Always; - public static synthetic fun copy$default (Larrow/core/Eval$Always;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Larrow/core/Eval$Always; - public fun equals (Ljava/lang/Object;)Z - public fun hashCode ()I - public fun memoize ()Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public fun value ()Ljava/lang/Object; -} - -public final class arrow/core/Eval$Companion { - public final fun always (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Always; - public final fun defer (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval; - public final fun later (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Later; - public final fun now (Ljava/lang/Object;)Larrow/core/Eval; - public final fun raise (Ljava/lang/Throwable;)Larrow/core/Eval; -} - -public final class arrow/core/Eval$Defer : arrow/core/Eval { - public fun (Lkotlin/jvm/functions/Function0;)V - public final fun component1 ()Lkotlin/jvm/functions/Function0; - public final fun copy (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Defer; - public static synthetic fun copy$default (Larrow/core/Eval$Defer;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Larrow/core/Eval$Defer; - public fun equals (Ljava/lang/Object;)Z - public final fun getThunk ()Lkotlin/jvm/functions/Function0; - public fun hashCode ()I - public fun memoize ()Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public fun value ()Ljava/lang/Object; -} - -public abstract class arrow/core/Eval$FlatMap : arrow/core/Eval { - public fun ()V - public fun memoize ()Larrow/core/Eval; - public abstract fun run (Ljava/lang/Object;)Larrow/core/Eval; - public abstract fun start ()Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public fun value ()Ljava/lang/Object; -} - -public final class arrow/core/Eval$Later : arrow/core/Eval { - public fun (Lkotlin/jvm/functions/Function0;)V - public final fun copy (Lkotlin/jvm/functions/Function0;)Larrow/core/Eval$Later; - public static synthetic fun copy$default (Larrow/core/Eval$Later;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Larrow/core/Eval$Later; - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Ljava/lang/Object; - public fun hashCode ()I - public fun memoize ()Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public fun value ()Ljava/lang/Object; -} - -public final class arrow/core/Eval$Now : arrow/core/Eval { - public static final field Companion Larrow/core/Eval$Now$Companion; - public fun (Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;)Larrow/core/Eval$Now; - public static synthetic fun copy$default (Larrow/core/Eval$Now;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Eval$Now; - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Ljava/lang/Object; - public fun hashCode ()I - public fun memoize ()Larrow/core/Eval; - public fun toString ()Ljava/lang/String; - public fun value ()Ljava/lang/Object; -} - -public final class arrow/core/Eval$Now$Companion { - public final fun getUnit ()Larrow/core/Eval; -} - -public final class arrow/core/EvalKt { - public static final fun iterateRight (Ljava/util/Iterator;Larrow/core/Eval;Lkotlin/jvm/functions/Function2;)Larrow/core/Eval; - public static final fun replicate (Larrow/core/Eval;I)Larrow/core/Eval; - public static final fun replicate (Larrow/core/Eval;ILarrow/typeclasses/Monoid;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function10;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function9;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function8;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function7;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function6;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function5;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function4;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function3;)Larrow/core/Eval; - public static final fun zip (Larrow/core/Eval;Larrow/core/Eval;Lkotlin/jvm/functions/Function2;)Larrow/core/Eval; -} - public abstract class arrow/core/Ior { public static final field Companion Larrow/core/Ior$Companion; - public final fun _isBoth ()Z - public final fun _isLeft ()Z - public final fun _isRight ()Z - public final fun all (Lkotlin/jvm/functions/Function1;)Z - public final fun bicrosswalk (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun bicrosswalkMap (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; - public final fun bicrosswalkNull (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun bifoldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun bifoldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun bimap (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun bitraverse (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun bitraverseEither (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun bitraverseNullable (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun bitraverseOption (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun bitraverseValidated (Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun bothNel (Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Ior; - public final fun crosswalk (Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun crosswalkMap (Lkotlin/jvm/functions/Function1;)Ljava/util/Map; - public final fun crosswalkNull (Larrow/core/Ior;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun exists (Lkotlin/jvm/functions/Function1;)Z - public final fun findOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public final fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun foldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun fromNullables (Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Ior; public final fun getOrNull ()Ljava/lang/Object; - public abstract fun isBoth ()Z + public final fun isBoth ()Z public final fun isBoth (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Z - public final fun isEmpty ()Z - public abstract fun isLeft ()Z + public final fun isLeft ()Z public final fun isLeft (Lkotlin/jvm/functions/Function1;)Z - public final fun isNotEmpty ()Z - public abstract fun isRight ()Z + public final fun isRight ()Z public final fun isRight (Lkotlin/jvm/functions/Function1;)Z public static final fun leftNel (Ljava/lang/Object;)Larrow/core/Ior; public final fun leftOrNull ()Ljava/lang/Object; - public static final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; public final fun mapLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun orNull ()Ljava/lang/Object; - public final fun padNull ()Lkotlin/Pair; public final fun swap ()Larrow/core/Ior; public final fun toEither ()Larrow/core/Either; public final fun toPair ()Lkotlin/Pair; public fun toString ()Ljava/lang/String; - public final fun toValidated ()Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun traverseEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverseNullable (Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public final fun traverseOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun traverseValidated (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public final fun unwrap ()Larrow/core/Either; - public final fun void ()Larrow/core/Ior; } public final class arrow/core/Ior$Both : arrow/core/Ior { @@ -567,9 +198,6 @@ public final class arrow/core/Ior$Both : arrow/core/Ior { public final fun getLeftValue ()Ljava/lang/Object; public final fun getRightValue ()Ljava/lang/Object; public fun hashCode ()I - public fun isBoth ()Z - public fun isLeft ()Z - public fun isRight ()Z public fun toString ()Ljava/lang/String; } @@ -577,8 +205,6 @@ public final class arrow/core/Ior$Companion { public final fun bothNel (Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Ior; public final fun fromNullables (Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Ior; public final fun leftNel (Ljava/lang/Object;)Larrow/core/Ior; - public final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; } public final class arrow/core/Ior$Left : arrow/core/Ior { @@ -590,9 +216,6 @@ public final class arrow/core/Ior$Left : arrow/core/Ior { public fun equals (Ljava/lang/Object;)Z public final fun getValue ()Ljava/lang/Object; public fun hashCode ()I - public fun isBoth ()Z - public fun isLeft ()Z - public fun isRight ()Z public fun toString ()Ljava/lang/String; } @@ -608,65 +231,28 @@ public final class arrow/core/Ior$Right : arrow/core/Ior { public fun equals (Ljava/lang/Object;)Z public final fun getValue ()Ljava/lang/Object; public fun hashCode ()I - public fun isBoth ()Z - public fun isLeft ()Z - public fun isRight ()Z public fun toString ()Ljava/lang/String; } public final class arrow/core/Ior$Right$Companion { - public final fun getUnit ()Larrow/core/Ior; } public final class arrow/core/IorKt { - public static final fun bisequence (Larrow/core/Ior;)Ljava/util/List; - public static final fun bisequenceEither (Larrow/core/Ior;)Larrow/core/Either; - public static final fun bisequenceNullable (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun bisequenceOption (Larrow/core/Ior;)Larrow/core/Option; - public static final fun bisequenceValidated (Larrow/core/Ior;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; public static final fun bothIor (Lkotlin/Pair;)Larrow/core/Ior; public static final fun combine (Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Ior; - public static final fun combine (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;Larrow/core/Ior;)Larrow/core/Ior; public static final fun compareTo (Larrow/core/Ior;Larrow/core/Ior;)I - public static final fun flatMap (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; public static final fun flatMap (Larrow/core/Ior;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public static final fun flatten (Larrow/core/Ior;Larrow/typeclasses/Semigroup;)Larrow/core/Ior; public static final fun flatten (Larrow/core/Ior;Lkotlin/jvm/functions/Function2;)Larrow/core/Ior; - public static final synthetic fun getOrElse (Larrow/core/Ior;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; public static final fun getOrElse (Larrow/core/Ior;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun leftIor (Ljava/lang/Object;)Larrow/core/Ior; - public static final fun leftWiden (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun replicate (Larrow/core/Ior;Larrow/typeclasses/Semigroup;I)Larrow/core/Ior; - public static final fun replicate (Larrow/core/Ior;Larrow/typeclasses/Semigroup;ILarrow/typeclasses/Monoid;)Larrow/core/Ior; public static final fun rightIor (Ljava/lang/Object;)Larrow/core/Ior; - public static final fun sequence (Larrow/core/Ior;)Larrow/core/Either; - public static final fun sequence (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun sequence (Larrow/core/Ior;)Larrow/core/Option; - public static final fun sequence (Larrow/core/Ior;)Larrow/core/Validated; - public static final fun sequence (Larrow/core/Ior;)Ljava/util/List; - public static final fun sequenceEither (Larrow/core/Ior;)Larrow/core/Either; - public static final fun sequenceNullable (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun sequenceOption (Larrow/core/Ior;)Larrow/core/Option; - public static final fun sequenceValidated (Larrow/core/Ior;)Larrow/core/Validated; public static final fun toIorNel (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun widen (Larrow/core/Ior;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function10;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function9;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function8;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function7;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function6;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function5;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function4;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Larrow/core/Ior;Lkotlin/jvm/functions/Function3;)Larrow/core/Ior; - public static final fun zip (Larrow/core/Ior;Larrow/typeclasses/Semigroup;Larrow/core/Ior;Lkotlin/jvm/functions/Function2;)Larrow/core/Ior; } public final class arrow/core/IterableKt { public static final fun align (Ljava/lang/Iterable;Ljava/lang/Iterable;)Ljava/util/List; public static final fun align (Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun collectionSizeOrDefault (Ljava/lang/Iterable;I)I - public static final fun combineAll (Ljava/lang/Iterable;Larrow/typeclasses/Monoid;)Ljava/lang/Object; public static final fun compareTo (Ljava/lang/Iterable;Ljava/lang/Iterable;)I public static final fun crosswalk (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun crosswalkMap (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; @@ -681,10 +267,6 @@ public final class arrow/core/IterableKt { public static final fun flattenOption (Ljava/lang/Iterable;)Ljava/util/List; public static final fun flattenOrAccumulate (Ljava/lang/Iterable;)Larrow/core/Either; public static final fun flattenOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public static final fun fold (Ljava/lang/Iterable;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun foldMap (Ljava/lang/Iterable;Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun getListUnit ()Ljava/util/List; - public static final fun ifThen (Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Iterable; public static final fun interleave (Ljava/lang/Iterable;Ljava/lang/Iterable;)Ljava/util/List; public static final fun lastOrNone (Ljava/lang/Iterable;)Larrow/core/Option; public static final fun lastOrNone (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; @@ -698,53 +280,20 @@ public final class arrow/core/IterableKt { public static final fun prependTo (Ljava/lang/Object;Ljava/lang/Iterable;)Ljava/util/List; public static final fun reduceOrNull (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun reduceRightNull (Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun replicate (Ljava/lang/Iterable;I)Ljava/util/List; - public static final fun replicate (Ljava/lang/Iterable;ILarrow/typeclasses/Monoid;)Ljava/util/List; public static final fun rightPadZip (Ljava/lang/Iterable;Ljava/lang/Iterable;)Ljava/util/List; public static final fun rightPadZip (Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; - public static final fun salign (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Ljava/lang/Iterable;)Ljava/lang/Iterable; public static final fun separateEither (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun separateEither (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; public static final fun separateIor (Ljava/lang/Iterable;)Lkotlin/Pair; - public static final fun separateValidated (Ljava/lang/Iterable;)Lkotlin/Pair; - public static final fun sequence (Ljava/lang/Iterable;)Larrow/core/Either; - public static final fun sequence (Ljava/lang/Iterable;)Larrow/core/Option; - public static final fun sequence (Ljava/lang/Iterable;)Larrow/core/Validated; - public static final fun sequence (Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun sequence (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun sequence (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun sequenceEither (Ljava/lang/Iterable;)Larrow/core/Either; - public static final fun sequenceNullable (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun sequenceOption (Ljava/lang/Iterable;)Larrow/core/Option; - public static final fun sequenceResult (Ljava/lang/Iterable;)Ljava/lang/Object; - public static final fun sequenceValidated (Ljava/lang/Iterable;)Larrow/core/Validated; - public static final fun sequenceValidated (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; public static final fun singleOrNone (Ljava/lang/Iterable;)Larrow/core/Option; public static final fun singleOrNone (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun split (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun tail (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun traverse (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public static final fun traverseEither (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverseNullable (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public static final fun traverseOption (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseResult (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun traverseValidated (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverseValidated (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun unalign (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun unalign (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun uniteEither (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun uniteValidated (Ljava/lang/Iterable;)Ljava/util/List; public static final fun unweave (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun unzip (Ljava/lang/Iterable;)Lkotlin/Pair; public static final fun unzip (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun void (Ljava/lang/Iterable;)Ljava/util/List; - public static final fun widen (Ljava/lang/Iterable;)Ljava/lang/Iterable; - public static final fun widen (Ljava/util/List;)Ljava/util/List; public static final fun zip (Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function10;)Ljava/util/List; public static final fun zip (Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function9;)Ljava/util/List; public static final fun zip (Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function8;)Ljava/util/List; @@ -758,14 +307,10 @@ public final class arrow/core/IterableKt { public final class arrow/core/MapKt { public static final fun align (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public static final fun align (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; - public static final fun combine (Ljava/util/Map;Larrow/typeclasses/Semigroup;Ljava/util/Map;)Ljava/util/Map; public static final fun combine (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Ljava/util/Map; - public static final fun combineAll (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;)Ljava/util/Map; - public static final fun filterMap (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun filterOption (Ljava/util/Map;)Ljava/util/Map; public static final fun flatMap (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun fold (Ljava/util/Map;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun foldLeft (Ljava/util/Map;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun getOrNone (Ljava/util/Map;Ljava/lang/Object;)Larrow/core/Option; public static final fun mapNotNull (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; public static final fun mapOrAccumulate (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; @@ -773,26 +318,11 @@ public final class arrow/core/MapKt { public static final fun padZip (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public static final fun padZip (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Ljava/util/Map; public static final fun padZip (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function3;)Ljava/util/Map; - public static final fun salign (Ljava/util/Map;Larrow/typeclasses/Semigroup;Ljava/util/Map;)Ljava/util/Map; public static final fun salign (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Ljava/util/Map; - public static final fun sequence (Ljava/util/Map;)Larrow/core/Either; - public static final fun sequence (Ljava/util/Map;)Larrow/core/Option; - public static final fun sequence (Ljava/util/Map;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun sequenceEither (Ljava/util/Map;)Larrow/core/Either; - public static final fun sequenceOption (Ljava/util/Map;)Larrow/core/Option; - public static final fun sequenceValidated (Ljava/util/Map;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun traverse (Ljava/util/Map;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverse (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverse (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseEither (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverseOption (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseValidated (Ljava/util/Map;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun unalign (Ljava/util/Map;)Lkotlin/Pair; public static final fun unalign (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; public static final fun unzip (Ljava/util/Map;)Lkotlin/Pair; public static final fun unzip (Ljava/util/Map;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun void (Ljava/util/Map;)Ljava/util/Map; - public static final fun widen (Ljava/util/Map;)Ljava/util/Map; public static final fun zip (Ljava/util/Map;Ljava/util/Map;)Ljava/util/Map; public static final fun zip (Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function11;)Ljava/util/Map; public static final fun zip (Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function10;)Ljava/util/Map; @@ -805,15 +335,6 @@ public final class arrow/core/MapKt { public static final fun zip (Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/functions/Function3;)Ljava/util/Map; } -public final class arrow/core/Memoization { - public static final fun memoize (Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function0; - public static final fun memoize (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun memoize (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; - public static final fun memoize (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; - public static final fun memoize (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function4; - public static final fun memoize (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function5; -} - public abstract interface class arrow/core/MemoizationCache { public abstract fun get (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; @@ -826,118 +347,154 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { } public abstract interface class arrow/core/NonEmptyCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { - public abstract fun distinct ()Larrow/core/NonEmptyList; - public abstract fun distinctBy (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public abstract fun distinct-1X0FA-Y ()Ljava/util/List; + public abstract fun distinctBy-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public abstract fun firstOrNull ()Ljava/lang/Object; - public abstract fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public abstract fun flatMap-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public abstract fun getHead ()Ljava/lang/Object; public abstract fun isEmpty ()Z public abstract fun lastOrNull ()Ljava/lang/Object; - public abstract fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public abstract fun mapIndexed (Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; + public abstract fun map-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public abstract fun mapIndexed-0-xjo5U (Lkotlin/jvm/functions/Function2;)Ljava/util/List; public abstract fun plus (Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; public abstract fun plus (Ljava/lang/Object;)Larrow/core/NonEmptyCollection; - public abstract fun toNonEmptyList ()Larrow/core/NonEmptyList; + public abstract fun toNonEmptyList-1X0FA-Y ()Ljava/util/List; public abstract fun toNonEmptySet-5sCjGKo ()Ljava/util/Set; public abstract fun zip (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } public final class arrow/core/NonEmptyCollection$DefaultImpls { - public static fun distinct (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyList; - public static fun distinctBy (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public static fun distinct-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; + public static fun distinctBy-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun firstOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; - public static fun flatMap (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public static fun flatMap-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun isEmpty (Larrow/core/NonEmptyCollection;)Z - public static fun map (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public static fun mapIndexed (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; - public static fun toNonEmptyList (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyList; + public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; public static fun toNonEmptySet-5sCjGKo (Larrow/core/NonEmptyCollection;)Ljava/util/Set; public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } -public final class arrow/core/NonEmptyList : kotlin/collections/AbstractList, arrow/core/NonEmptyCollection { +public final class arrow/core/NonEmptyList : arrow/core/NonEmptyCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; - public fun (Ljava/lang/Object;Ljava/util/List;)V - public synthetic fun (Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun align (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun coflatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public fun distinct ()Larrow/core/NonEmptyList; - public fun distinctBy (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public fun add (ILjava/lang/Object;)V + public fun add (Ljava/lang/Object;)Z + public fun addAll (ILjava/util/Collection;)Z + public fun addAll (Ljava/util/Collection;)Z + public static final fun align-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final synthetic fun box-impl (Ljava/util/List;)Larrow/core/NonEmptyList; + public fun clear ()V + public static final fun coflatMap-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun constructor-impl (Ljava/lang/Object;Ljava/util/List;)Ljava/util/List; + public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; + public fun contains (Ljava/lang/Object;)Z + public static fun contains-impl (Ljava/util/List;Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public static fun containsAll-impl (Ljava/util/List;Ljava/util/Collection;)Z + public fun distinct-1X0FA-Y ()Ljava/util/List; + public static fun distinct-1X0FA-Y (Ljava/util/List;)Ljava/util/List; + public static fun distinctBy-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun distinctBy-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public fun equals (Ljava/lang/Object;)Z - public final fun extract ()Ljava/lang/Object; + public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z + public static final fun extract-impl (Ljava/util/List;)Ljava/lang/Object; public fun firstOrNull ()Ljava/lang/Object; - public fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun fromList (Ljava/util/List;)Larrow/core/Option; - public static final fun fromListUnsafe (Ljava/util/List;)Larrow/core/NonEmptyList; + public static fun firstOrNull-impl (Ljava/util/List;)Ljava/lang/Object; + public static fun flatMap-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun flatMap-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun foldLeft-impl (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public fun get (I)Ljava/lang/Object; + public static fun get-impl (Ljava/util/List;I)Ljava/lang/Object; public final fun getAll ()Ljava/util/List; public fun getHead ()Ljava/lang/Object; + public static fun getHead-impl (Ljava/util/List;)Ljava/lang/Object; public fun getSize ()I - public final fun getTail ()Ljava/util/List; + public static fun getSize-impl (Ljava/util/List;)I + public static final fun getTail-impl (Ljava/util/List;)Ljava/util/List; public fun hashCode ()I + public static fun hashCode-impl (Ljava/util/List;)I + public fun indexOf (Ljava/lang/Object;)I + public static fun indexOf-impl (Ljava/util/List;Ljava/lang/Object;)I public fun isEmpty ()Z + public static fun isEmpty-impl (Ljava/util/List;)Z + public fun iterator ()Ljava/util/Iterator; + public static fun iterator-impl (Ljava/util/List;)Ljava/util/Iterator; + public fun lastIndexOf (Ljava/lang/Object;)I + public static fun lastIndexOf-impl (Ljava/util/List;Ljava/lang/Object;)I public fun lastOrNull ()Ljava/lang/Object; - public fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public fun mapIndexed (Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; - public final fun padZip (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun padZip (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; - public final fun plus (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public static fun lastOrNull-impl (Ljava/util/List;)Ljava/lang/Object; + public fun listIterator ()Ljava/util/ListIterator; + public fun listIterator (I)Ljava/util/ListIterator; + public static fun listIterator-impl (Ljava/util/List;)Ljava/util/ListIterator; + public static fun listIterator-impl (Ljava/util/List;I)Ljava/util/ListIterator; + public static fun map-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun map-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun mapIndexed-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public fun mapIndexed-0-xjo5U (Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static final fun padZip-YfahJLU (Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static final fun padZip-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; public synthetic fun plus (Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; - public fun plus (Ljava/lang/Iterable;)Larrow/core/NonEmptyList; public synthetic fun plus (Ljava/lang/Object;)Larrow/core/NonEmptyCollection; - public fun plus (Ljava/lang/Object;)Larrow/core/NonEmptyList; - public final fun salign (Larrow/typeclasses/Semigroup;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun toList ()Ljava/util/List; - public fun toNonEmptyList ()Larrow/core/NonEmptyList; + public fun plus-0-xjo5U (Ljava/lang/Iterable;)Ljava/util/List; + public fun plus-0-xjo5U (Ljava/lang/Object;)Ljava/util/List; + public static fun plus-0-xjo5U (Ljava/util/List;Ljava/lang/Iterable;)Ljava/util/List; + public static fun plus-0-xjo5U (Ljava/util/List;Ljava/lang/Object;)Ljava/util/List; + public static final fun plus-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public fun remove (I)Ljava/lang/Object; + public fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun replaceAll (Ljava/util/function/UnaryOperator;)V + public fun retainAll (Ljava/util/Collection;)Z + public fun set (ILjava/lang/Object;)Ljava/lang/Object; + public synthetic fun size ()I + public fun sort (Ljava/util/Comparator;)V + public fun subList (II)Ljava/util/List; + public static fun subList-impl (Ljava/util/List;II)Ljava/util/List; + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; + public static final fun toList-impl (Ljava/util/List;)Ljava/util/List; + public fun toNonEmptyList-1X0FA-Y ()Ljava/util/List; + public static fun toNonEmptyList-1X0FA-Y (Ljava/util/List;)Ljava/util/List; public fun toNonEmptySet-5sCjGKo ()Ljava/util/Set; + public static fun toNonEmptySet-5sCjGKo (Ljava/util/List;)Ljava/util/Set; public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/util/List; public fun zip (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; - public final fun zip (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function10;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function9;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function8;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function7;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function6;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function5;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function4;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function3;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; + public static final fun zip-BdUWqYY (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function5;)Ljava/util/List; + public static final fun zip-EkAgaZI (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function10;)Ljava/util/List; + public static final fun zip-FrVv2gs (Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static final fun zip-QNErI5A (Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function3;)Ljava/util/List; + public static final fun zip-Sy0iXXA (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function4;)Ljava/util/List; + public static final fun zip-Vwi0aTY (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function7;)Ljava/util/List; + public static final fun zip-e5uF9gA (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function6;)Ljava/util/List; + public static fun zip-impl (Ljava/util/List;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; + public static final fun zip-oYG1GSg (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function8;)Ljava/util/List; + public static final fun zip-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final fun zip-vi6g5TI (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function9;)Ljava/util/List; } public final class arrow/core/NonEmptyList$Companion { - public final fun fromList (Ljava/util/List;)Larrow/core/Option; - public final fun fromListUnsafe (Ljava/util/List;)Larrow/core/NonEmptyList; - public final fun getUnit ()Larrow/core/NonEmptyList; + public final fun getUnit-1X0FA-Y ()Ljava/util/List; } public final class arrow/core/NonEmptyListKt { - public static final fun compareTo (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)I - public static final fun flatten (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public static final fun mapOrAccumulate (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public static final fun mapOrAccumulate (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public static final fun max (Larrow/core/NonEmptyList;)Ljava/lang/Comparable; - public static final fun maxBy (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun min (Larrow/core/NonEmptyList;)Ljava/lang/Comparable; - public static final fun minBy (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun nel (Ljava/lang/Object;)Larrow/core/NonEmptyList; - public static final fun nonEmptyListOf (Ljava/lang/Object;[Ljava/lang/Object;)Larrow/core/NonEmptyList; - public static final fun sequence (Larrow/core/NonEmptyList;)Larrow/core/Either; - public static final fun sequence (Larrow/core/NonEmptyList;)Larrow/core/Option; - public static final fun sequence (Larrow/core/NonEmptyList;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun sequenceEither (Larrow/core/NonEmptyList;)Larrow/core/Either; - public static final fun sequenceOption (Larrow/core/NonEmptyList;)Larrow/core/Option; - public static final fun sequenceValidated (Larrow/core/NonEmptyList;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; + public static final fun compareTo-8QhqC-A (Ljava/util/List;Ljava/util/List;)I + public static final fun flatten-GZgkXh4 (Ljava/util/List;)Ljava/util/List; + public static final fun mapOrAccumulate-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; + public static final fun mapOrAccumulate-lNWZWLA (Ljava/util/List;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; + public static final fun max-GZgkXh4 (Ljava/util/List;)Ljava/lang/Comparable; + public static final fun maxBy-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun min-GZgkXh4 (Ljava/util/List;)Ljava/lang/Comparable; + public static final fun minBy-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun nel (Ljava/lang/Object;)Ljava/util/List; + public static final fun nonEmptyListOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; public static final fun toNonEmptyListOrNone (Ljava/lang/Iterable;)Larrow/core/Option; - public static final fun toNonEmptyListOrNull (Ljava/lang/Iterable;)Larrow/core/NonEmptyList; - public static final fun traverse (Larrow/core/NonEmptyList;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverse (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverse (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseEither (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverseOption (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseValidated (Larrow/core/NonEmptyList;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun unzip (Larrow/core/NonEmptyList;)Lkotlin/Pair; - public static final fun unzip (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; + public static final fun toNonEmptyListOrNull (Ljava/lang/Iterable;)Ljava/util/List; + public static final fun unzip-GZgkXh4 (Ljava/util/List;)Lkotlin/Pair; + public static final fun unzip-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; } public final class arrow/core/NonEmptySet : arrow/core/NonEmptyCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { @@ -950,17 +507,17 @@ public final class arrow/core/NonEmptySet : arrow/core/NonEmptyCollection, java/ public static fun contains-impl (Ljava/util/Set;Ljava/lang/Object;)Z public fun containsAll (Ljava/util/Collection;)Z public static fun containsAll-impl (Ljava/util/Set;Ljava/util/Collection;)Z - public fun distinct ()Larrow/core/NonEmptyList; - public static fun distinct-impl (Ljava/util/Set;)Larrow/core/NonEmptyList; - public fun distinctBy (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public static fun distinctBy-impl (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public fun distinct-1X0FA-Y ()Ljava/util/List; + public static fun distinct-1X0FA-Y (Ljava/util/Set;)Ljava/util/List; + public static fun distinctBy-0-xjo5U (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun distinctBy-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public fun equals (Ljava/lang/Object;)Z public static fun equals-impl (Ljava/util/Set;Ljava/lang/Object;)Z public static final fun equals-impl0 (Ljava/util/Set;Ljava/util/Set;)Z public fun firstOrNull ()Ljava/lang/Object; public static fun firstOrNull-impl (Ljava/util/Set;)Ljava/lang/Object; - public fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public static fun flatMap-impl (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public static fun flatMap-0-xjo5U (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun flatMap-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public fun getHead ()Ljava/lang/Object; public static fun getHead-impl (Ljava/util/Set;)Ljava/lang/Object; public fun getSize ()I @@ -973,10 +530,10 @@ public final class arrow/core/NonEmptySet : arrow/core/NonEmptyCollection, java/ public static fun iterator-impl (Ljava/util/Set;)Ljava/util/Iterator; public fun lastOrNull ()Ljava/lang/Object; public static fun lastOrNull-impl (Ljava/util/Set;)Ljava/lang/Object; - public fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public static fun map-impl (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public fun mapIndexed (Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; - public static fun mapIndexed-impl (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; + public static fun map-0-xjo5U (Ljava/util/Set;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public fun map-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun mapIndexed-0-xjo5U (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public fun mapIndexed-0-xjo5U (Lkotlin/jvm/functions/Function2;)Ljava/util/List; public synthetic fun plus (Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; public synthetic fun plus (Ljava/lang/Object;)Larrow/core/NonEmptyCollection; public fun plus-J9TPrxk (Ljava/lang/Iterable;)Ljava/util/Set; @@ -989,15 +546,16 @@ public final class arrow/core/NonEmptySet : arrow/core/NonEmptyCollection, java/ public synthetic fun size ()I public fun toArray ()[Ljava/lang/Object; public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; - public fun toNonEmptyList ()Larrow/core/NonEmptyList; - public static fun toNonEmptyList-impl (Ljava/util/Set;)Larrow/core/NonEmptyList; + public fun toNonEmptyList-1X0FA-Y ()Ljava/util/List; + public static fun toNonEmptyList-1X0FA-Y (Ljava/util/Set;)Ljava/util/List; public fun toNonEmptySet-5sCjGKo ()Ljava/util/Set; public static fun toNonEmptySet-5sCjGKo (Ljava/util/Set;)Ljava/util/Set; public fun toString ()Ljava/lang/String; public static fun toString-impl (Ljava/util/Set;)Ljava/lang/String; public final synthetic fun unbox-impl ()Ljava/util/Set; - public fun zip (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; - public static fun zip-impl (Ljava/util/Set;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; + public synthetic fun zip (Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; + public fun zip-0-xjo5U (Larrow/core/NonEmptyCollection;)Ljava/util/List; + public static fun zip-0-xjo5U (Ljava/util/Set;Larrow/core/NonEmptyCollection;)Ljava/util/List; } public final class arrow/core/NonEmptySetKt { @@ -1018,685 +576,67 @@ public final class arrow/core/NonFatalOrThrowKt { public final class arrow/core/None : arrow/core/Option { public static final field INSTANCE Larrow/core/None; - public fun isEmpty ()Z public fun toString ()Ljava/lang/String; } -public final class arrow/core/Nullable { - public static final field INSTANCE Larrow/core/Nullable; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function10;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - public abstract class arrow/core/Option { public static final field Companion Larrow/core/Option$Companion; - public final fun align (Larrow/core/Option;)Larrow/core/Option; - public final fun align (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun all (Lkotlin/jvm/functions/Function1;)Z - public final fun and (Larrow/core/Option;)Larrow/core/Option; - public final fun crosswalk (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun crosswalkMap (Lkotlin/jvm/functions/Function1;)Ljava/util/Map; - public final fun crosswalkNull (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun exists (Lkotlin/jvm/functions/Function1;)Z public final fun filter (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public final fun filterNot (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun findOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public final fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public final fun fold (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun foldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun fromNullable (Ljava/lang/Object;)Larrow/core/Option; public final fun getOrNull ()Ljava/lang/Object; public static final fun invoke (Ljava/lang/Object;)Larrow/core/Option; - public final fun isDefined ()Z - public abstract fun isEmpty ()Z public final fun isNone ()Z - public final fun isNotEmpty ()Z public final fun isSome ()Z public final fun isSome (Lkotlin/jvm/functions/Function1;)Z - public static final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun mapNotNull (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun nonEmpty ()Z public final fun onNone (Lkotlin/jvm/functions/Function0;)Larrow/core/Option; public final fun onSome (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun orNull ()Ljava/lang/Object; - public final fun padZip (Larrow/core/Option;)Larrow/core/Option; - public final fun padZip (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Larrow/core/Option; - public final fun pairLeft (Ljava/lang/Object;)Larrow/core/Option; - public final fun pairRight (Ljava/lang/Object;)Larrow/core/Option; - public final fun reduceOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun reduceRightEvalOrNull (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/core/Eval; - public final fun replicate (I)Larrow/core/Option; - public final fun tap (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun tapNone (Lkotlin/jvm/functions/Function0;)Larrow/core/Option; public final fun toEither (Lkotlin/jvm/functions/Function0;)Larrow/core/Either; public final fun toList ()Ljava/util/List; public fun toString ()Ljava/lang/String; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun traverseEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverseValidated (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Option; public static final fun tryCatchOrNone (Lkotlin/jvm/functions/Function0;)Larrow/core/Option; - public final fun void ()Larrow/core/Option; - public final fun zip (Larrow/core/Option;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function10;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function9;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function8;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function7;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function6;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function5;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function4;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function3;)Larrow/core/Option; - public final fun zip (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Larrow/core/Option; } public final class arrow/core/Option$Companion { public final fun fromNullable (Ljava/lang/Object;)Larrow/core/Option; public final fun invoke (Ljava/lang/Object;)Larrow/core/Option; - public final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Option; public final fun tryCatchOrNone (Lkotlin/jvm/functions/Function0;)Larrow/core/Option; } public final class arrow/core/OptionKt { public static final fun combine (Larrow/core/Option;Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Larrow/core/Option; - public static final fun combine (Larrow/core/Option;Larrow/typeclasses/Semigroup;Larrow/core/Option;)Larrow/core/Option; - public static final fun combineAll (Larrow/core/Option;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun combineAll (Ljava/lang/Iterable;Larrow/typeclasses/Monoid;)Larrow/core/Option; public static final fun compareTo (Larrow/core/Option;Larrow/core/Option;)I - public static final fun ensure (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun flatten (Larrow/core/Option;)Larrow/core/Option; public static final fun getOrElse (Larrow/core/Option;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; - public static final fun handleError (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun handleErrorWith (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun maybe (ZLkotlin/jvm/functions/Function0;)Larrow/core/Option; public static final fun none ()Larrow/core/Option; - public static final fun or (Larrow/core/Option;Larrow/core/Option;)Larrow/core/Option; - public static final fun orElse (Larrow/core/Option;Lkotlin/jvm/functions/Function0;)Larrow/core/Option; - public static final fun recover (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Larrow/core/Option; - public static final fun redeem (Larrow/core/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun redeemWith (Larrow/core/Option;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun replicate (Larrow/core/Option;ILarrow/typeclasses/Monoid;)Larrow/core/Option; - public static final fun rethrow (Larrow/core/Option;)Larrow/core/Option; - public static final fun salign (Larrow/core/Option;Larrow/typeclasses/Semigroup;Larrow/core/Option;)Larrow/core/Option; - public static final fun separateEither (Larrow/core/Option;)Lkotlin/Pair; - public static final fun separateValidated (Larrow/core/Option;)Lkotlin/Pair; - public static final fun sequence (Larrow/core/Option;)Larrow/core/Either; - public static final fun sequence (Larrow/core/Option;)Larrow/core/Validated; - public static final fun sequence (Larrow/core/Option;)Ljava/util/List; - public static final fun sequenceEither (Larrow/core/Option;)Larrow/core/Either; - public static final fun sequenceValidated (Larrow/core/Option;)Larrow/core/Validated; + public static final fun recover (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun some (Ljava/lang/Object;)Larrow/core/Option; public static final fun toMap (Larrow/core/Option;)Ljava/util/Map; public static final fun toOption (Ljava/lang/Object;)Larrow/core/Option; public static final fun toOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun toOption (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun unalign (Larrow/core/Option;)Lkotlin/Pair; - public static final fun unalign (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun unite (Larrow/core/Option;Larrow/typeclasses/Monoid;)Larrow/core/Option; - public static final fun uniteEither (Larrow/core/Option;)Larrow/core/Option; - public static final fun uniteValidated (Larrow/core/Option;)Larrow/core/Option; - public static final fun unzip (Larrow/core/Option;)Lkotlin/Pair; - public static final fun unzip (Larrow/core/Option;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun widen (Larrow/core/Option;)Larrow/core/Option; -} - -public final class arrow/core/Partials { - public static final fun partially1 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially1 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially1 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially1 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially1 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially1 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially1 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially1 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially1 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially1 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially1 (Lkotlin/jvm/functions/Function1;Ljava/lang/Object;)Lkotlin/jvm/functions/Function0; - public static final fun partially1 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially1 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially1 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially1 (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; - public static final fun partially1 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; - public static final fun partially1 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially1 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially1 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially1 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially1 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially1 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially10 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially10 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially10 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially10 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially10 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially10 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially10 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially10 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially10 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially10 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially10 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially10 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially10 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially10Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially10Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially11 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially11 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially11 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially11 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially11 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially11 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially11 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially11 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially11 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially11 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially11 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially11 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially11Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially11Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially12 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially12 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially12 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially12 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially12 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially12 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially12 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially12 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially12 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially12 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially12 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially12Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially12Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially13 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially13 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially13 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially13 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially13 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially13 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially13 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially13 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially13 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially13 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially13Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially13Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially14 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially14 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially14 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially14 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially14 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially14 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially14 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially14 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially14 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially14Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially14Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially15 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially15 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially15 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially15 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially15 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially15 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially15 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially15 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially15Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially15Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially16 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially16 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially16 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially16 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially16 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially16 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially16 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially16Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially16Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially17 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially17 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially17 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially17 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially17 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially17 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially17Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially17Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially17Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially17Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially17Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially17Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially18 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially18 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially18 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially18 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially18 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially18Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially18Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially18Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially18Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially18Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially19 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially19 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially19 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially19 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially19Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially19Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially19Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially19Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially1Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially1Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially2 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially2 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially2 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially2 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially2 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially2 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially2 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially2 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially2 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially2 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially2 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially2 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially2 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially2 (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; - public static final fun partially2 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; - public static final fun partially2 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially2 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially2 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially2 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially2 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially2 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially20 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially20 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially20 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially20Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially20Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially20Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially21 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially21 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially21Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially21Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially22 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially22Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially2Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially2Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially3 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially3 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially3 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially3 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially3 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially3 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially3 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially3 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially3 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially3 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially3 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially3 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially3 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially3 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; - public static final fun partially3 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially3 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially3 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially3 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially3 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially3 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially3Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially3Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially4 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially4 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially4 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially4 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially4 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially4 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially4 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially4 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially4 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially4 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially4 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially4 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially4 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially4 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; - public static final fun partially4 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially4 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially4 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially4 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially4 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially4Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially4Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially5 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially5 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially5 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially5 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially5 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially5 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially5 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially5 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially5 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially5 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially5 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially5 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially5 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially5 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; - public static final fun partially5 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially5 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially5 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially5 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially5Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially5Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially6 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially6 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially6 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially6 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially6 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially6 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially6 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially6 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially6 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially6 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially6 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially6 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially6 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially6 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; - public static final fun partially6 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially6 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially6 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially6Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially6Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially7 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially7 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially7 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially7 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially7 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially7 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially7 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially7 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially7 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially7 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially7 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially7 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially7 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially7 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; - public static final fun partially7 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially7 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially7Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially7Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially8 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially8 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially8 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially8 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially8 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially8 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially8 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially8 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially8 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially8 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially8 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially8 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially8 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially8 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; - public static final fun partially8 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially8Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially8Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; - public static final fun partially9 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially9 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially9 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially9 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially9 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially9 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially9 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially9 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially9 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially9 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially9 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially9 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially9 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially9 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; - public static final fun partially9Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; - public static final fun partially9Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; } public final class arrow/core/PredefKt { - public static final fun emptyCombine (Larrow/typeclasses/Semigroup;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static final fun identity (Ljava/lang/Object;)Ljava/lang/Object; } public final class arrow/core/ResultKt { - public static final field deprecateZip Ljava/lang/String; - public static final fun composeErrors ([Ljava/lang/Throwable;)Ljava/lang/Throwable; public static final fun flatMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun getUnitResult ()Ljava/lang/Object; - public static final fun handleErrorWith (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun redeemWith (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function10;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function9;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function8;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function7;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static final fun zip (Ljava/lang/Object;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; } public final class arrow/core/SequenceKt { public static final fun align (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun align (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence; - public static final fun combineAll (Lkotlin/sequences/Sequence;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun crosswalk (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence; - public static final fun crosswalkMap (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/util/Map; - public static final fun crosswalkNull (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence; - public static final fun crosswalkT (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun crosswalk (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun crosswalkNull (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun filterOption (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun flatten (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; - public static final fun fold (Lkotlin/sequences/Sequence;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun foldMap (Lkotlin/sequences/Sequence;Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun ifThen (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence; public static final fun interleave (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun leftPadZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun leftPadZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; @@ -1706,38 +646,17 @@ public final class arrow/core/SequenceKt { public static final fun once (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun padZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun padZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; - public static final fun replicate (Lkotlin/sequences/Sequence;I)Lkotlin/sequences/Sequence; - public static final fun replicate (Lkotlin/sequences/Sequence;ILarrow/typeclasses/Monoid;)Lkotlin/sequences/Sequence; public static final fun rightPadZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun rightPadZip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; - public static final fun salign (Lkotlin/sequences/Sequence;Larrow/typeclasses/Semigroup;Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun salign (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Lkotlin/sequences/Sequence; public static final fun separateEither (Lkotlin/sequences/Sequence;)Lkotlin/Pair; - public static final fun separateValidated (Lkotlin/sequences/Sequence;)Lkotlin/Pair; - public static final fun sequence (Lkotlin/sequences/Sequence;)Larrow/core/Either; - public static final fun sequence (Lkotlin/sequences/Sequence;)Larrow/core/Option; - public static final fun sequence (Lkotlin/sequences/Sequence;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun sequenceEither (Lkotlin/sequences/Sequence;)Larrow/core/Either; - public static final fun sequenceOption (Lkotlin/sequences/Sequence;)Larrow/core/Option; - public static final fun sequenceValidated (Lkotlin/sequences/Sequence;Larrow/typeclasses/Semigroup;)Larrow/core/Validated; - public static final fun some (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun split (Lkotlin/sequences/Sequence;)Lkotlin/Pair; public static final fun tail (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; - public static final fun traverse (Lkotlin/sequences/Sequence;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun traverse (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverse (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseEither (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public static final fun traverseOption (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun traverseValidated (Lkotlin/sequences/Sequence;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; public static final fun unalign (Lkotlin/sequences/Sequence;)Lkotlin/Pair; public static final fun unalign (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun uniteEither (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; - public static final fun uniteValidated (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun unweave (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/sequences/Sequence; public static final fun unzip (Lkotlin/sequences/Sequence;)Lkotlin/Pair; public static final fun unzip (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; - public static final fun void (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; - public static final fun widen (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; public static final fun zip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function3;)Lkotlin/sequences/Sequence; public static final fun zip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function4;)Lkotlin/sequences/Sequence; public static final fun zip (Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function5;)Lkotlin/sequences/Sequence; @@ -1757,12 +676,10 @@ public final class arrow/core/Some : arrow/core/Option { public fun equals (Ljava/lang/Object;)Z public final fun getValue ()Ljava/lang/Object; public fun hashCode ()I - public fun isEmpty ()Z public fun toString ()Ljava/lang/String; } public final class arrow/core/Some$Companion { - public final fun getUnit ()Larrow/core/Option; } public final class arrow/core/SortedMapKKt { @@ -1773,159 +690,106 @@ public final class arrow/core/StringKt { public static final fun escaped (Ljava/lang/String;)Ljava/lang/String; } -public final class arrow/core/Tuple10 { - public static final field Companion Larrow/core/Tuple10$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple4 { + public static final field Companion Larrow/core/Tuple4$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple10; - public static synthetic fun copy$default (Larrow/core/Tuple10;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple10; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple4; + public static synthetic fun copy$default (Larrow/core/Tuple4;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple4; public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple10$Companion { +public final class arrow/core/Tuple4$Companion { } -public final class arrow/core/Tuple11 { - public static final field Companion Larrow/core/Tuple11$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple5 { + public static final field Companion Larrow/core/Tuple5$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple11; - public static synthetic fun copy$default (Larrow/core/Tuple11;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple11; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple5; + public static synthetic fun copy$default (Larrow/core/Tuple5;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple5; public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple11$Companion { +public final class arrow/core/Tuple5$Companion { } -public final class arrow/core/Tuple12 { - public static final field Companion Larrow/core/Tuple12$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple6 { + public static final field Companion Larrow/core/Tuple6$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; public final fun component5 ()Ljava/lang/Object; public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple12; - public static synthetic fun copy$default (Larrow/core/Tuple12;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple12; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple6; + public static synthetic fun copy$default (Larrow/core/Tuple6;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple6; public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple12$Companion { +public final class arrow/core/Tuple6$Companion { } -public final class arrow/core/Tuple13 { - public static final field Companion Larrow/core/Tuple13$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple7 { + public static final field Companion Larrow/core/Tuple7$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; public final fun component5 ()Ljava/lang/Object; public final fun component6 ()Ljava/lang/Object; public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple13; - public static synthetic fun copy$default (Larrow/core/Tuple13;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple13; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple7; + public static synthetic fun copy$default (Larrow/core/Tuple7;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple7; public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; public final fun getSeventh ()Ljava/lang/Object; public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple13$Companion { +public final class arrow/core/Tuple7$Companion { } -public final class arrow/core/Tuple14 { - public static final field Companion Larrow/core/Tuple14$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple8 { + public static final field Companion Larrow/core/Tuple8$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; @@ -1933,41 +797,28 @@ public final class arrow/core/Tuple14 { public final fun component6 ()Ljava/lang/Object; public final fun component7 ()Ljava/lang/Object; public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple14; - public static synthetic fun copy$default (Larrow/core/Tuple14;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple14; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple8; + public static synthetic fun copy$default (Larrow/core/Tuple8;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple8; public fun equals (Ljava/lang/Object;)Z public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; public final fun getSeventh ()Ljava/lang/Object; public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple14$Companion { +public final class arrow/core/Tuple8$Companion { } -public final class arrow/core/Tuple15 { - public static final field Companion Larrow/core/Tuple15$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V +public final class arrow/core/Tuple9 { + public static final field Companion Larrow/core/Tuple9$Companion; + public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; public final fun component2 ()Ljava/lang/Object; public final fun component3 ()Ljava/lang/Object; public final fun component4 ()Ljava/lang/Object; @@ -1976,1610 +827,139 @@ public final class arrow/core/Tuple15 { public final fun component7 ()Ljava/lang/Object; public final fun component8 ()Ljava/lang/Object; public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple15; - public static synthetic fun copy$default (Larrow/core/Tuple15;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple15; + public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple9; + public static synthetic fun copy$default (Larrow/core/Tuple9;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple9; public fun equals (Ljava/lang/Object;)Z public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; public final fun getFifth ()Ljava/lang/Object; public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; public final fun getFourth ()Ljava/lang/Object; public final fun getNinth ()Ljava/lang/Object; public final fun getSecond ()Ljava/lang/Object; public final fun getSeventh ()Ljava/lang/Object; public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class arrow/core/Tuple15$Companion { -} - -public final class arrow/core/Tuple16 { - public static final field Companion Larrow/core/Tuple16$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple16; - public static synthetic fun copy$default (Larrow/core/Tuple16;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple16; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public final class arrow/core/Tuple9$Companion { } -public final class arrow/core/Tuple16$Companion { +public final class arrow/core/TupleNKt { + public static final fun compareTo (Larrow/core/Tuple4;Larrow/core/Tuple4;)I + public static final fun compareTo (Larrow/core/Tuple5;Larrow/core/Tuple5;)I + public static final fun compareTo (Larrow/core/Tuple6;Larrow/core/Tuple6;)I + public static final fun compareTo (Larrow/core/Tuple7;Larrow/core/Tuple7;)I + public static final fun compareTo (Larrow/core/Tuple8;Larrow/core/Tuple8;)I + public static final fun compareTo (Larrow/core/Tuple9;Larrow/core/Tuple9;)I + public static final fun compareTo (Lkotlin/Pair;Lkotlin/Pair;)I + public static final fun compareTo (Lkotlin/Triple;Lkotlin/Triple;)I + public static final fun plus (Larrow/core/Tuple4;Ljava/lang/Object;)Larrow/core/Tuple5; + public static final fun plus (Larrow/core/Tuple5;Ljava/lang/Object;)Larrow/core/Tuple6; + public static final fun plus (Larrow/core/Tuple6;Ljava/lang/Object;)Larrow/core/Tuple7; + public static final fun plus (Larrow/core/Tuple7;Ljava/lang/Object;)Larrow/core/Tuple8; + public static final fun plus (Larrow/core/Tuple8;Ljava/lang/Object;)Larrow/core/Tuple9; + public static final fun plus (Lkotlin/Pair;Ljava/lang/Object;)Lkotlin/Triple; + public static final fun plus (Lkotlin/Triple;Ljava/lang/Object;)Larrow/core/Tuple4; } -public final class arrow/core/Tuple17 { - public static final field Companion Larrow/core/Tuple17$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple17; - public static synthetic fun copy$default (Larrow/core/Tuple17;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple17; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public final class arrow/core/UtilsKt { + public static final field DeprecatedAmbiguity Ljava/lang/String; + public static final field DeprecatedUnsafeAccess Ljava/lang/String; + public static final fun constant (Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; + public static final fun mapNullable (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; } -public final class arrow/core/Tuple17$Companion { +public final class arrow/core/raise/DefaultRaise : arrow/core/raise/Raise { + public fun (Z)V + public fun bind (Larrow/core/Either;)Ljava/lang/Object; + public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; + public fun bindAll (Ljava/util/Map;)Ljava/util/Map; + public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; + public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; + public final fun complete ()Z + public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun isTraced ()Z + public fun raise (Ljava/lang/Object;)Ljava/lang/Void; } -public final class arrow/core/Tuple18 { - public static final field Companion Larrow/core/Tuple18$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component18 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple18; - public static synthetic fun copy$default (Larrow/core/Tuple18;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple18; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighteenth ()Ljava/lang/Object; - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public abstract interface annotation class arrow/core/raise/DelicateRaiseApi : java/lang/annotation/Annotation { } -public final class arrow/core/Tuple18$Companion { -} - -public final class arrow/core/Tuple19 { - public static final field Companion Larrow/core/Tuple19$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component18 ()Ljava/lang/Object; - public final fun component19 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple19; - public static synthetic fun copy$default (Larrow/core/Tuple19;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple19; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighteenth ()Ljava/lang/Object; - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNineteenth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple19$Companion { -} - -public final class arrow/core/Tuple20 { - public static final field Companion Larrow/core/Tuple20$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component18 ()Ljava/lang/Object; - public final fun component19 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component20 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple20; - public static synthetic fun copy$default (Larrow/core/Tuple20;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple20; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighteenth ()Ljava/lang/Object; - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNineteenth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public final fun getTwentieth ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple20$Companion { -} - -public final class arrow/core/Tuple21 { - public static final field Companion Larrow/core/Tuple21$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component18 ()Ljava/lang/Object; - public final fun component19 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component20 ()Ljava/lang/Object; - public final fun component21 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple21; - public static synthetic fun copy$default (Larrow/core/Tuple21;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple21; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighteenth ()Ljava/lang/Object; - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNineteenth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public final fun getTwentieth ()Ljava/lang/Object; - public final fun getTwentyFirst ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple21$Companion { -} - -public final class arrow/core/Tuple22 { - public static final field Companion Larrow/core/Tuple22$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component10 ()Ljava/lang/Object; - public final fun component11 ()Ljava/lang/Object; - public final fun component12 ()Ljava/lang/Object; - public final fun component13 ()Ljava/lang/Object; - public final fun component14 ()Ljava/lang/Object; - public final fun component15 ()Ljava/lang/Object; - public final fun component16 ()Ljava/lang/Object; - public final fun component17 ()Ljava/lang/Object; - public final fun component18 ()Ljava/lang/Object; - public final fun component19 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component20 ()Ljava/lang/Object; - public final fun component21 ()Ljava/lang/Object; - public final fun component22 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple22; - public static synthetic fun copy$default (Larrow/core/Tuple22;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple22; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighteenth ()Ljava/lang/Object; - public final fun getEighth ()Ljava/lang/Object; - public final fun getEleventh ()Ljava/lang/Object; - public final fun getFifteenth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourteenth ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNineteenth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventeenth ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixteenth ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getTenth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public final fun getThirteenth ()Ljava/lang/Object; - public final fun getTwelfth ()Ljava/lang/Object; - public final fun getTwentieth ()Ljava/lang/Object; - public final fun getTwentyFirst ()Ljava/lang/Object; - public final fun getTwentySecond ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple22$Companion { -} - -public final class arrow/core/Tuple4 { - public static final field Companion Larrow/core/Tuple4$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple4; - public static synthetic fun copy$default (Larrow/core/Tuple4;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple4; - public fun equals (Ljava/lang/Object;)Z - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple4$Companion { -} - -public final class arrow/core/Tuple5 { - public static final field Companion Larrow/core/Tuple5$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple5; - public static synthetic fun copy$default (Larrow/core/Tuple5;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple5; - public fun equals (Ljava/lang/Object;)Z - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple5$Companion { -} - -public final class arrow/core/Tuple6 { - public static final field Companion Larrow/core/Tuple6$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple6; - public static synthetic fun copy$default (Larrow/core/Tuple6;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple6; - public fun equals (Ljava/lang/Object;)Z - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple6$Companion { -} - -public final class arrow/core/Tuple7 { - public static final field Companion Larrow/core/Tuple7$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple7; - public static synthetic fun copy$default (Larrow/core/Tuple7;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple7; - public fun equals (Ljava/lang/Object;)Z - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple7$Companion { -} - -public final class arrow/core/Tuple8 { - public static final field Companion Larrow/core/Tuple8$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple8; - public static synthetic fun copy$default (Larrow/core/Tuple8;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple8; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple8$Companion { -} - -public final class arrow/core/Tuple9 { - public static final field Companion Larrow/core/Tuple9$Companion; - public fun (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun component2 ()Ljava/lang/Object; - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Ljava/lang/Object; - public final fun component5 ()Ljava/lang/Object; - public final fun component6 ()Ljava/lang/Object; - public final fun component7 ()Ljava/lang/Object; - public final fun component8 ()Ljava/lang/Object; - public final fun component9 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Larrow/core/Tuple9; - public static synthetic fun copy$default (Larrow/core/Tuple9;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Tuple9; - public fun equals (Ljava/lang/Object;)Z - public final fun getEighth ()Ljava/lang/Object; - public final fun getFifth ()Ljava/lang/Object; - public final fun getFirst ()Ljava/lang/Object; - public final fun getFourth ()Ljava/lang/Object; - public final fun getNinth ()Ljava/lang/Object; - public final fun getSecond ()Ljava/lang/Object; - public final fun getSeventh ()Ljava/lang/Object; - public final fun getSixth ()Ljava/lang/Object; - public final fun getThird ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Tuple9$Companion { -} - -public final class arrow/core/TupleNKt { - public static final fun combine (Lkotlin/Pair;Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;Lkotlin/Pair;)Lkotlin/Pair; - public static final fun compareTo (Larrow/core/Tuple10;Larrow/core/Tuple10;)I - public static final fun compareTo (Larrow/core/Tuple4;Larrow/core/Tuple4;)I - public static final fun compareTo (Larrow/core/Tuple5;Larrow/core/Tuple5;)I - public static final fun compareTo (Larrow/core/Tuple6;Larrow/core/Tuple6;)I - public static final fun compareTo (Larrow/core/Tuple7;Larrow/core/Tuple7;)I - public static final fun compareTo (Larrow/core/Tuple8;Larrow/core/Tuple8;)I - public static final fun compareTo (Larrow/core/Tuple9;Larrow/core/Tuple9;)I - public static final fun compareTo (Lkotlin/Pair;Lkotlin/Pair;)I - public static final fun compareTo (Lkotlin/Triple;Lkotlin/Triple;)I - public static final fun plus (Larrow/core/Tuple10;Ljava/lang/Object;)Larrow/core/Tuple11; - public static final fun plus (Larrow/core/Tuple11;Ljava/lang/Object;)Larrow/core/Tuple12; - public static final fun plus (Larrow/core/Tuple12;Ljava/lang/Object;)Larrow/core/Tuple13; - public static final fun plus (Larrow/core/Tuple13;Ljava/lang/Object;)Larrow/core/Tuple14; - public static final fun plus (Larrow/core/Tuple14;Ljava/lang/Object;)Larrow/core/Tuple15; - public static final fun plus (Larrow/core/Tuple15;Ljava/lang/Object;)Larrow/core/Tuple16; - public static final fun plus (Larrow/core/Tuple16;Ljava/lang/Object;)Larrow/core/Tuple17; - public static final fun plus (Larrow/core/Tuple17;Ljava/lang/Object;)Larrow/core/Tuple18; - public static final fun plus (Larrow/core/Tuple18;Ljava/lang/Object;)Larrow/core/Tuple19; - public static final fun plus (Larrow/core/Tuple19;Ljava/lang/Object;)Larrow/core/Tuple20; - public static final fun plus (Larrow/core/Tuple20;Ljava/lang/Object;)Larrow/core/Tuple21; - public static final fun plus (Larrow/core/Tuple21;Ljava/lang/Object;)Larrow/core/Tuple22; - public static final fun plus (Larrow/core/Tuple4;Ljava/lang/Object;)Larrow/core/Tuple5; - public static final fun plus (Larrow/core/Tuple5;Ljava/lang/Object;)Larrow/core/Tuple6; - public static final fun plus (Larrow/core/Tuple6;Ljava/lang/Object;)Larrow/core/Tuple7; - public static final fun plus (Larrow/core/Tuple7;Ljava/lang/Object;)Larrow/core/Tuple8; - public static final fun plus (Larrow/core/Tuple8;Ljava/lang/Object;)Larrow/core/Tuple9; - public static final fun plus (Larrow/core/Tuple9;Ljava/lang/Object;)Larrow/core/Tuple10; - public static final fun plus (Lkotlin/Pair;Ljava/lang/Object;)Lkotlin/Triple; - public static final fun plus (Lkotlin/Triple;Ljava/lang/Object;)Larrow/core/Tuple4; -} - -public final class arrow/core/UtilsKt { - public static final field DeprecatedAmbiguity Ljava/lang/String; - public static final field DeprecatedUnsafeAccess Ljava/lang/String; - public static final field DeprecatedWiden Ljava/lang/String; - public static final fun constant (Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; - public static final fun mapNullable (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; -} - -public abstract class arrow/core/Validated { - public static final field Companion Larrow/core/Validated$Companion; - public final fun all (Lkotlin/jvm/functions/Function1;)Z - public final fun bifoldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun bifoldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun bimap (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun bitraverse (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun bitraverseEither (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun bitraverseNullable (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun bitraverseOption (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun catchNel (Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun exist (Lkotlin/jvm/functions/Function1;)Z - public final fun findOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun foldMap (Larrow/typeclasses/Monoid;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun fromEither (Larrow/core/Either;)Larrow/core/Validated; - public static final fun fromNullable (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun fromOption (Larrow/core/Option;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun invalidNel (Ljava/lang/Object;)Larrow/core/Validated; - public final fun isEmpty ()Z - public final fun isInvalid ()Z - public final fun isNotEmpty ()Z - public final fun isValid ()Z - public static final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun mapLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun swap ()Larrow/core/Validated; - public final fun tap (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun tapInvalid (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun toEither ()Larrow/core/Either; - public final fun toList ()Ljava/util/List; - public final fun toOption ()Larrow/core/Option; - public fun toString ()Ljava/lang/String; - public final fun toValidatedNel ()Larrow/core/Validated; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public final fun traverse (Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public final fun traverseEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; - public final fun traverseNullable (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public final fun traverseOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun tryCatch (Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun validNel (Ljava/lang/Object;)Larrow/core/Validated; - public final fun void ()Larrow/core/Validated; - public final fun withEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; -} - -public final class arrow/core/Validated$Companion { - public final fun catchNel (Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun fromEither (Larrow/core/Either;)Larrow/core/Validated; - public final fun fromNullable (Ljava/lang/Object;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun fromOption (Larrow/core/Option;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun invalidNel (Ljava/lang/Object;)Larrow/core/Validated; - public final fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun lift (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public final fun tryCatch (Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun tryCatch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public final fun validNel (Ljava/lang/Object;)Larrow/core/Validated; -} - -public final class arrow/core/Validated$Invalid : arrow/core/Validated { - public fun (Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;)Larrow/core/Validated$Invalid; - public static synthetic fun copy$default (Larrow/core/Validated$Invalid;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Validated$Invalid; - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Validated$Valid : arrow/core/Validated { - public static final field Companion Larrow/core/Validated$Valid$Companion; - public fun (Ljava/lang/Object;)V - public final fun component1 ()Ljava/lang/Object; - public final fun copy (Ljava/lang/Object;)Larrow/core/Validated$Valid; - public static synthetic fun copy$default (Larrow/core/Validated$Valid;Ljava/lang/Object;ILjava/lang/Object;)Larrow/core/Validated$Valid; - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Ljava/lang/Object; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/Validated$Valid$Companion { - public final fun getUnit ()Larrow/core/Validated; -} - -public final class arrow/core/ValidatedKt { - public static final field DeprAndNicheMsg Ljava/lang/String; - public static final field ValidatedDeprMsg Ljava/lang/String; - public static final fun andThen (Larrow/core/Validated;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun attempt (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun bisequence (Larrow/core/Validated;)Ljava/util/List; - public static final fun bisequenceEither (Larrow/core/Validated;)Larrow/core/Either; - public static final fun bisequenceNullable (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun bisequenceOption (Larrow/core/Validated;)Larrow/core/Option; - public static final fun combine (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;Larrow/core/Validated;)Larrow/core/Validated; - public static final fun combineAll (Larrow/core/Validated;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun combineK (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;)Larrow/core/Validated; - public static final fun compareTo (Larrow/core/Validated;Larrow/core/Validated;)I - public static final fun findValid (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun fold (Larrow/core/Validated;Larrow/typeclasses/Monoid;)Ljava/lang/Object; - public static final fun getOrElse (Larrow/core/Validated;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; - public static final fun handleError (Larrow/core/Validated;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun handleErrorWith (Larrow/core/Validated;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun invalid (Ljava/lang/Object;)Larrow/core/Validated; - public static final fun invalidNel (Ljava/lang/Object;)Larrow/core/Validated; - public static final fun leftWiden (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun merge (Larrow/core/Validated;)Ljava/lang/Object; - public static final fun orElse (Larrow/core/Validated;Lkotlin/jvm/functions/Function0;)Larrow/core/Validated; - public static final fun orNone (Larrow/core/Validated;)Larrow/core/Option; - public static final fun orNull (Larrow/core/Validated;)Ljava/lang/Object; - public static final fun redeem (Larrow/core/Validated;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun replicate (Larrow/core/Validated;Larrow/typeclasses/Semigroup;I)Larrow/core/Validated; - public static final fun replicate (Larrow/core/Validated;Larrow/typeclasses/Semigroup;ILarrow/typeclasses/Monoid;)Larrow/core/Validated; - public static final fun sequence (Larrow/core/Validated;)Larrow/core/Either; - public static final fun sequence (Larrow/core/Validated;)Larrow/core/Option; - public static final fun sequence (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun sequence (Larrow/core/Validated;)Ljava/util/List; - public static final fun sequenceEither (Larrow/core/Validated;)Larrow/core/Either; - public static final fun sequenceNullable (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun sequenceOption (Larrow/core/Validated;)Larrow/core/Option; - public static final fun toIor (Larrow/core/Validated;)Larrow/core/Ior; - public static final fun valid (Ljava/lang/Object;)Larrow/core/Validated; - public static final fun validNel (Ljava/lang/Object;)Larrow/core/Validated; - public static final fun valueOr (Larrow/core/Validated;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun widen (Larrow/core/Validated;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function10;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function9;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function8;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function7;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function6;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function5;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function4;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function3;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function2;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function10;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function9;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function8;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function7;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function6;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function5;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function4;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Larrow/core/Validated;Lkotlin/jvm/functions/Function3;)Larrow/core/Validated; - public static final fun zip (Larrow/core/Validated;Larrow/typeclasses/Semigroup;Larrow/core/Validated;Lkotlin/jvm/functions/Function2;)Larrow/core/Validated; -} - -public abstract interface class arrow/core/computations/EitherEffect : arrow/continuations/Effect { - public abstract fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/EitherEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/EitherEffect;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/EitherEffect;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/EitherEffect;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/EitherEffect;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/EitherKt { - public static final field eitherDSLDeprecation Ljava/lang/String; - public static final fun ensureNotNull (Larrow/core/computations/EitherEffect;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/EvalEffect : arrow/continuations/Effect { - public abstract fun bind (Larrow/core/Eval;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/EvalEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/EvalEffect;Larrow/core/Eval;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/NullableEffect : arrow/continuations/Effect { - public abstract fun bind (Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun ensure (ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/NullableEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/NullableEffect;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/NullableEffect;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/NullableEffect;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/NullableKt { - public static final field nullableDSLDeprecation Ljava/lang/String; - public static final fun ensureNotNull (Larrow/core/computations/NullableEffect;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/OptionEffect : arrow/continuations/Effect { - public abstract fun bind (Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun ensure (ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/OptionEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/OptionEffect;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/OptionEffect;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/OptionKt { - public static final field optionDSLDeprecation Ljava/lang/String; - public static final fun ensureNotNull (Larrow/core/computations/OptionEffect;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/RestrictedEitherEffect : arrow/core/computations/EitherEffect { -} - -public final class arrow/core/computations/RestrictedEitherEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/RestrictedEitherEffect;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/RestrictedEitherEffect;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/RestrictedEitherEffect;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/RestrictedEitherEffect;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/RestrictedEvalEffect : arrow/core/computations/EvalEffect { -} - -public final class arrow/core/computations/RestrictedEvalEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/RestrictedEvalEffect;Larrow/core/Eval;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/RestrictedNullableEffect : arrow/core/computations/NullableEffect { -} - -public final class arrow/core/computations/RestrictedNullableEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/RestrictedNullableEffect;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/computations/RestrictedNullableEffect;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/RestrictedNullableEffect;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/computations/RestrictedOptionEffect : arrow/core/computations/OptionEffect { -} - -public final class arrow/core/computations/RestrictedOptionEffect$DefaultImpls { - public static fun bind (Larrow/core/computations/RestrictedOptionEffect;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/computations/RestrictedOptionEffect;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/ResultEffect { - public static final field INSTANCE Larrow/core/computations/ResultEffect; - public final fun bind (Larrow/core/Either;)Ljava/lang/Object; - public final fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public final fun bind (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/core/computations/ResultKt { - public static final field resultDSLDeprecation Ljava/lang/String; -} - -public final class arrow/core/computations/either { - public static final field INSTANCE Larrow/core/computations/either; - public final fun eager (Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/eval { - public static final field INSTANCE Larrow/core/computations/eval; - public final fun eager (Lkotlin/jvm/functions/Function2;)Larrow/core/Eval; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/nullable { - public static final field INSTANCE Larrow/core/computations/nullable; - public final fun eager (Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/option { - public static final field INSTANCE Larrow/core/computations/option; - public final fun eager (Lkotlin/jvm/functions/Function2;)Larrow/core/Option; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/computations/result { - public static final field INSTANCE Larrow/core/computations/result; - public final fun invoke-IoAF18A (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/AtomicRefKt { - public static final fun getAndUpdate (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun loop (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Void; - public static final fun update (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)V - public static final fun updateAndGet (Ljava/util/concurrent/atomic/AtomicReference;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; -} - -public class arrow/core/continuations/CancellationExceptionNoTrace : java/util/concurrent/CancellationException { - public fun ()V - public fun fillInStackTrace ()Ljava/lang/Throwable; -} - -public final class arrow/core/continuations/Eager : arrow/core/continuations/ShiftCancellationException { - public fun (Larrow/core/continuations/Token;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V - public final fun getRecover ()Lkotlin/jvm/functions/Function1; - public final fun getShifted ()Ljava/lang/Object; - public final fun getToken ()Larrow/core/continuations/Token; - public fun toString ()Ljava/lang/String; -} - -public abstract interface class arrow/core/continuations/EagerEffect { - public abstract fun attempt ()Larrow/core/continuations/EagerEffect; - public abstract fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun handleError (Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun handleErrorWith (Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun orNull ()Ljava/lang/Object; - public abstract fun redeem (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun redeemWith (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public abstract fun toEither ()Larrow/core/Either; - public abstract fun toIor ()Larrow/core/Ior; - public abstract fun toOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public abstract fun toValidated ()Larrow/core/Validated; -} - -public final class arrow/core/continuations/EagerEffect$DefaultImpls { - public static fun attempt (Larrow/core/continuations/EagerEffect;)Larrow/core/continuations/EagerEffect; - public static fun flatMap (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun fold (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun handleError (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun handleErrorWith (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun map (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun orNull (Larrow/core/continuations/EagerEffect;)Ljava/lang/Object; - public static fun redeem (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun redeemWith (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/core/continuations/EagerEffect; - public static fun toEither (Larrow/core/continuations/EagerEffect;)Larrow/core/Either; - public static fun toIor (Larrow/core/continuations/EagerEffect;)Larrow/core/Ior; - public static fun toOption (Larrow/core/continuations/EagerEffect;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static fun toValidated (Larrow/core/continuations/EagerEffect;)Larrow/core/Validated; -} - -public final class arrow/core/continuations/EagerEffectKt { - public static final fun eagerEffect (Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/EagerEffect; - public static final fun merge (Larrow/core/continuations/EagerEffect;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/continuations/EagerEffectScope { - public abstract fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public abstract fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EagerEffectScope$DefaultImpls { - public static fun attempt (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun catch (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun ensure (Larrow/core/continuations/EagerEffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EagerEffectScopeKt { - public static final fun ensureNotNull (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/continuations/Effect { - public abstract fun attempt ()Larrow/core/continuations/Effect; - public abstract fun fold (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun fold (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun handleError (Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public abstract fun handleErrorWith (Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public abstract fun orNull (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun redeem (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public abstract fun redeemWith (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public abstract fun toEither (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun toIor (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun toOption (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun toValidated (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/Effect$DefaultImpls { - public static fun attempt (Larrow/core/continuations/Effect;)Larrow/core/continuations/Effect; - public static fun fold (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun handleError (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public static fun handleErrorWith (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public static fun orNull (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun redeem (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public static fun redeemWith (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public static fun toEither (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun toIor (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun toOption (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun toValidated (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EffectKt { - public static final fun effect (Lkotlin/jvm/functions/Function2;)Larrow/core/continuations/Effect; - public static final fun merge (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface class arrow/core/continuations/EffectScope { - public abstract fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EffectScope$DefaultImpls { - public static fun attempt (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun catch (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure (Larrow/core/continuations/EffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun recover (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EffectScopeKt { - public static final fun ensureNotNull (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/EitherKt { - public static final field eitherDSLDeprecation Ljava/lang/String; -} - -public final class arrow/core/continuations/FoldContinuation : arrow/core/continuations/Token, arrow/core/continuations/EffectScope, kotlin/coroutines/Continuation { - public field recover Lkotlin/jvm/functions/Function2; - public fun (Larrow/core/continuations/Token;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)V - public fun (Larrow/core/continuations/Token;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V - public fun (Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun getContext ()Lkotlin/coroutines/CoroutineContext; - public final fun getRecover ()Lkotlin/jvm/functions/Function2; - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun resumeWith (Ljava/lang/Object;)V - public final fun setRecover (Lkotlin/jvm/functions/Function2;)V - public fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/IorEagerEffectScope : arrow/core/continuations/EagerEffectScope, arrow/typeclasses/Semigroup { - public fun (Larrow/typeclasses/Semigroup;Larrow/core/continuations/EagerEffectScope;)V - public fun append (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun bind (Larrow/core/Ior;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun getLeftState ()Ljava/util/concurrent/atomic/AtomicReference; - public fun maybeCombine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public final fun setLeftState (Ljava/util/concurrent/atomic/AtomicReference;)V - public fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/IorEffectScope : arrow/core/continuations/EffectScope, arrow/typeclasses/Semigroup { - public fun (Larrow/typeclasses/Semigroup;Larrow/core/continuations/EffectScope;)V - public fun append (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun bind (Larrow/core/Ior;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun getLeftState ()Ljava/util/concurrent/atomic/AtomicReference; - public fun maybeCombine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun setLeftState (Ljava/util/concurrent/atomic/AtomicReference;)V - public fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/IorKt { - public static final field iorDSLDeprecation Ljava/lang/String; -} - -public final class arrow/core/continuations/NullableEagerEffectScope : arrow/core/continuations/EagerEffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/NullableEagerEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/EagerEffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensure-impl (Larrow/core/continuations/EagerEffectScope;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EagerEffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EagerEffectScope;)I - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Ljava/lang/Void;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Void;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EagerEffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EagerEffectScope; -} - -public final class arrow/core/continuations/NullableEffectScope : arrow/core/continuations/EffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/NullableEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/EffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensure-impl (Larrow/core/continuations/EffectScope;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EffectScope;)I - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun recover-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Ljava/lang/Void;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Void;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EffectScope; -} - -public final class arrow/core/continuations/NullableKt { - public static final field nullableDSLDeprecation Ljava/lang/String; - public static final fun ensureNotNull-0Rsnnio (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensureNotNull-7s8y1X8 (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/OptionEagerEffectScope : arrow/core/continuations/EagerEffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/OptionEagerEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/EagerEffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensure-impl (Larrow/core/continuations/EagerEffectScope;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EagerEffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EagerEffectScope;)I - public fun shift (Larrow/core/None;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/None;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EagerEffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EagerEffectScope; -} - -public final class arrow/core/continuations/OptionEffectScope : arrow/core/continuations/EffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/OptionEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/EffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensure-impl (Larrow/core/continuations/EffectScope;ZLkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EffectScope;)I - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun recover-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Larrow/core/None;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EffectScope;Larrow/core/None;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EffectScope; -} - -public final class arrow/core/continuations/OptionKt { - public static final field optionDSLDeprecation Ljava/lang/String; - public static final fun ensureNotNull-09sQPHg (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun ensureNotNull-dxZa7OQ (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun toOption (Larrow/core/continuations/EagerEffect;)Larrow/core/Option; - public static final fun toOption (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/ResultEagerEffectScope : arrow/core/continuations/EagerEffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/ResultEagerEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EagerEffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EagerEffectScope;)Larrow/core/continuations/EagerEffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EagerEffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EagerEffectScope;Larrow/core/continuations/EagerEffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EagerEffectScope;)I - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Ljava/lang/Throwable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EagerEffectScope;Ljava/lang/Throwable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EagerEffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EagerEffectScope; -} - -public final class arrow/core/continuations/ResultEffectScope : arrow/core/continuations/EffectScope { - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun attempt-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Either;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Option;Lkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/Validated;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun bind-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final synthetic fun box-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/ResultEffectScope; - public fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun catch-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun constructor-impl (Larrow/core/continuations/EffectScope;)Larrow/core/continuations/EffectScope; - public fun ensure (ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun ensure-impl (Larrow/core/continuations/EffectScope;ZLkotlin/jvm/functions/Function0;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Larrow/core/continuations/EffectScope;Larrow/core/continuations/EffectScope;)Z - public fun hashCode ()I - public static fun hashCode-impl (Larrow/core/continuations/EffectScope;)I - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun recover-impl (Larrow/core/continuations/EffectScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Ljava/lang/Throwable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift-impl (Larrow/core/continuations/EffectScope;Ljava/lang/Throwable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Larrow/core/continuations/EffectScope;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Larrow/core/continuations/EffectScope; -} - -public final class arrow/core/continuations/ResultKt { - public static final field resultDSLDeprecation Ljava/lang/String; - public static final fun toResult (Larrow/core/continuations/EagerEffect;)Ljava/lang/Object; - public static final fun toResult (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract class arrow/core/continuations/ShiftCancellationException : arrow/core/continuations/CancellationExceptionNoTrace { -} - -public final class arrow/core/continuations/ShiftLeakedException : java/lang/IllegalStateException { - public fun ()V -} - -public final class arrow/core/continuations/Suspend : arrow/core/continuations/ShiftCancellationException { - public fun (Larrow/core/continuations/Token;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V - public final fun getRecover ()Lkotlin/jvm/functions/Function2; - public final fun getShifted ()Ljava/lang/Object; - public final fun getToken ()Larrow/core/continuations/Token; - public fun toString ()Ljava/lang/String; -} - -public class arrow/core/continuations/Token { - public fun ()V - public fun toString ()Ljava/lang/String; -} - -public final class arrow/core/continuations/either { - public static final field INSTANCE Larrow/core/continuations/either; - public final fun eager (Lkotlin/jvm/functions/Function2;)Larrow/core/Either; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/ior { - public static final field INSTANCE Larrow/core/continuations/ior; - public final fun eager (Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function2;)Larrow/core/Ior; - public final fun invoke (Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/nullable { - public static final field INSTANCE Larrow/core/continuations/nullable; - public final fun eager (Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/option { - public static final field INSTANCE Larrow/core/continuations/option; - public final fun eager (Lkotlin/jvm/functions/Function2;)Larrow/core/Option; - public final fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/continuations/result { - public static final field INSTANCE Larrow/core/continuations/result; - public final fun eager-IoAF18A (Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public final fun invoke-gIAlu-s (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/core/raise/DefaultRaise : arrow/core/raise/Raise { - public fun (Z)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; - public fun bindAll (Ljava/util/Map;)Ljava/util/Map; - public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun complete ()Z - public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun isTraced ()Z - public fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public fun shift (Ljava/lang/Object;)Ljava/lang/Object; -} - -public abstract interface annotation class arrow/core/raise/DelicateRaiseApi : java/lang/annotation/Annotation { -} - -public abstract interface annotation class arrow/core/raise/ExperimentalTraceApi : java/lang/annotation/Annotation { -} - -public final class arrow/core/raise/IgnoreErrorsRaise : arrow/core/raise/Raise { - public fun (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function0;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public final fun bind (Larrow/core/Option;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun bind (Ljava/lang/Object;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; - public fun bindAll (Ljava/util/Map;)Ljava/util/Map; - public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun ensure (Z)V - public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public fun shift (Ljava/lang/Object;)Ljava/lang/Object; +public abstract interface annotation class arrow/core/raise/ExperimentalTraceApi : java/lang/annotation/Annotation { } public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise { public fun (Lkotlin/jvm/functions/Function2;Ljava/util/concurrent/atomic/AtomicReference;Larrow/core/raise/Raise;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; public final fun bind (Larrow/core/Ior;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; public fun bindAll (Ljava/util/Map;)Ljava/util/Map; public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public final fun bindAllIor (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; public final fun bindAllIor (Ljava/lang/Iterable;)Ljava/util/List; + public final fun bindAllIor (Ljava/util/List;)Ljava/util/List; public final fun bindAllIor (Ljava/util/Map;)Ljava/util/Map; public final fun bindAllIor (Ljava/util/Set;)Ljava/util/Set; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun combine (Ljava/lang/Object;)Ljava/lang/Object; public final fun getCombineError ()Lkotlin/jvm/functions/Function2; public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun raise (Ljava/lang/Object;)Ljava/lang/Void; public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun shift (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/core/raise/NullableRaise : arrow/core/raise/Raise { - public fun (Larrow/core/raise/Raise;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public final fun bind (Larrow/core/Option;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun bind (Ljava/lang/Object;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; - public fun bindAll (Ljava/util/Map;)Ljava/util/Map; - public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public final fun bindAllNullable (Ljava/lang/Iterable;)Ljava/util/List; - public final fun bindAllNullable (Ljava/util/Map;)Ljava/util/Map; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun ensure (Z)V - public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object; - public final fun ignoreErrors (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public fun raise (Ljava/lang/Void;)Ljava/lang/Void; - public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;)Ljava/lang/Object; - public fun shift (Ljava/lang/Void;)Ljava/lang/Object; -} - -public final class arrow/core/raise/OptionRaise : arrow/core/raise/Raise { - public fun (Larrow/core/raise/Raise;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public final fun bind (Larrow/core/Option;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; - public fun bindAll (Ljava/util/Map;)Ljava/util/Map; - public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public final fun bindAllOption (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun bindAllOption (Ljava/lang/Iterable;)Ljava/util/List; - public final fun bindAllOption (Ljava/util/Map;)Ljava/util/Map; - public final fun bindAllOption (Ljava/util/Set;)Ljava/util/Set; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun ensure (Z)V - public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object; - public final fun ignoreErrors (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun raise (Larrow/core/None;)Ljava/lang/Void; - public synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; - public fun shift (Larrow/core/None;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface class arrow/core/raise/Raise { - public abstract fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun bind (Larrow/core/Either;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public abstract fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; public abstract fun bindAll (Ljava/util/Map;)Ljava/util/Map; public abstract fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public abstract fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public abstract fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public abstract fun shift (Ljava/lang/Object;)Ljava/lang/Object; } public final class arrow/core/raise/Raise$DefaultImpls { - public static fun attempt (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun bind (Larrow/core/raise/Raise;Larrow/core/Either;)Ljava/lang/Object; - public static fun bind (Larrow/core/raise/Raise;Larrow/core/Validated;)Ljava/lang/Object; - public static fun bind (Larrow/core/raise/Raise;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun bind (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bindAll (Larrow/core/raise/Raise;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public static fun bindAll (Larrow/core/raise/Raise;Ljava/lang/Iterable;)Ljava/util/List; public static fun bindAll (Larrow/core/raise/Raise;Ljava/util/Map;)Ljava/util/Map; public static fun bindAll-1TN0_VU (Larrow/core/raise/Raise;Ljava/util/Set;)Ljava/util/Set; - public static fun catch (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun bindAll-vcjLgH4 (Larrow/core/raise/Raise;Ljava/util/List;)Ljava/util/List; public static fun invoke (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun invoke (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun shift (Larrow/core/raise/Raise;Ljava/lang/Object;)Ljava/lang/Object; } public class arrow/core/raise/RaiseAccumulate : arrow/core/raise/Raise { public fun (Larrow/core/raise/Raise;)V - public final fun _mapOrAccumulate (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; public final fun _mapOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public final fun _mapOrAccumulate (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public final fun _mapOrAccumulate (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/Set; - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; public fun bindAll (Ljava/util/Map;)Ljava/util/Map; public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; + public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; public final fun bindNel (Larrow/core/Either;)Ljava/lang/Object; - public final fun bindNel (Larrow/core/Validated;)Ljava/lang/Object; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun getRaise ()Larrow/core/raise/Raise; public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun mapOrAccumulate (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; public final fun mapOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public final fun mapOrAccumulate-FrVv2gs (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public final fun mapOrAccumulate-nfMsDo0 (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/Set; public fun raise (Ljava/lang/Object;)Ljava/lang/Void; - public fun shift (Ljava/lang/Object;)Ljava/lang/Object; public final fun withNel (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } @@ -3618,15 +998,15 @@ public final class arrow/core/raise/RaiseKt { public static final fun get (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun get (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun getOrElse (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun getOrElse (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun getOrElse (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun getOrNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun getOrNull (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun impure (Lkotlin/jvm/functions/Function1;)V public static final fun ior (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; public static final fun iorNel (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; public static synthetic fun iorNel$default (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Larrow/core/Ior; public static final fun mapError (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static final fun mapError (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; - public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Ljava/util/Map; @@ -3634,18 +1014,18 @@ public final class arrow/core/raise/RaiseKt { public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun mapOrAccumulate--YW8gn4 (Larrow/core/raise/Raise;Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Ljava/util/Set; + public static final fun mapOrAccumulate-l8IBlHg (Larrow/core/raise/Raise;Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static final fun merge (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun merge (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun nullable (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun option (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; - public static final fun orNull (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun orNull (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun raisedOrRethrow (Ljava/util/concurrent/CancellationException;Larrow/core/raise/DefaultRaise;)Ljava/lang/Object; public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1; public static final fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2; public static final fun result (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun singleton (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun toEither (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun toEither (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun toIor (Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; @@ -3656,8 +1036,6 @@ public final class arrow/core/raise/RaiseKt { public static final fun toResult (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun toResult (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun toResult (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun toValidated (Lkotlin/jvm/functions/Function1;)Larrow/core/Validated; - public static final fun toValidated (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun traced (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun withCause (Larrow/core/raise/Traced;Larrow/core/raise/Traced;)Larrow/core/raise/Traced; public static final fun withError (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; @@ -3681,30 +1059,52 @@ public final class arrow/core/raise/RaiseKt { public final class arrow/core/raise/ResultRaise : arrow/core/raise/Raise { public fun (Larrow/core/raise/Raise;)V - public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Validated;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bind (Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public final fun bind (Ljava/lang/Object;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun bindAll (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; public fun bindAll (Ljava/util/Map;)Ljava/util/Map; public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; - public final fun bindAllResult (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; public final fun bindAllResult (Ljava/lang/Iterable;)Ljava/util/List; + public final fun bindAllResult (Ljava/util/List;)Ljava/util/List; public final fun bindAllResult (Ljava/util/Map;)Ljava/util/Map; public final fun bindAllResult (Ljava/util/Set;)Ljava/util/Set; - public fun catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public synthetic fun raise (Ljava/lang/Object;)Ljava/lang/Void; public fun raise (Ljava/lang/Throwable;)Ljava/lang/Void; public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public synthetic fun shift (Ljava/lang/Object;)Ljava/lang/Object; - public fun shift (Ljava/lang/Throwable;)Ljava/lang/Object; +} + +public final class arrow/core/raise/SingletonRaise : arrow/core/raise/Raise { + public fun (Larrow/core/raise/Raise;)V + public fun bind (Larrow/core/Either;)Ljava/lang/Object; + public final fun bind (Larrow/core/Option;)Ljava/lang/Object; + public final fun bind (Ljava/lang/Object;)Ljava/lang/Object; + public fun bind (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun bindAll (Ljava/lang/Iterable;)Ljava/util/List; + public fun bindAll (Ljava/util/Map;)Ljava/util/Map; + public fun bindAll-1TN0_VU (Ljava/util/Set;)Ljava/util/Set; + public fun bindAll-vcjLgH4 (Ljava/util/List;)Ljava/util/List; + public final fun bindAllNullable (Ljava/lang/Iterable;)Ljava/util/List; + public final fun bindAllNullable (Ljava/util/List;)Ljava/util/List; + public final fun bindAllNullable (Ljava/util/Map;)Ljava/util/Map; + public final fun bindAllNullable (Ljava/util/Set;)Ljava/util/Set; + public final fun bindAllOption (Ljava/lang/Iterable;)Ljava/util/List; + public final fun bindAllOption (Ljava/util/List;)Ljava/util/List; + public final fun bindAllOption (Ljava/util/Map;)Ljava/util/Map; + public final fun bindAllOption (Ljava/util/Set;)Ljava/util/Set; + public final fun ensure (Z)V + public final fun ensureNotNull (Ljava/lang/Object;)Ljava/lang/Object; + public final fun ignoreErrors (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public fun invoke (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public final fun raise ()Ljava/lang/Void; + public fun raise (Ljava/lang/Object;)Ljava/lang/Void; + public final fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object; } public final class arrow/core/raise/Trace { @@ -3723,164 +1123,3 @@ public final class arrow/core/raise/Trace { public final synthetic fun unbox-impl ()Ljava/util/concurrent/CancellationException; } -public abstract interface class arrow/typeclasses/Monoid : arrow/typeclasses/Semigroup { - public static final field Companion Larrow/typeclasses/Monoid$Companion; - public static fun Boolean ()Larrow/typeclasses/Monoid; - public static fun Byte ()Larrow/typeclasses/Monoid; - public static fun Integer ()Larrow/typeclasses/Monoid; - public static fun Long ()Larrow/typeclasses/Monoid; - public static fun Short ()Larrow/typeclasses/Monoid; - public abstract fun combineAll (Ljava/util/Collection;)Ljava/lang/Object; - public abstract fun combineAll (Ljava/util/List;)Ljava/lang/Object; - public static fun constant (Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public static fun either (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public abstract fun empty ()Ljava/lang/Object; - public static fun endo ()Larrow/typeclasses/Monoid; - public abstract fun fold (Ljava/util/Collection;)Ljava/lang/Object; - public abstract fun fold (Ljava/util/List;)Ljava/lang/Object; - public static fun list ()Larrow/typeclasses/Monoid; - public static fun map (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Monoid; - public static fun option (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Monoid; - public static fun pair (Larrow/typeclasses/Monoid;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public static fun sequence ()Larrow/typeclasses/Monoid; - public static fun string ()Larrow/typeclasses/Monoid; - public static fun validated (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; -} - -public final class arrow/typeclasses/Monoid$Companion { - public final fun Boolean ()Larrow/typeclasses/Monoid; - public final fun Byte ()Larrow/typeclasses/Monoid; - public final fun Integer ()Larrow/typeclasses/Monoid; - public final fun Long ()Larrow/typeclasses/Monoid; - public final fun Short ()Larrow/typeclasses/Monoid; - public final fun constant (Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public final synthetic fun either (Larrow/typeclasses/Monoid;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public final fun either (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public final fun endo ()Larrow/typeclasses/Monoid; - public final fun list ()Larrow/typeclasses/Monoid; - public final fun map (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Monoid; - public final fun option (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Monoid; - public final fun pair (Larrow/typeclasses/Monoid;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; - public final fun sequence ()Larrow/typeclasses/Monoid; - public final fun string ()Larrow/typeclasses/Monoid; - public final fun validated (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Monoid;)Larrow/typeclasses/Monoid; -} - -public final class arrow/typeclasses/Monoid$DefaultImpls { - public static fun append (Larrow/typeclasses/Monoid;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun combineAll (Larrow/typeclasses/Monoid;Ljava/util/Collection;)Ljava/lang/Object; - public static fun combineAll (Larrow/typeclasses/Monoid;Ljava/util/List;)Ljava/lang/Object; - public static fun fold (Larrow/typeclasses/Monoid;Ljava/util/Collection;)Ljava/lang/Object; - public static fun fold (Larrow/typeclasses/Monoid;Ljava/util/List;)Ljava/lang/Object; - public static fun maybeCombine (Larrow/typeclasses/Monoid;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Larrow/typeclasses/Monoid;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/typeclasses/MonoidKt { - public static final field MonoidDeprecation Ljava/lang/String; -} - -public abstract interface class arrow/typeclasses/Semigroup { - public static final field Companion Larrow/typeclasses/Semigroup$Companion; - public static fun Boolean ()Larrow/typeclasses/Semigroup; - public static fun Byte ()Larrow/typeclasses/Semigroup; - public static fun Integer ()Larrow/typeclasses/Semigroup; - public static fun Long ()Larrow/typeclasses/Semigroup; - public static fun Short ()Larrow/typeclasses/Semigroup; - public abstract fun append (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun constant (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public static fun either (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public static fun endo ()Larrow/typeclasses/Semigroup; - public static fun ior (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public static fun list ()Larrow/typeclasses/Semigroup; - public static fun map (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public abstract fun maybeCombine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun nonEmptyList ()Larrow/typeclasses/Semigroup; - public static fun option (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public static fun pair (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun sequence ()Larrow/typeclasses/Semigroup; - public static fun string ()Larrow/typeclasses/Semigroup; - public static fun validated (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; -} - -public final class arrow/typeclasses/Semigroup$Companion { - public final fun Boolean ()Larrow/typeclasses/Semigroup; - public final fun Byte ()Larrow/typeclasses/Semigroup; - public final fun Integer ()Larrow/typeclasses/Semigroup; - public final fun Long ()Larrow/typeclasses/Semigroup; - public final fun Short ()Larrow/typeclasses/Semigroup; - public final fun constant (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun either (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun endo ()Larrow/typeclasses/Semigroup; - public final fun ior (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun list ()Larrow/typeclasses/Semigroup; - public final fun map (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun nonEmptyList ()Larrow/typeclasses/Semigroup; - public final fun option (Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun pair (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; - public final fun sequence ()Larrow/typeclasses/Semigroup; - public final fun string ()Larrow/typeclasses/Semigroup; - public final fun validated (Larrow/typeclasses/Semigroup;Larrow/typeclasses/Semigroup;)Larrow/typeclasses/Semigroup; -} - -public final class arrow/typeclasses/Semigroup$Companion$NonEmptyListSemigroup : arrow/typeclasses/Semigroup { - public static final field INSTANCE Larrow/typeclasses/Semigroup$Companion$NonEmptyListSemigroup; - public fun append (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public synthetic fun append (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun combine (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public synthetic fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun maybeCombine (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public synthetic fun maybeCombine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/typeclasses/Semigroup$DefaultImpls { - public static fun append (Larrow/typeclasses/Semigroup;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun maybeCombine (Larrow/typeclasses/Semigroup;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Larrow/typeclasses/Semigroup;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/typeclasses/SemigroupKt { - public static final field SemigroupDeprecation Ljava/lang/String; - public static final fun combine (Larrow/typeclasses/Semigroup;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public abstract interface class arrow/typeclasses/Semiring { - public static final field Companion Larrow/typeclasses/Semiring$Companion; - public static fun Byte ()Larrow/typeclasses/Semiring; - public static fun Integer ()Larrow/typeclasses/Semiring; - public static fun Long ()Larrow/typeclasses/Semiring; - public static fun Short ()Larrow/typeclasses/Semiring; - public abstract fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun combineMultiplicate (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun maybeCombineAddition (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun maybeCombineMultiplicate (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun one ()Ljava/lang/Object; - public abstract fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun times (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun zero ()Ljava/lang/Object; -} - -public final class arrow/typeclasses/Semiring$Companion { - public final fun Byte ()Larrow/typeclasses/Semiring; - public final fun Integer ()Larrow/typeclasses/Semiring; - public final fun Long ()Larrow/typeclasses/Semiring; - public final fun Short ()Larrow/typeclasses/Semiring; -} - -public final class arrow/typeclasses/Semiring$DefaultImpls { - public static fun maybeCombineAddition (Larrow/typeclasses/Semiring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun maybeCombineMultiplicate (Larrow/typeclasses/Semiring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun plus (Larrow/typeclasses/Semiring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun times (Larrow/typeclasses/Semiring;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/typeclasses/SemiringKt { - public static final field DoubleInstanceDeprecation Ljava/lang/String; - public static final field FloatInstanceDeprecation Ljava/lang/String; - public static final field SemiringDeprecation Ljava/lang/String; -} - diff --git a/arrow-libs/core/arrow-core/build.gradle.kts b/arrow-libs/core/arrow-core/build.gradle.kts index 42e8923ea3a..c1841844ac0 100644 --- a/arrow-libs/core/arrow-core/build.gradle.kts +++ b/arrow-libs/core/arrow-core/build.gradle.kts @@ -1,13 +1,13 @@ @file:Suppress("DSL_SCOPE_VIOLATION") import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.time.Duration plugins { id(libs.plugins.kotlin.multiplatform.get().pluginId) alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.spotless) } @@ -24,7 +24,6 @@ kotlin { commonMain { dependencies { api(projects.arrowAtomic) - api(projects.arrowContinuations) api(projects.arrowAnnotations) api(libs.kotlin.stdlib) } @@ -33,17 +32,12 @@ kotlin { commonTest { dependencies { implementation(projects.arrowFxCoroutines) - implementation(libs.kotest.frameworkEngine) + implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } } - - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) - } - } } jvm { @@ -53,9 +47,35 @@ kotlin { } } } + + js { + nodejs { + testTask { + useMocha { + timeout = "300s" + } + } + } + browser { + testTask { + useKarma { + useChromeHeadless() + timeout.set(Duration.ofMinutes(5)) + } + } + } + } +} + +tasks.withType().configureEach { + kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes" } // enables context receivers for Jvm Tests tasks.named("compileTestKotlinJvm") { kotlinOptions.freeCompilerArgs += "-Xcontext-receivers" } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/core/arrow-core/knit.test.template b/arrow-libs/core/arrow-core/knit.test.template index 7b3f20935a9..081b5998b41 100644 --- a/arrow-libs/core/arrow-core/knit.test.template +++ b/arrow-libs/core/arrow-core/knit.test.template @@ -1,15 +1,14 @@ // 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.test.Test +import kotlinx.coroutines.test.runTest -class ${test.name} : StringSpec({ +class ${test.name} { <#list cases as case> - "${case.name}" { + @Test fun ${case.knit.name}() = runTest { ${case.knit.package}.${case.knit.name}.test() } -}) { - override fun timeout(): Long = 1000 } \ No newline at end of file diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Const.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Const.kt deleted file mode 100644 index 1ea06bf172c..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Const.kt +++ /dev/null @@ -1,180 +0,0 @@ -package arrow.core - -import arrow.typeclasses.Semigroup - -public const val ConstDeprecation: String = - "Const is deprecated in Arrow Core and will be removed in 2.x.x. \n If Const is crucial for you, please let us know on the Arrow Github. Thanks!\n" + " https://github.com/arrow-kt/arrow/issues\n" - -@Deprecated(ConstDeprecation) -public data class Const(private val value: A) { - - @Suppress("UNCHECKED_CAST") - public fun retag(): Const = - this as Const - - public companion object {} - - public fun value(): A = - value - - public fun map(f: (T) -> U): Const = - retag() - - public inline fun zip( - SG: Semigroup, - b: Const, - map: (T, B) -> C - ): Const = - retag().combine(SG, b.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - map: (T, B, C) -> D - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - map: (T, B, C, D) -> E - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - map: (T, B, C, D, E) -> F - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - f: Const, - map: (A, B, C, D, E, F) -> G - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - .combine(SG, f.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - f: Const, - g: Const, - map: (A, B, C, D, E, F, G) -> H - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - .combine(SG, f.retag()) - .combine(SG, g.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - f: Const, - g: Const, - h: Const, - map: (A, B, C, D, E, F, G, H) -> I - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - .combine(SG, f.retag()) - .combine(SG, g.retag()) - .combine(SG, h.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - f: Const, - g: Const, - h: Const, - i: Const, - map: (A, B, C, D, E, F, G, H, I) -> J - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - .combine(SG, f.retag()) - .combine(SG, g.retag()) - .combine(SG, h.retag()) - .combine(SG, i.retag()) - - public inline fun zip( - SG: Semigroup, - b: Const, - c: Const, - d: Const, - e: Const, - f: Const, - g: Const, - h: Const, - i: Const, - j: Const, - map: (A, B, C, D, E, F, G, H, I, J) -> K - ): Const = - retag() - .combine(SG, b.retag()) - .combine(SG, c.retag()) - .combine(SG, d.retag()) - .combine(SG, e.retag()) - .combine(SG, f.retag()) - .combine(SG, g.retag()) - .combine(SG, h.retag()) - .combine(SG, i.retag()) - .combine(SG, j.retag()) - - override fun toString(): String = - "$Const($value)" -} - -public fun Const.combine(SG: Semigroup, that: Const): Const = - Const(SG.run { this@combine.value().combine(that.value()) }) - -public inline fun A.const(): Const = - Const(this) - -public fun Const.contramap(f: (U) -> T): Const = - retag() - -public operator fun , T> Const.compareTo(other: Const): Int = - value().compareTo(other.value()) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt index 81f7107af12..0f435f523b2 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt @@ -1,22 +1,19 @@ +@file:JvmMultifileClass +@file:JvmName("EitherKt") @file:OptIn(ExperimentalContracts::class) package arrow.core -import arrow.core.Either.Companion.resolve import arrow.core.Either.Left import arrow.core.Either.Right import arrow.core.Either.Right.Companion.unit import arrow.core.raise.Raise import arrow.core.raise.either -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation -import arrow.typeclasses.Semigroup -import arrow.typeclasses.combine import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference -import kotlin.js.JsName +import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -35,13 +32,15 @@ public typealias EitherNel = Either, A> * all becomes even more unwieldy when we try to compose exception-throwing procedures. * * ```kotlin - * import arrow.core.andThen - * * //sampleStart * val throwsSomeStuff: (Int) -> Double = {x -> x.toDouble()} * val throwsOtherThings: (Double) -> String = {x -> x.toString()} * val moreThrowing: (String) -> List = {x -> listOf(x)} - * val magic = throwsSomeStuff.andThen(throwsOtherThings).andThen(moreThrowing) + * val magic: (Int) -> List = { x -> + * val y = throwsSomeStuff(x) + * val z = throwsOtherThings(y) + * moreThrowing(z) + * } * //sampleEnd * fun main() { * println ("magic = $magic") @@ -485,28 +484,9 @@ public typealias EitherNel = Either, A> */ public sealed class Either { - /** - * Returns `true` if this is a [Right], `false` otherwise. - * Used only for performance instead of fold. - */ - @Deprecated( - RedundantAPI + "Use isRight()", - ReplaceWith("isRight()") - ) - @JsName("_isRight") - internal abstract val isRight: Boolean - /** * Returns `true` if this is a [Left], `false` otherwise. - * Used only for performance instead of fold. */ - @Deprecated( - RedundantAPI + "Use isLeft()", - ReplaceWith("isLeft()") - ) - @JsName("_isLeft") - internal abstract val isLeft: Boolean - public fun isLeft(): Boolean { contract { returns(true) implies (this@Either is Left) @@ -515,6 +495,9 @@ public sealed class Either { return this@Either is Left } + /** + * Returns `true` if this is a [Right], `false` otherwise. + */ public fun isRight(): Boolean { contract { returns(true) implies (this@Either is Right) @@ -610,34 +593,6 @@ public sealed class Either { } } - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("this.fold({ initial }) { rightOperation(initial, it) }") - ) - public inline fun foldLeft(initial: C, rightOperation: (C, B) -> C): C = - fold({ initial }) { rightOperation(initial, it) } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ ifLeft }, f)") - ) - public fun foldMap(MN: Monoid, f: (B) -> C): C = - fold({ MN.empty() }, f) - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ f(c, it) }, { g(c, it) })") - ) - public inline fun bifoldLeft(c: C, f: (C, A) -> C, g: (C, B) -> C): C = - fold({ f(c, it) }, { g(c, it) }) - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold(f, g)") - ) - public inline fun bifoldMap(MN: Monoid, f: (A) -> C, g: (B) -> C): C = - fold(f, g) - /** * Swap the generic parameters [A] and [B] of this [Either]. * @@ -701,20 +656,6 @@ public sealed class Either { return fold({ Left(f(it)) }, { Right(it) }) } - @Deprecated( - "tapLeft is being renamed to onLeft to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("onLeft(f)") - ) - public inline fun tapLeft(f: (left: A) -> Unit): Either = - onLeft(f) - - @Deprecated( - "tap is being renamed to onRight to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("onRight(f)") - ) - public inline fun tap(f: (right: B) -> Unit): Either = - onRight(f) - /** * Performs the given [action] on the encapsulated [B] value if this instance represents [Either.Right]. * Returns the original [Either] unchanged. @@ -759,81 +700,6 @@ public sealed class Either { return also { if (it.isLeft()) action(it.value) } } - /** - * Map over Left and Right of this Either - */ - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or map + mapLeft", - ReplaceWith("map(rightOperation).mapLeft(leftOperation)") - ) - public inline fun bimap(leftOperation: (left: A) -> C, rightOperation: (right: B) -> D): Either = - map(rightOperation).mapLeft(leftOperation) - - /** - * Returns `false` if [Left] or returns the result of the application of - * the given predicate to the [Right] value. - * - * Example: - * ```kotlin - * import arrow.core.Either - * import arrow.core.Either.Left - * - * fun main() { - * Either.Right(12).exists { it > 10 } // Result: true - * Either.Right(7).exists { it > 10 } // Result: false - * - * val left: Either = Left(12) - * left.exists { it > 10 } // Result: false - * } - * ``` - * - */ - @Deprecated( - NicheAPI + "Prefer isRight", - ReplaceWith("isRight(predicate)") - ) - public inline fun exists(predicate: (B) -> Boolean): Boolean = - fold({ false }, predicate) - - @Deprecated( - "Facilitates the migration from Validated to Either.", - ReplaceWith("isRight(predicate)") - ) - public inline fun exist(predicate: (B) -> Boolean): Boolean = - exists(predicate) - - /** - * Returns `true` if [Left] or returns the result of the application of - * the given predicate to the [Right] value. - * - * Example: - * ``` - * Right(12).all { it > 10 } // Result: true - * Right(7).all { it > 10 } // Result: false - * - * val left: Either = Left(12) - * left.all { it > 10 } // Result: true - * ``` - */ - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ true }, predicate)") - ) - public inline fun all(predicate: (B) -> Boolean): Boolean = - fold({ true }, predicate) - - @Deprecated( - "orNull is being renamed to getOrNull to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNull()") - ) - public fun orNull(): B? { - contract { - returns(null) implies (this@Either is Left) - returnsNotNull() implies (this@Either is Right) - } - return fold({ null }, { it }) - } - /** * Returns the unwrapped value [B] of [Either.Right] or `null` if it is [Either.Left]. * @@ -846,7 +712,7 @@ public sealed class Either { * Either.Left(12).getOrNull() shouldBe null * } * ``` - * + * * */ public fun getOrNull(): B? { @@ -869,7 +735,7 @@ public sealed class Either { * Either.Left(12).leftOrNull() shouldBe 12 * } * ``` - * + * * */ public fun leftOrNull(): A? { @@ -880,12 +746,6 @@ public sealed class Either { return fold(::identity) { null } } - @Deprecated( - "orNone is being renamed to getOrNone to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNone()") - ) - public fun orNone(): Option = getOrNone() - /** * Transforms [Either] into [Option], * where the encapsulated value [B] is wrapped in [Some] when this instance represents [Either.Right], @@ -902,173 +762,24 @@ public sealed class Either { * Either.Left(12).getOrNone() shouldBe None * } * ``` - * + * * */ public fun getOrNone(): Option = fold({ None }, { Some(it) }) - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or map", - ReplaceWith("if (n <= 0) Right(emptyList()) else map { b -> List(n) { b } }") - ) - public fun replicate(n: Int): Either> = - if (n <= 0) Right(emptyList()) else map { b -> List(n) { b } } - - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ listOf(it.left()) }, { fa(it).map(::Right) })", - "arrow.core.Either.Right", - "arrow.core.Either.left" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Iterable): List> = - fold({ listOf(it.left()) }, { fa(it).map(::Right) }) - - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ Some(it.left()) }, { right -> fa(right).map(::Right) })", - "arrow.core.Either.Right", - "arrow.core.Some", - "arrow.core.left" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Option): Option> = - fold({ Some(it.left()) }, { right -> fa(right).map(::Right) }) - - @Deprecated("traverseOption is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseOption(fa: (B) -> Option): Option> = - traverse(fa) - - @Deprecated( - RedundantAPI + "Use orNull() and Kotlin nullable types", - ReplaceWith("fold({ it.left() }) { fa(it)?.right() }", "arrow.core.left", "arrow.core.right") - ) - public inline fun traverseNullable(fa: (B) -> C?): Either? = - fold({ it.left() }) { fa(it)?.right() } - - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith("fold({ it.left().valid() }, { fa(it).map(::Right) })") - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Validated): Validated> = - fold({ it.left().valid() }, { fa(it).map(::Right) }) - - @Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseValidated(fa: (B) -> Validated): Validated> = - traverse(fa) - - @Deprecated( - NicheAPI + "Prefer explicit fold instead", - ReplaceWith("fold({ fe(it).map { aa -> Left(aa) } }, { fa(it).map { c -> Right(c) } })") - ) - public inline fun bitraverse(fe: (A) -> Iterable, fa: (B) -> Iterable): List> = - fold({ fe(it).map { aa -> Left(aa) } }, { fa(it).map { c -> Right(c) } }) - - @Deprecated( - NicheAPI + "Prefer explicit fold instead", - ReplaceWith("fold({ fl(it).map(::Left) }, { fr(it).map(::Right) })") - ) - public inline fun bitraverseOption(fl: (A) -> Option, fr: (B) -> Option): Option> = - fold({ fl(it).map(::Left) }, { fr(it).map(::Right) }) - - @Deprecated( - NicheAPI + "Prefer explicit fold instead", - ReplaceWith("fold({ fl(it)?.let(::Left) }, { fr(it)?.let(::Right) })") - ) - public inline fun bitraverseNullable(fl: (A) -> AA?, fr: (B) -> C?): Either? = - fold({ fl(it)?.let(::Left) }, { fr(it)?.let(::Right) }) - - @Deprecated( - NicheAPI + "Prefer explicit fold instead", - ReplaceWith("fold({ fe(it).map { Left(it) } }, { fa(it).map { Right(it) } })") - ) - public inline fun bitraverseValidated( - fe: (A) -> Validated, - fa: (B) -> Validated, - ): Validated> = - fold({ fe(it).map { Left(it) } }, { fa(it).map { Right(it) } }) - - @Deprecated( - NicheAPI + "Prefer Kotlin nullable syntax instead", - ReplaceWith("orNull()?.takeIf(predicate)") - ) - public inline fun findOrNull(predicate: (B) -> Boolean): B? = - orNull()?.takeIf(predicate) - - /** - * Returns `true` if [Left] - * - * Example: - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * Either.Left("foo").isEmpty() // Result: true - * Either.Right("foo").isEmpty() // Result: false - * } - * ``` - * - */ - @Deprecated( - RedundantAPI + "Use isLeft()", - ReplaceWith("isLeft()") - ) - public fun isEmpty(): Boolean = isLeft - - /** - * Returns `true` if [Right] - * - * Example: - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * Either.Left("foo").isNotEmpty() // Result: false - * Either.Right("foo").isNotEmpty() // Result: true - * //sampleEnd - * } - * ``` - * - */ - @Deprecated( - RedundantAPI + "Use isRight()", - ReplaceWith("isRight()") - ) - public fun isNotEmpty(): Boolean = isRight - /** * The left side of the disjoint union, as opposed to the [Right] side. */ public data class Left constructor(val value: A) : Either() { - override val isLeft = true - override val isRight = false - override fun toString(): String = "Either.Left($value)" - public companion object { - @Deprecated("Unused, will be removed from bytecode in Arrow 2.x.x", ReplaceWith("Left(Unit)")) - @PublishedApi - internal val leftUnit: Either = Left(Unit) - } + public companion object } /** * The right side of the disjoint union, as opposed to the [Left] side. */ public data class Right constructor(val value: B) : Either() { - override val isLeft = false - override val isRight = true - override fun toString(): String = "Either.Right($value)" public companion object { @@ -1082,48 +793,11 @@ public sealed class Either { { "Either.Right($it)" } ) - @Deprecated(ValidatedDeprMsg + "ValidatedNel is being replaced by EitherNel") - public fun toValidatedNel(): ValidatedNel = - fold({ Validated.invalidNel(it) }, ::Valid) - - @Deprecated(ValidatedDeprMsg + "You can find more details about how to migrate on the Github release page, or the 1.2.0 release post.") - public fun toValidated(): Validated = - fold({ it.invalid() }, { it.valid() }) - public fun toIor(): Ior = fold({ Ior.Left(it) }, { Ior.Right(it) }) public companion object { - - @Deprecated( - RedundantAPI + "Prefer Kotlin nullable syntax, or ensureNotNull inside Either DSL", - ReplaceWith("a?.right() ?: Unit.left()") - ) - @JvmStatic - public fun fromNullable(a: A?): Either = a?.right() ?: Unit.left() - - /** - * Will create an [Either] from the result of evaluating the first parameter using the functions - * provided on second and third parameters. Second parameter represents function for creating - * an [Left] in case of a false result of evaluation and third parameter will be used - * to create a [Right] in case of a true result. - * - * @param test expression to evaluate and build an [Either] - * @param ifFalse function to create a [Left] in case of false result of test - * @param ifTrue function to create a [Right] in case of true result of test - * - * @return [Right] if evaluation succeed, [Left] otherwise - */ - @Deprecated( - RedundantAPI + "Prefer explicit if-else statements, or ensure inside Either DSL", - ReplaceWith("if (test) Right(ifTrue()) else Left(ifFalse())") - ) @JvmStatic - public inline fun conditionally(test: Boolean, ifFalse: () -> L, ifTrue: () -> R): Either = - if (test) Right(ifTrue()) else Left(ifFalse()) - - @JvmStatic - @JvmName("tryCatch") public inline fun catch(f: () -> R): Either = arrow.core.raise.catch({ f().right() }) { it.left() } @@ -1131,95 +805,6 @@ public sealed class Either { public inline fun catchOrThrow(f: () -> R): Either = arrow.core.raise.catch>({ f().right() }) { it.left() } - @Deprecated( - RedundantAPI + "Compose catch with flatten instead", - ReplaceWith("catch(f).flatten()") - ) - @JvmStatic - @JvmName("tryCatchAndFlatten") - public inline fun catchAndFlatten(f: () -> Either): Either = - catch(f).flatten() - - @Deprecated( - RedundantAPI + "Compose catch with mapLeft instead", - ReplaceWith("catch(f).mapLeft(fe)") - ) - @JvmStatic - @JvmName("tryCatch") - public inline fun catch(fe: (Throwable) -> L, f: () -> R): Either { - contract { callsInPlace(fe, InvocationKind.AT_MOST_ONCE) } - return catch(f).mapLeft(fe) - } - - /** - * The resolve function can resolve any function that yields an Either into one type of value. - * - * @param f the function that needs to be resolved. - * @param success the function to apply if [f] yields a success of type [A]. - * @param error the function to apply if [f] yields an error of type [E]. - * @param throwable the function to apply if [f] throws a [Throwable]. - * Throwing any [Throwable] in the [throwable] function will render the [resolve] function nondeterministic. - * @param unrecoverableState the function to apply if [resolve] is in an unrecoverable state. - * @return the result of applying the [resolve] function. - */ - @Deprecated(NicheAPI + "Prefer using recover, catch and the either DSL to work with errors") - @JvmStatic - public inline fun resolve( - f: () -> Either, - success: (a: A) -> Either, - error: (e: E) -> Either, - throwable: (throwable: Throwable) -> Either, - unrecoverableState: (throwable: Throwable) -> Either, - ): B { - contract { - callsInPlace(success, InvocationKind.AT_MOST_ONCE) - callsInPlace(error, InvocationKind.AT_MOST_ONCE) - callsInPlace(throwable, InvocationKind.AT_MOST_ONCE) - callsInPlace(unrecoverableState, InvocationKind.AT_MOST_ONCE) - } - return catch(f) - .fold( - { t: Throwable -> throwable(t) }, - { it.fold({ e: E -> catchAndFlatten { error(e) } }, { a: A -> catchAndFlatten { success(a) } }) }) - .fold({ t: Throwable -> throwable(t) }, { b: B -> b.right() }) - .fold({ t: Throwable -> unrecoverableState(t); throw t }, { b: B -> b }) - } - - /** - * Lifts a function `(B) -> C` to the [Either] structure returning a polymorphic function - * that can be applied over all [Either] values in the shape of Either - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val f = Either.lift { s: CharSequence -> "$s World" } - * val either: Either = "Hello".right() - * val result = f(either) - * //sampleEnd - * println(result) - * } - * ``` - * - */ - @JvmStatic - @Deprecated( - RedundantAPI + "Prefer explicitly creating lambdas", - ReplaceWith("{ it.map(f) }") - ) - public fun lift(f: (B) -> C): (Either) -> Either = - { it.map(f) } - - @JvmStatic - @Deprecated( - RedundantAPI + "Prefer explicitly creating lambdas", - ReplaceWith("{ it.bimap(fa, fb) }") - ) - public fun lift(fa: (A) -> C, fb: (B) -> D): (Either) -> Either = - { it.bimap(fa, fb) } - - public inline fun zipOrAccumulate( combine: (E, E) -> E, a: Either, @@ -1689,23 +1274,10 @@ public sealed class Either { } } } - - @Deprecated( - RedundantAPI + "Map with Unit", - ReplaceWith("map { }") - ) - public fun void(): Either = - map { } - - @Deprecated( - "Facilitates the migration from Validated to Either, you can simply remove this method call.", - ReplaceWith("this") - ) - public inline fun toEither(): Either = - this } /** + * Binds the given function across [Right], that is, * Map, or transform, the right value [B] of this [Either] into a new [Either] with a right value of type [C]. * Returns a new [Either] with either the original left value of type [A] or the newly transformed right value of type [C]. * @@ -1722,13 +1294,6 @@ public inline fun Either.flatMap(f: (right: B) -> Either): public fun Either>.flatten(): Either = flatMap(::identity) -@Deprecated( - RedundantAPI + "This API is overloaded with an API with a single argument", - level = DeprecationLevel.HIDDEN -) -public inline fun Either<*, B>.getOrElse(default: () -> B): B = - fold({ default() }, ::identity) - /** * Get the right value [B] of this [Either], * or compute a [default] value with the left value [A]. @@ -1742,7 +1307,7 @@ public inline fun Either<*, B>.getOrElse(default: () -> B): B = * Either.Left(12) getOrElse { it + 5 } shouldBe 17 * } * ``` - * + * * */ public inline infix fun Either.getOrElse(default: (A) -> B): B { @@ -1750,120 +1315,6 @@ public inline infix fun Either.getOrElse(default: (A) -> B): B { return fold(default, ::identity) } -/** - * Returns the value from this [Right] or null if this is a [Left]. - * - * Example: - * ```kotlin - * import arrow.core.Either.Right - * import arrow.core.Either.Left - * - * fun main() { - * Right(12).orNull() // Result: 12 - * Left(12).orNull() // Result: null - * } - * ``` - * - */ -@Deprecated( - "Duplicated API. Please use Either's member function orNull. This will be removed towards Arrow 2.0", - ReplaceWith("orNull()") -) -public fun Either<*, B>.orNull(): B? = - orNull() - -/** - * Returns the value from this [Right] or allows clients to transform the value from [Left] with the [default] lambda. - * - * Example: - * ```kotlin - * import arrow.core.Either.Right - * import arrow.core.Either.Left - * import arrow.core.getOrHandle - * - * fun main() { - * Right(12).getOrHandle { 17 } // Result: 12 - * Left(12).getOrHandle { it + 5 } // Result: 17 - * } - * ``` - * - */ -@Deprecated( - RedundantAPI + "Use other getOrElse signature", - ReplaceWith("getOrElse(default)") -) -public inline fun Either.getOrHandle(default: (A) -> B): B = - fold({ default(it) }, ::identity) - -/** - * Returns [Right] with the existing value of [Right] if this is a [Right] and the given predicate - * holds for the right value.
- * - * Returns `Left(default)` if this is a [Right] and the given predicate does not - * hold for the right value.
- * - * Returns [Left] with the existing value of [Left] if this is a [Left].
- * - * Example: - * ```kotlin - * import arrow.core.Either.* - * import arrow.core.Either - * import arrow.core.filterOrElse - * - * fun main() { - * Right(12).filterOrElse({ it > 10 }, { -1 }) // Result: Right(12) - * Right(7).filterOrElse({ it > 10 }, { -1 }) // Result: Left(-1) - * - * val left: Either = Left(12) - * left.filterOrElse({ it > 10 }, { -1 }) // Result: Left(12) - * } - * ``` - * - */ -@Deprecated( - RedundantAPI + "Prefer if-else statement inside either DSL, or replace with explicit flatMap", - ReplaceWith("this.flatMap { if (predicate(it)) Either.Right(it) else Either.Left(default(it)) }") -) -public inline fun Either.filterOrElse(predicate: (B) -> Boolean, default: () -> A): Either = - flatMap { if (predicate(it)) Right(it) else Left(default()) } - -/** - * Returns [Right] with the existing value of [Right] if this is a [Right] and the given - * predicate holds for the right value.
- * - * Returns `Left(default({right}))` if this is a [Right] and the given predicate does not - * hold for the right value. Useful for error handling where 'default' returns a message with context on why the value - * did not pass the filter
- * - * Returns [Left] with the existing value of [Left] if this is a [Left].
- * - * Example: - * - * ```kotlin - * import arrow.core.* - * - * suspend fun main(): Unit { - * //sampleStart - * Either.Right(7).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - * .let(::println) // Either.Left(Value '7' is not equal to 10") - * - * Either.Right(10).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - * .let(::println) // Either.Right(10) - * - * Either.Left(12).filterOrOther({ str: String -> str.contains("impossible") }, { -1 }) - * .let(::println) // Either.Left(12) - * //sampleEnd - * } - * ``` - * - */ -@Deprecated( - RedundantAPI + "Prefer if-else statement inside either DSL, or replace with explicit flatMap", - ReplaceWith("this.flatMap { if (predicate(it)) Either.Right(it) else Either.Left(default()) }") -) -public inline fun Either.filterOrOther(predicate: (B) -> Boolean, default: (B) -> A): Either = - flatMap { if (predicate(it)) Right(it) else Left(default(it)) } - /** * Returns the value from this [Right] or [Left]. * @@ -1878,149 +1329,17 @@ public inline fun Either.filterOrOther(predicate: (B) -> Boolean, d * Left(12).merge() // Result: 12 * } * ``` - * + * * */ +@Suppress("NOTHING_TO_INLINE") public inline fun
Either.merge(): A = fold(::identity, ::identity) -/** - * Returns [Right] with the existing value of [Right] if this is an [Right] with a non-null value. - * The returned Either.Right type is not nullable. - * - * Returns `Left(default())` if this is an [Right] and the existing value is null - * - * Returns [Left] with the existing value of [Left] if this is an [Left]. - * - * Example: - * ```kotlin - * import arrow.core.Either.* - * import arrow.core.leftIfNull - * - * fun main() { - * Right(12).leftIfNull({ -1 }) // Result: Right(12) - * Right(null).leftIfNull({ -1 }) // Result: Left(-1) - * - * Left(12).leftIfNull({ -1 }) // Result: Left(12) - * } - * ``` - * - */ -@Deprecated( - RedundantAPI + "Prefer Kotlin nullable syntax inside either DSL, or replace with explicit flatMap", - ReplaceWith("flatMap { b -> b?.right() ?: default().left() }") -) -public inline fun Either.leftIfNull(default: () -> A): Either = - flatMap { b -> b?.right() ?: default().left() } - -/** - * Returns `true` if this is a [Right] and its value is equal to `elem` (as determined by `==`), - * returns `false` otherwise. - * - * Example: - * ```kotlin - * import arrow.core.Either.Right - * import arrow.core.Either.Left - * import arrow.core.contains - * - * fun main() { - * Right("something").contains("something") // Result: true - * Right("something").contains("anything") // Result: false - * Left("something").contains("something") // Result: false - * } - * ``` - * - * - * @param elem the element to test. - * @return `true` if the option has an element that is equal (as determined by `==`) to `elem`, `false` otherwise. - */ -@Deprecated( - RedundantAPI + "Prefer the Either DSL, or replace with explicit fold", - ReplaceWith("fold({ false }) { it == elem }") -) -public fun Either.contains(elem: B): Boolean = - fold({ false }) { it == elem } - -@Deprecated( - RedundantAPI + "Prefer the Either DSL, or new recover API", - ReplaceWith("recover { y.bind() }") -) -public fun Either.combineK(y: Either): Either = - recover { y.bind() } - public fun A.left(): Either = Left(this) public fun A.right(): Either = Right(this) -/** - * Returns [Right] if the value of type B is not null, otherwise the specified A value wrapped into an - * [Left]. - * - * Example: - * ```kotlin - * import arrow.core.rightIfNotNull - * - * fun main() { - * "value".rightIfNotNull { "left" } // Right(b="value") - * null.rightIfNotNull { "left" } // Left(a="left") - * } - * ``` - * - */ -@Deprecated( - RedundantAPI + "Prefer Kotlin nullable syntax", - ReplaceWith("this?.right() ?: default().left()") -) -public inline fun B?.rightIfNotNull(default: () -> A): Either = - this?.right() ?: default().left() - -/** - * Returns [Right] if the value of type Any? is null, otherwise the specified A value wrapped into an - * [Left]. - */ -@Deprecated( - RedundantAPI + "Prefer Kotlin nullable syntax", - ReplaceWith("this?.let { default().left() } ?: null.right()") -) -public inline fun Any?.rightIfNull(default: () -> A): Either = - this?.let { default().left() } ?: null.right() - -@Deprecated( - RedundantAPI + "Prefer the new recover API", - ReplaceWith( - "recover { a -> f(a).bind() }", - "arrow.core.recover" - ) -) -public inline fun Either.handleErrorWith(f: (A) -> Either): Either { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return recover { a -> f(a).bind() } -} - -@Deprecated( - RedundantAPI + "Prefer resolving the error with getOrElse.", - ReplaceWith("getOrElse(f).right()", "arrow.core.right", "arrow.core.getOrElse") -) -public inline fun Either.handleError(f: (A) -> B): Either { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return getOrElse(f).right() -} - -@Deprecated( - RedundantAPI + "Prefer using the Either DSL or explicit fold with right", - ReplaceWith( - "fold({ a -> fe(a) }, fa).right()", - "arrow.core.right" - ) -) -public inline fun Either.redeem(fe: (A) -> C, fa: (B) -> C): Either { - contract { - callsInPlace(fe, InvocationKind.AT_MOST_ONCE) - callsInPlace(fa, InvocationKind.AT_MOST_ONCE) - } - return fold({ a -> fe(a) }, fa).right() -} - public operator fun , B : Comparable> Either.compareTo(other: Either): Int = fold( { a1 -> other.fold({ a2 -> a1.compareTo(a2) }, { -1 }) }, @@ -2045,345 +1364,6 @@ public fun Either.combine(other: Either, combineLeft: (A, A) } } -@Deprecated( - RedundantAPI + "Prefer zipOrAccumulate", - ReplaceWith("Either.zipOrAccumulate({ a:A, bb:A -> a + bb }, this, b) { a:B, bb:B -> a + bb }") -) -public fun Either.combine(SGA: Semigroup, SGB: Semigroup, b: Either): Either = - combine(b, SGA::combine, SGB::combine) - - -@Deprecated( - MonoidDeprecation, - ReplaceWith( - "this.fold, Either>(initialValue.right()) { x, y -> Either.zipOrAccumulate({a1, a2 -> a1 + a2}, x, y, {b1, b2 -> b1 + b2}) }" - ) -) -public fun Iterable>.combineAll(MA: Monoid, MB: Monoid): Either = - fold, Either>(MB.empty().right()) { x, y -> Either.zipOrAccumulate(MA::combine, x, y, MB::combine) } - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [B] is a sub type of [C], re-type this value from Either to Either - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val string: Either = "Hello".right() - * val chars: Either = - * string.widen() - * //sampleEnd - * println(chars) - * } - * ``` - * - */ -public fun Either.widen(): Either = - this - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -public fun Either.leftWiden(): Either = - this - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { f(this.bind(), fb.bind()) }", - "arrow.core.raise.either" - ) -) -public fun Either.zip(fb: Either, f: (B, C) -> D): Either { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return either { f(bind(), fb.bind()) } -} - -@Deprecated( - "Prefer using the inline arrow.core.raise.either DSL", - ReplaceWith( - "either { Pair(this.bind(), fb.bind()) }", - "arrow.core.raise.either" - ) -) -public fun Either.zip(fb: Either): Either> = either { - Pair(bind(), fb.bind()) -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - map: (B, C, D) -> E, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - map: (B, C, D, E) -> F, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - map: (B, C, D, E, F) -> G, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - g: Either, - map: (B, C, D, E, F, G) -> H, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - g: Either, - h: Either, - map: (B, C, D, E, F, G, H) -> I, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - g: Either, - h: Either, - i: Either, - map: (B, C, D, E, F, G, H, I) -> J, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - g: Either, - h: Either, - i: Either, - j: Either, - map: (B, C, D, E, F, G, H, I, J) -> K, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) } -} - -@Deprecated( - "Prefer using the inline either DSL", - ReplaceWith( - "either { map(this.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind(), k.bind()) }", - "arrow.core.raise.either" - ) -) -public inline fun Either.zip( - c: Either, - d: Either, - e: Either, - f: Either, - g: Either, - h: Either, - i: Either, - j: Either, - k: Either, - map: (B, C, D, E, F, G, H, I, J, K) -> L, -): Either { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return either { map(bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind(), k.bind()) } -} - -@Deprecated( - NicheAPI + "Prefer using the Either DSL, or map", - ReplaceWith("if (n <= 0) Either.Right(initial) else this.map { b -> List(n) { b }.fold(initial){r, t -> r + t} }") -) -public fun Either.replicate(n: Int, MB: Monoid): Either = - map { b -> List(n) { b }.fold(MB.empty(), MB::combine) } - -@Deprecated( - RedundantAPI + "Prefer if-else statement inside either DSL, or replace with explicit flatMap", - ReplaceWith("flatMap { b -> b.takeIf(predicate)?.right() ?: error().left() }") -) // TODO open-question: should we expose `ensureNotNull` or `ensure` DSL API on Either or Companion? -public inline fun Either.ensure(error: () -> A, predicate: (B) -> Boolean): Either = - flatMap { b -> b.takeIf(predicate)?.right() ?: error().left() } - -@Deprecated( - NicheAPI + "Prefer using a simple fold, or when expression", - ReplaceWith("fold(fa, fb)") -) -public inline fun Either.redeemWith(fa: (A) -> Either, fb: (B) -> Either): Either { - contract { - callsInPlace(fa, InvocationKind.AT_MOST_ONCE) - callsInPlace(fb, InvocationKind.AT_MOST_ONCE) - } - return fold(fa, fb) -} - -@Deprecated( - "Prefer Kotlin nullable syntax inside either DSL, or replace with explicit fold", - ReplaceWith( - "fold({ listOf>(it.left()) }, { iterable -> iterable.map> { it.right() } })", - "arrow.core.right", "arrow.core.left" - ) -) -public fun Either>.sequence(): List> = - fold({ listOf(it.left()) }, { iterable -> iterable.map { it.right() } }) - -@Deprecated( - "Prefer Kotlin nullable syntax inside either DSL, or replace with explicit fold", - ReplaceWith( - "this.fold>>({ Some(it.left()) }, { iterable -> iterable.map> { it.right() } })", - "arrow.core.Either", - "arrow.core.Option", - "arrow.core.Some", - "arrow.core.left", - "arrow.core.right" - ) -) -public fun Either>.sequenceOption(): Option> = - sequence() - -@Deprecated( - "Prefer Kotlin nullable syntax inside either DSL, or replace with explicit fold", - ReplaceWith( - "this.fold>>({ Some(it.left()) }, { iterable -> iterable.map> { it.right() } })", - "arrow.core.Either", - "arrow.core.Option", - "arrow.core.Some", - "arrow.core.left", - "arrow.core.right" - ) -) -public fun Either>.sequence(): Option> = - fold({ Some(it.left()) }) { it.map { it.right() } } - -@Deprecated( - "Prefer Kotlin nullable syntax inside either DSL, or replace with explicit fold", - ReplaceWith( - "this.fold?>({ it.left() }, { it?.right() })", - "arrow.core.Either", - "arrow.core.right", - "arrow.core.left" - ) -) -public fun Either.sequenceNullable(): Either? = - sequence() - -@Deprecated( - "Prefer Kotlin nullable syntax", - ReplaceWith( - "this.fold?>({ it.left() }, { it?.right() })", - "arrow.core.Either", - "arrow.core.right", - "arrow.core.left" - ) -) -public fun Either.sequence(): Either? = - this.fold?>({ it.left() }, { it?.right() }) - -@Deprecated( - "sequenceValidated is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Either>.sequenceValidated(): Validated> = - sequence() - -@Deprecated( - ValidatedDeprMsg + NicheAPI, - ReplaceWith("fold({ Valid(Left(it)) }) { it.fold({ Invalid(it) }) { Valid(Right(it)) } }") -) -public fun Either>.sequence(): Validated> = - traverse(::identity) - -public fun Either, Iterable>.bisequence(): List> = - bitraverse(::identity, ::identity) - -public fun Either, Option>.bisequenceOption(): Option> = - bitraverseOption(::identity, ::identity) - -public fun Either.bisequenceNullable(): Either? = - bitraverseNullable(::identity, ::identity) - -@Deprecated( - ValidatedDeprMsg + NicheAPI, - ReplaceWith("fold({ it.fold({ Invalid(it) }) { Valid(Left(it)) } }) { it.fold({ Invalid(it) }) { Valid(Right(it)) } }") -) -public fun Either, Validated>.bisequenceValidated(): Validated> = - bitraverseValidated(::identity, ::identity) - public const val NicheAPI: String = "This API is niche and will be removed in the future. If this method is crucial for you, please let us know on the Arrow Github. Thanks!\n https://github.com/arrow-kt/arrow/issues\n" @@ -2417,7 +1397,7 @@ public fun E.leftNel(): EitherNel = * fallback shouldBe Either.Right(5) * } * ``` - * + * * * * When shifting a new error [EE] into the [Either.Left] channel, @@ -2434,7 +1414,7 @@ public fun E.leftNel(): EitherNel = * listOfErrors shouldBe Either.Left(listOf('e', 'r', 'r', 'o', 'r')) * } * ``` - * + * * */ @OptIn(ExperimentalTypeInference::class) @@ -2471,7 +1451,7 @@ public inline fun Either.recover(@BuilderInference recover: Rai * failure shouldBe Either.Left("failure") * } * ``` - * + * * */ @OptIn(ExperimentalTypeInference::class) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Endo.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Endo.kt deleted file mode 100644 index 89df2d31f24..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Endo.kt +++ /dev/null @@ -1,13 +0,0 @@ -package arrow.core - -/** - * The monoid of endomorphisms under composition. - */ -@Deprecated("Semigroup, and Monoid are being deprecated. Use regular function composition instead.") -public data class Endo(val f: (A) -> A) { - - public fun combine(g: Endo): Endo = - Endo(f.compose(g.f)) - - public companion object -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Eval.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Eval.kt deleted file mode 100644 index 0d626164797..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Eval.kt +++ /dev/null @@ -1,570 +0,0 @@ -package arrow.core - -import arrow.typeclasses.Monoid -import kotlin.js.JsName -import kotlin.jvm.JvmStatic - -/** - * Eval is a monad which controls evaluation of a value or a computation that produces a value. - * - * Three basic evaluation strategies: - * - * - Now: evaluated immediately - * - Later: evaluated once when value is needed - * - Always: evaluated every time value is needed - * - * The Later and Always are both lazy strategies while Now is eager. - * Later and Always are distinguished from each other only by - * memoization: once evaluated Later will save the value to be returned - * immediately if it is needed again. Always will run its computation - * every time. - * - * methods, which use an internal trampoline to avoid stack overflows. - * Computation done within .map and .flatMap is always done lazily, - * even when applied to a Now instance. - * - * It is not generally good style to pattern-match on Eval instances. - * Rather, use .map and .flatMap to chain computation, and use .value - * to get the result when needed. It is also not good style to create - * Eval instances whose computation involves calling .value on another - * Eval instance -- this can defeat the trampolining and lead to stack - * overflows. - * - * Example of stack safety: - * - * ```kotlin - * import arrow.core.Eval - * - * //sampleStart - * fun even(n: Int): Eval = - * Eval.always { n == 0 }.flatMap { - * if(it == true) Eval.now(true) - * else odd(n - 1) - * } - * - * fun odd(n: Int): Eval = - * Eval.always { n == 0 }.flatMap { - * if(it == true) Eval.now(false) - * else even(n - 1) - * } - * - * // if not wrapped in eval this type of computation would blow the stack and result in a StackOverflowError - * fun main() { - * println(odd(100000).value()) - * } - * //sampleEnd - * ``` - * - * - */ -@Deprecated( - "This is now part of the arrow-eval module, and will be removed from arrow-core in version 2.0. Please update your project dependencies.", - ReplaceWith("Eval", "arrow.eval.Eval") -) -public sealed class Eval { - - public companion object { - - /** - * Creates an Eval instance from an already constructed value but still defers evaluation when chaining expressions with `map` and `flatMap` - * - * @param a is an already computed value of type [A] - * - * ```kotlin - * import arrow.core.* - * - * fun main() { - * //sampleStart - * val eager = Eval.now(1).map { it + 1 } - * println(eager.value()) - * //sampleEnd - * } - * ``` - * - * - * It will return 2. - */ - @JvmStatic - public fun now(a: A): Eval = - Now(a) - - /** - * Creates an Eval instance from a function deferring it's evaluation until `.value()` is invoked memoizing the computed value. - * - * @param f is a function or computation that will be called only once when `.value()` is invoked for the first time. - * - * ```kotlin - * import arrow.core.* - * - * fun main() { - * //sampleStart - * val lazyEvaled = Eval.later { "expensive computation" } - * println(lazyEvaled.value()) - * //sampleEnd - * } - * ``` - * - * - * "expensive computation" is only computed once since the results are memoized and multiple calls to `value()` will just return the cached value. - */ - @JvmStatic - public inline fun later(crossinline f: () -> A): Later = - Later { f() } - - /** - * Creates an Eval instance from a function deferring it's evaluation until `.value()` is invoked recomputing each time `.value()` is invoked. - * - * @param f is a function or computation that will be called every time `.value()` is invoked. - * - * ```kotlin - * import arrow.core.* - * - * fun main() { - * //sampleStart - * val alwaysEvaled = Eval.always { "expensive computation" } - * println(alwaysEvaled.value()) - * //sampleEnd - * } - * ``` - * - * - * "expensive computation" is computed every time `value()` is invoked. - */ - @JvmStatic - public inline fun always(crossinline f: () -> A): Always = - Always { f() } - - @JvmStatic - public inline fun defer(crossinline f: () -> Eval): Eval = - Defer { f() } - - @JvmStatic - public fun raise(t: Throwable): Eval = - defer { throw t } - - /** - * Collapse the call stack for eager evaluations. - */ - private tailrec fun collapse(fa: Eval): Eval = - when (fa) { - is Defer -> collapse(fa.thunk()) - is FlatMap -> - object : FlatMap() { - override fun start(): Eval = fa.start() - override fun run(s: S): Eval = collapse1(fa.run(s)) - } - else -> fa - } - - // Enforce tailrec call to collapse inside compute loop - private fun collapse1(fa: Eval): Eval = collapse(fa) - - @Suppress("UNCHECKED_CAST") - private fun evaluate(e: Eval): A = run { - var curr: Eval = e - val fs: MutableList<(Any?) -> Eval> = mutableListOf() - - fun addToMemo(m: Memoize): (Any?) -> Eval = { - m.result = Some(it) - now(it) - } - - loop@ while (true) { - when (curr) { - is FlatMap -> { - val currComp = curr as FlatMap - currComp.start().let { cc -> - when (cc) { - is FlatMap -> { - curr = cc.start() - fs.add(0, currComp::run) - fs.add(0, cc::run) - } - is Memoize -> { - cc.result.fold( - { - curr = cc.eval - fs.add(0, currComp::run) - fs.add(0, addToMemo(cc as Memoize)) - }, - { - curr = Now(it) - fs.add(0, currComp::run) - } - ) - } - else -> { - curr = currComp.run(cc.value()) - } - } - } - } - is Memoize -> { - val currComp = curr as Memoize - val eval = currComp.eval - currComp.result.fold( - { - curr = eval - fs.add(0, addToMemo(currComp)) - }, - { - if (fs.isNotEmpty()) { - curr = fs[0](it) - fs.removeAt(0) - } - } - ) - } - else -> - if (fs.isNotEmpty()) { - curr = fs[0](curr.value()) - fs.removeAt(0) - } else { - break@loop - } - } - } - - return curr.value() as A - } - } - - public abstract fun value(): A - - public abstract fun memoize(): Eval - - public inline fun map(crossinline f: (A) -> B): Eval = - flatMap { a -> Now(f(a)) } - - @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE", "UNCHECKED_CAST") - public fun flatMap(f: (A) -> Eval): Eval = - when (this) { - is FlatMap -> object : FlatMap() { - override fun start(): Eval = (this@Eval).start() - - // @IgnoreJRERequirement - override fun run(s: S): Eval = - object : FlatMap() { - override fun start(): Eval = (this@Eval).run(s) as Eval - override fun run(s1: S1): Eval = f(s1 as A) - } - } - is Defer -> object : FlatMap() { - override fun start(): Eval = this@Eval.thunk() as Eval - override fun run(s: S): Eval = f(s as A) - } - else -> object : FlatMap() { - override fun start(): Eval = this@Eval as Eval - override fun run(s: S): Eval = f(s as A) - } - } - - public inline fun coflatMap(crossinline f: (Eval) -> B): Eval = - Later { f(this) } - - /** - * Construct an eager Eval instance. In some sense it is equivalent to using a val. - * - * This type should be used when an A value is already in hand, or when the computation to produce an A value is - * pure and very fast. - */ - public data class Now(@JsName("_value") val value: A) : Eval() { - override fun value(): A = value - override fun memoize(): Eval = this - - override fun toString(): String = - "Eval.Now($value)" - - public companion object { - @PublishedApi - internal val unit: Eval = Now(Unit) - } - } - - /** - * Construct a lazy Eval instance. - * - * This type should be used for most "lazy" values. In some sense it is equivalent to using a lazy val. - * - * When caching is not required or desired (e.g. if the value produced may be large) prefer Always. When there - * is no computation necessary, prefer Now. - * - * Once Later has been evaluated, the closure (and any values captured by the closure) will not be retained, and - * will be available for garbage collection. - */ - public data class Later(private val f: () -> A) : Eval() { - @JsName("_name") - val value: A by lazy(f) - - override fun value(): A = value - override fun memoize(): Eval = this - - override fun toString(): String = - "Eval.Later(f)" - } - - /** - * Construct a lazy Eval instance. - * - * This type can be used for "lazy" values. In some sense it is equivalent to using a Function0 value. - * - * This type will evaluate the computation every time the value is required. It should be avoided except when - * laziness is required and caching must be avoided. Generally, prefer Later. - */ - public data class Always(private val f: () -> A) : Eval() { - override fun value(): A = f() - override fun memoize(): Eval = Later(f) - - override fun toString(): String = - "Eval.Always(f)" - } - - /** - * Defer is a type of Eval that is used to defer computations which produce Eval. - * - * Users should not instantiate Defer instances themselves. Instead, they will be automatically created when needed. - */ - public data class Defer(val thunk: () -> Eval) : Eval() { - override fun memoize(): Eval = Memoize(this) - override fun value(): A = collapse(this).value() - - override fun toString(): String = - "Eval.Defer(thunk)" - } - - /** - * FlatMap is a type of Eval that is used to chain computations involving .map and .flatMap. Along with - * Eval#flatMap. It implements the trampoline that guarantees stack-safety. - * - * Users should not instantiate FlatMap instances themselves. Instead, they will be automatically created when - * needed. - * - * Unlike a traditional trampoline, the internal workings of the trampoline are not exposed. This allows a slightly - * more efficient implementation of the .value method. - */ - public abstract class FlatMap : Eval() { - public abstract fun start(): Eval - public abstract fun run(s: S): Eval - override fun memoize(): Eval = Memoize(this) - override fun value(): A = evaluate(this) - - override fun toString(): String = - "Eval.FlatMap(..)" - } - - /** - * Memoize is a type of Eval that is used to memoize an eval value. Unlike Later, Memoize exposes its cache, - * allowing Eval's internal trampoline to compute it when needed. - * - * Users should not instantiate Memoize instances themselves. Instead, they will be automatically created when - * needed. - */ - internal data class Memoize(val eval: Eval) : Eval() { - var result: Option = None - override fun memoize() = this - override fun value(): A = result.getOrElse { - evaluate(eval).also { result = Some(it) } - } - - override fun toString(): String = - "Eval.Memoize($eval)" - } - - override fun toString(): String = - "Eval(...)" -} - -public fun Iterator.iterateRight(lb: Eval, f: (A, Eval) -> Eval): Eval { - fun loop(): Eval = - Eval.defer { if (this.hasNext()) f(this.next(), loop()) else lb } - return loop() -} - -public fun Eval.zip(b: Eval, map: (A, B) -> Z): Eval = - flatMap { a: A -> b.map { bb: B -> map(a, bb) } } - -public fun Eval.zip(b: Eval): Eval> = - flatMap { a: A -> b.map { bb: B -> Pair(a, bb) } } - -public fun Eval.zip( - b: Eval, - c: Eval, - map: (A, B, C) -> D -): Eval = - zip( - b, - c, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit - ) { aa, bb, cc, _, _, _, _, _, _, _ -> map(aa, bb, cc) } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - map: (A, B, C, D) -> E -): Eval = - zip( - b, - c, - d, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit, - Eval.Now.unit - ) { aa, bb, cc, dd, _, _, _, _, _, _ -> map(aa, bb, cc, dd) } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - map: (A, B, C, D, E) -> F -): Eval = - zip(b, c, d, e, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit) { aa, bb, cc, dd, ee, _, _, _, _, _ -> - map( - aa, - bb, - cc, - dd, - ee - ) - } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - f: Eval, - map: (A, B, C, D, E, F) -> G -): Eval = - zip(b, c, d, e, f, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit) { aa, bb, cc, dd, ee, ff, _, _, _, _ -> - map( - aa, - bb, - cc, - dd, - ee, - ff - ) - } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - f: Eval, - g: Eval, - map: (A, B, C, D, E, F, G) -> H -): Eval = - zip(b, c, d, e, f, g, Eval.Now.unit, Eval.Now.unit, Eval.Now.unit) { aa, bb, cc, dd, ee, ff, gg, _, _, _ -> - map( - aa, - bb, - cc, - dd, - ee, - ff, - gg - ) - } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - f: Eval, - g: Eval, - h: Eval, - map: (A, B, C, D, E, F, G, H) -> I -): Eval = - zip(b, c, d, e, f, g, h, Eval.Now.unit, Eval.Now.unit) { aa, bb, cc, dd, ee, ff, gg, hh, _, _ -> - map( - aa, - bb, - cc, - dd, - ee, - ff, - gg, - hh - ) - } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - f: Eval, - g: Eval, - h: Eval, - i: Eval, - map: (A, B, C, D, E, F, G, H, I) -> J -): Eval = - zip(b, c, d, e, f, g, h, i, Eval.Now.unit) { aa, bb, cc, dd, ee, ff, gg, hh, ii, _ -> - map( - aa, - bb, - cc, - dd, - ee, - ff, - gg, - hh, - ii - ) - } - -public fun Eval.zip( - b: Eval, - c: Eval, - d: Eval, - e: Eval, - f: Eval, - g: Eval, - h: Eval, - i: Eval, - j: Eval, - map: (A, B, C, D, E, F, G, H, I, J) -> K -): Eval = - flatMap { aa -> - b.flatMap { bb -> - c.flatMap { cc -> - d.flatMap { dd -> - e.flatMap { ee -> - f.flatMap { ff -> - g.flatMap { gg -> - h.flatMap { hh -> - i.flatMap { ii -> - j.map { jj -> - map(aa, bb, cc, dd, ee, ff, gg, hh, ii, jj) - } - } - } - } - } - } - } - } - } - } - -public fun Eval.replicate(n: Int): Eval> = - if (n <= 0) Eval.now(emptyList()) - else this.zip(replicate(n - 1)) { a: A, xs: List -> listOf(a) + xs } - -public fun Eval.replicate(n: Int, MA: Monoid): Eval = MA.run { - if (n <= 0) Eval.now(MA.empty()) - else this@replicate.zip(replicate(n - 1, MA)) { a: A, xs: A -> MA.run { a + xs } } -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Ior.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Ior.kt index efdc2a2e00c..df337ef365e 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Ior.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Ior.kt @@ -5,20 +5,9 @@ package arrow.core import arrow.core.Ior.Both import arrow.core.Ior.Left import arrow.core.Ior.Right -import arrow.core.raise.either -import arrow.core.raise.ior -import arrow.core.raise.nullable -import arrow.core.raise.option -import arrow.typeclasses.Monoid -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference -import kotlin.js.JsName -import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic public typealias IorNel = Ior, B> @@ -45,7 +34,7 @@ public typealias IorNel = Ior, B> public sealed class Ior { /** - * Returns `true` if this is a [Right], `false` otherwise. + * Returns `true` if this is a [Left], `false` otherwise. * * Example: * @@ -53,21 +42,23 @@ public sealed class Ior { * import arrow.core.Ior * * fun main() { - * Ior.Left("tulip").isRight // Result: false - * Ior.Right("venus fly-trap").isRight // Result: true - * Ior.Both("venus", "fly-trap").isRight // Result: false + * Ior.Left("tulip").isLeft() // Result: true + * Ior.Right("venus fly-trap").isLeft() // Result: false + * Ior.Both("venus", "fly-trap").isLeft() // Result: false * } * ``` * */ - @Deprecated( - RedundantAPI + "Use isRight()", - ReplaceWith("isRight()") - ) - public abstract val isRight: Boolean + public fun isLeft(): Boolean { + contract { + returns(true) implies (this@Ior is Ior.Left) + returns(false) implies (this@Ior is Ior.Right || this@Ior is Ior.Both) + } + return this@Ior is Ior.Left + } /** - * Returns `true` if this is a [Left], `false` otherwise. + * Returns `true` if this is a [Right], `false` otherwise. * * Example: * @@ -75,18 +66,20 @@ public sealed class Ior { * import arrow.core.Ior * * fun main() { - * Ior.Left("tulip").isLeft // Result: true - * Ior.Right("venus fly-trap").isLeft // Result: false - * Ior.Both("venus", "fly-trap").isLeft // Result: false + * Ior.Left("tulip").isRight() // Result: false + * Ior.Right("venus fly-trap").isRight() // Result: true + * Ior.Both("venus", "fly-trap").isRight() // Result: false * } * ``` * */ - @Deprecated( - RedundantAPI + "Use isLeft()", - ReplaceWith("isLeft()") - ) - public abstract val isLeft: Boolean + public fun isRight(): Boolean { + contract { + returns(true) implies (this@Ior is Ior.Right) + returns(false) implies (this@Ior is Ior.Left || this@Ior is Ior.Both) + } + return this@Ior is Ior.Right + } /** * Returns `true` if this is a [Both], `false` otherwise. @@ -96,43 +89,13 @@ public sealed class Ior { * import arrow.core.Ior * * fun main() { - * Ior.Left("tulip").isBoth // Result: false - * Ior.Right("venus fly-trap").isBoth // Result: false - * Ior.Both("venus", "fly-trap").isBoth // Result: true + * Ior.Left("tulip").isBoth() // Result: false + * Ior.Right("venus fly-trap").isBoth() // Result: false + * Ior.Both("venus", "fly-trap").isBoth() // Result: true * } * ``` * */ - - @Deprecated( - RedundantAPI + "Use isBoth()", - ReplaceWith("isBoth()") - ) - public abstract val isBoth: Boolean - - - @JsName("_isLeft") - @JvmName("_isLeft") - public fun isLeft(): Boolean { - contract { - returns(true) implies (this@Ior is Ior.Left) - returns(false) implies (this@Ior is Ior.Right || this@Ior is Ior.Both) - } - return this@Ior is Ior.Left - } - - @JsName("_isRight") - @JvmName("_isRight") - public fun isRight(): Boolean { - contract { - returns(true) implies (this@Ior is Ior.Right) - returns(false) implies (this@Ior is Ior.Left || this@Ior is Ior.Both) - } - return this@Ior is Ior.Right - } - - @JsName("_isBoth") - @JvmName("_isBoth") public fun isBoth(): Boolean { contract { returns(false) implies (this@Ior is Ior.Right || this@Ior is Ior.Left) @@ -141,7 +104,6 @@ public sealed class Ior { return this@Ior is Ior.Both } - public companion object { /** * Create an [Ior] from two nullables if at least one of them is defined. @@ -149,7 +111,7 @@ public sealed class Ior { * @param a an element (nullable) for the left side of the [Ior] * @param b an element (nullable) for the right side of the [Ior] * - * @return [null] if both [a] and [b] are [null]. Otherwise + * @return `null` if both [a] and [b] are `null`. Otherwise * an [Ior.Left], [Ior.Right], or [Ior.Both] if [a], [b], or both are defined (respectively). */ @JvmStatic @@ -171,39 +133,6 @@ public sealed class Ior { @JvmStatic public fun bothNel(a: A, b: B): IorNel = Both(nonEmptyListOf(a), b) - - /** - * Lifts a function `(B) -> C` to the [Ior] structure returning a polymorphic function - * that can be applied over all [Ior] values in the shape of Ior - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val f = Ior.lift { s: CharSequence -> "$s World" } - * val ior: Ior = Ior.Right("Hello") - * val result = f(ior) - * //sampleEnd - * println(result) - * } - * ``` - */ - @JvmStatic - @Deprecated( - RedundantAPI + "Prefer explicitly creating lambdas", - ReplaceWith("{ it.map(f) }") - ) - public fun lift(f: (B) -> C): (Ior) -> Ior = - { it.map(f) } - - @JvmStatic - @Deprecated( - RedundantAPI + "Prefer explicitly creating lambdas", - ReplaceWith("{ it.map(fb).mapLeft(fa) }") - ) - public fun lift(fa: (A) -> C, fb: (B) -> D): (Ior) -> Ior = - { it.map(fb).mapLeft(fa) } } /** @@ -228,49 +157,6 @@ public sealed class Ior { } } - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ c }, { f(c, it) }, { _, b -> f(c, b) })") - ) - public inline fun foldLeft(c: C, f: (C, B) -> C): C { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return fold({ c }, { f(c, it) }, { _, b -> f(c, b) }) - } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("this.fold({ leftValue }, { f }, { _, b -> f(b) })") - ) - public inline fun foldMap(MN: Monoid, f: (B) -> C): C { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return MN.run { - fold({ MN.empty() }, { f(it) }, { _, b -> f(b) }) - } - } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("this.fold({ f(c, it) }, { g(c, it) }, { a, b -> g(f(c, a), b) })") - ) - public inline fun bifoldLeft(c: C, f: (C, A) -> C, g: (C, B) -> C): C { - contract { - callsInPlace(f, InvocationKind.AT_MOST_ONCE) - callsInPlace(g, InvocationKind.AT_MOST_ONCE) - } - return fold({ f(c, it) }, { g(c, it) }, { a, b -> g(f(c, a), b) }) - } - - @Deprecated(NicheAPI + "Prefer when or fold instead. See the Arrow web migration guide for more info.") - public inline fun bifoldMap(MN: Monoid, f: (A) -> C, g: (B) -> C): C { - contract { - callsInPlace(f, InvocationKind.AT_MOST_ONCE) - callsInPlace(g, InvocationKind.AT_MOST_ONCE) - } - return MN.run { - fold({ f(it) }, { g(it) }, { a, b -> f(a).combine(g(b)) }) - } - } - /** * The given function is applied if this is a [Right] or [Both] to `B`. * @@ -289,40 +175,12 @@ public sealed class Ior { public inline fun map(f: (B) -> D): Ior { contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } return when (this) { - is Left -> Left(value) + is Left -> this is Right -> Right(f(value)) is Both -> Both(leftValue, f(rightValue)) } } - /** - * Apply `fa` if this is a [Left] or [Both] to `A` - * and apply `fb` if this is [Right] or [Both] to `B` - * - * Example: - * ```kotlin - * import arrow.core.Ior - * - * fun main() { - * Ior.Right(12).bimap ({ "flower" }, { 12 }) // Result: Right(12) - * Ior.Left(12).bimap({ "flower" }, { 12 }) // Result: Left("flower") - * Ior.Both(12, "power").bimap ({ it * 2 }, { b -> "flower $b" }) // Result: Both("flower power", 24) - * } - * ``` - * - */ - @Deprecated( - NicheAPI + "Prefer using the Either DSL, or map + mapLeft", - ReplaceWith("map(fb).mapLeft(fa)") - ) - public inline fun bimap(fa: (A) -> C, fb: (B) -> D): Ior { - contract { - callsInPlace(fa, InvocationKind.AT_MOST_ONCE) - callsInPlace(fb, InvocationKind.AT_MOST_ONCE) - } - return map(fb).mapLeft(fa) - } - /** * The given function is applied if this is a [Left] or [Both] to `A`. * @@ -336,15 +194,15 @@ public sealed class Ior { * Ior.Both(12, "power").mapLeft { "flower $it" } // Result: Both("flower 12", "power") * } * ``` - * + * */ public inline fun mapLeft(fa: (A) -> C): Ior { contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { Left(fa(it)) }, - ::Right, - { a, b -> Both(fa(a), b) } - ) + return when (this) { + is Left -> Left(fa(value)) + is Right -> this + is Both -> Both(fa(leftValue), rightValue) + } } /** @@ -361,7 +219,7 @@ public sealed class Ior { * Ior.Both("left", "right").swap() // Result: Both("right", "left") * } * ``` - * + * */ public fun swap(): Ior = fold( { Right(it) }, @@ -378,43 +236,12 @@ public sealed class Ior { { a, b -> Either.Right(Pair(a, b)) } ) - /** - * Return this [Ior] as [Pair] of nullables] - * - * Example: - * ```kotlin - * import arrow.core.Ior - * - * fun main() { - * val right = Ior.Right(12).padNull() // Result: Pair(null, 12) - * val left = Ior.Left(12).padNull() // Result: Pair(12, null) - * val both = Ior.Both("power", 12).padNull() // Result: Pair("power", 12) - * - * println("right = $right") - * println("left = $left") - * println("both = $both") - * } - * ``` - * - */ - @Deprecated( - "padNull is being renamed to toPair to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("toPair()") - ) - public fun padNull(): Pair = fold( - { Pair(it, null) }, - { Pair(null, it) }, - { a, b -> Pair(a, b) } - ) - - public fun toPair(): Pair = fold( { Pair(it, null) }, { Pair(null, it) }, { a, b -> Pair(a, b) } ) - /** * Returns a [Either.Right] containing the [Right] value or `B` if this is [Right] or [Both] * and [Either.Left] if this is a [Left]. @@ -429,43 +256,11 @@ public sealed class Ior { * Ior.Both("power", 12).toEither() // Result: Either.Right(12) * } * ``` - * + * */ public fun toEither(): Either = fold({ Either.Left(it) }, { Either.Right(it) }, { _, b -> Either.Right(b) }) - /** - * Returns the [Right] value or `B` if this is [Right] or [Both] - * and [null] if this is a [Left]. - * - * Example: - * ```kotlin - * import arrow.core.Ior - * - * fun main() { - * val right = Ior.Right(12).orNull() // Result: 12 - * val left = Ior.Left(12).orNull() // Result: null - * val both = Ior.Both(12, "power").orNull() // Result: "power" - * - * println("right = $right") - * println("left = $left") - * println("both = $both") - * } - * ``` - * - */ - @Deprecated( - "orNull is being renamed to getOrNull to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNull()") - ) - public fun orNull(): B? { - contract { - returns(null) implies (this@Ior is Left) - returnsNotNull() implies ((this@Ior is Right) || (this@Ior is Both)) - } - return fold({ null }, { it }, { _, b -> b }) - } - public fun getOrNull(): B? { contract { returns(null) implies (this@Ior is Left) @@ -476,7 +271,7 @@ public sealed class Ior { /** * Returns the [Left] value or `A` if this is [Left] or [Both] - * and [null] if this is a [Right]. + * and `null` if this is a [Right]. * * Example: * ```kotlin @@ -491,7 +286,7 @@ public sealed class Ior { * println("both = $both") * } * ``` - * + * */ public fun leftOrNull(): A? { contract { @@ -501,55 +296,19 @@ public sealed class Ior { return fold({ it }, { null }, { a, _ -> a }) } - /** - * Returns a [Validated.Valid] containing the [Right] value or `B` if this is [Right] or [Both] - * and [Validated.Invalid] if this is a [Left]. - * - * Example: - * ```kotlin - * import arrow.core.Ior - * - * fun main() { - * Ior.Right(12).toValidated() // Result: Valid(12) - * Ior.Left(12).toValidated() // Result: Invalid(12) - * Ior.Both(12, "power").toValidated() // Result: Valid("power") - * } - * ``` - * - */ - @Deprecated(NicheAPI + "Prefer using fold. See the Arrow web migration guide for more info.") - public fun toValidated(): Validated = - fold({ Invalid(it) }, { Valid(it) }, { _, b -> Valid(b) }) - public data class Left(val value: A) : Ior() { - override val isRight: Boolean get() = false - override val isLeft: Boolean get() = true - override val isBoth: Boolean get() = false - override fun toString(): String = "Ior.Left($value)" public companion object } public data class Right(val value: B) : Ior() { - override val isRight: Boolean get() = true - override val isLeft: Boolean get() = false - override val isBoth: Boolean get() = false - override fun toString(): String = "Ior.Right($value)" - public companion object { - @PublishedApi - internal val unit: Ior = - Right(Unit) - } + public companion object } public data class Both(val leftValue: A, val rightValue: B) : Ior() { - override val isRight: Boolean get() = false - override val isLeft: Boolean get() = false - override val isBoth: Boolean get() = true - override fun toString(): String = "Ior.Both($leftValue, $rightValue)" } @@ -559,160 +318,6 @@ public sealed class Ior { { a, b -> "Ior.Both($a, $b)" } ) - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bicrosswalk( - fa: (A) -> Iterable, - fb: (B) -> Iterable - ): List> = - fold( - { a -> fa(a).map { it.leftIor() } }, - { b -> fb(b).map { it.rightIor() } }, - { a, b -> fa(a).align(fb(b)) } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bicrosswalkMap( - fa: (A) -> Map, - fb: (B) -> Map - ): Map> = - fold( - { a -> fa(a).mapValues { it.value.leftIor() } }, - { b -> fb(b).mapValues { it.value.rightIor() } }, - { a, b -> fa(a).align(fb(b)) } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bicrosswalkNull( - fa: (A) -> C?, - fb: (B) -> D? - ): Ior? = - fold( - { a -> fa(a)?.let { Left(it) } }, - { b -> fb(b)?.let { Right(it) } }, - { a, b -> fromNullables(fa(a), fb(b)) } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bitraverse(fa: (A) -> Iterable, fb: (B) -> Iterable): List> = - fold( - { a -> fa(a).map { Left(it) } }, - { b -> fb(b).map { Right(it) } }, - { a, b -> fa(a).zip(fb(b)) { aa, c -> Both(aa, c) } } - ) - - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bitraverseEither( - fa: (A) -> Either, - fb: (B) -> Either - ): Either> = - fold( - { a -> fa(a).map { Left(it) } }, - { b -> fb(b).map { Right(it) } }, - { a, b -> either { Both(fa(a).bind(), fb(b).bind()) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bitraverseOption( - fa: (A) -> Option, - fb: (B) -> Option - ): Option> = - fold( - { a -> fa(a).map { Left(it) } }, - { b -> fb(b).map { Right(it) } }, - { a, b -> option { Both(fa(a).bind(), fb(b).bind()) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bitraverseNullable( - fa: (A) -> C?, - fb: (B) -> D? - ): Ior? = - fold( - { a -> fa(a)?.let { Left(it) } }, - { b -> fb(b)?.let { Right(it) } }, - { a, b -> nullable { Both(fa(a).bind(), fb(b).bind()) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun bitraverseValidated( - SA: Semigroup, - fa: (A) -> Validated, - fb: (B) -> Validated - ): Validated> = - fold( - { a -> fa(a).map { Left(it) } }, - { b -> fb(b).map { Right(it) } }, - { a, b -> fa(a).zip(SA, fb(b)) { aa, c -> Both(aa, c) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun crosswalk(fa: (B) -> Iterable): List> = - fold( - { emptyList() }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun crosswalkMap(fa: (B) -> Map): Map> = - fold( - { emptyMap() }, - { b -> fa(b).mapValues { Right(it.value) } }, - { a, b -> fa(b).mapValues { Both(a, it.value) } } - ) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun crosswalkNull(ior: Ior, fa: (B) -> C?): Ior? = - ior.fold( - { a -> Left(a) }, - { b -> fa(b)?.let { Right(it) } }, - { a, b -> fa(b)?.let { Both(a, it) } } - ) - - @Deprecated(NicheAPI + "Prefer using fold, or map + getOrElse. See the Arrow web migration guide for more info.") - public inline fun all(predicate: (B) -> Boolean): Boolean { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return fold({ true }, predicate, { _, b -> predicate(b) }) - } - - /** - * Returns `false` if [Left] or returns the result of the application of - * the given predicate to the [Right] value. - * - * Example: - * ```kotlin - * import arrow.core.Ior - * - * fun main() { - * Ior.Both(5, 12).exists { it > 10 } // Result: true - * Ior.Right(12).exists { it > 10 } // Result: true - * Ior.Right(7).exists { it > 10 } // Result: false - * val left: Ior = Ior.Left(12) - * left.exists { it > 10 } // Result: false - * } - * ``` - * - */ - @Deprecated( - NicheAPI + "Prefer using fold, or map + getOrElse", - ReplaceWith("fold({ false }, predicate, { _, b -> predicate(b) })") - ) - public inline fun exists(predicate: (B) -> Boolean): Boolean { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return fold({ false }, predicate, { _, b -> predicate(b) }) - } - - @Deprecated( - NicheAPI + "Prefer Kotlin nullable syntax instead", - ReplaceWith("getOrNull()?.takeIf(predicate)") - ) - public inline fun findOrNull(predicate: (B) -> Boolean): B? { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return getOrNull()?.takeIf(predicate) - } - - /** * Returns `false` if [Right] or [Both], or returns the result of the application of * the given predicate to the [Left] value. @@ -728,7 +333,7 @@ public sealed class Ior { * Ior.Left(12).isLeft { it > 10 } // Result: true * } * ``` - * + * */ public inline fun isLeft(predicate: (A) -> Boolean): Boolean { contract { @@ -753,7 +358,7 @@ public sealed class Ior { * left.isRight { it > 10 } // Result: true * } * ``` - * + * */ public inline fun isRight(predicate: (B) -> Boolean): Boolean { contract { @@ -779,7 +384,7 @@ public sealed class Ior { * left.isBoth ( {it > 10}, {it > 6 }) // Result: false * } * ``` - * + * */ public inline fun isBoth(leftPredicate: (A) -> Boolean, rightPredicate: (B) -> Boolean): Boolean { contract { @@ -788,131 +393,8 @@ public sealed class Ior { } return this@Ior is Both && leftPredicate(leftValue) && rightPredicate(rightValue) } - - - @Deprecated( - NicheAPI + "Prefer using isLeft", - ReplaceWith("isLeft()") - ) - public fun isEmpty(): Boolean { - contract { - returns(true) implies (this@Ior is Left) - returns(false) implies (this@Ior is Right || this@Ior is Both) - } - return isLeft - } - - @Deprecated( - NicheAPI + "Prefer using isRight and isBoth", - ReplaceWith("(this.isRight() || this.isBoth())") - ) - public fun isNotEmpty(): Boolean { - contract { - returns(false) implies (this@Ior is Left) - returns(true) implies (this@Ior is Right || this@Ior is Both) - } - return !isLeft - } - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Iterable): List> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { a -> listOf(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } } - ) - } - - @Deprecated("traverseEither is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseEither(fa: (B) -> Either): Either> = - fold( - { a -> Either.Right(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } }) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Either): Either> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { a -> Either.Right(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } } - ) - } - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (B) -> Option): Option> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { a -> Some(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } } - ) - } - - @Deprecated("traverseOption is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseOption(fa: (B) -> Option): Option> = - fold( - { a -> Some(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } }) - - @Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") - public inline fun traverseNullable(fa: (B) -> C?): Ior? { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { a -> Left(a) }, - { b -> fa(b)?.let { Right(it) } }, - { a, b -> fa(b)?.let { Both(a, it) } } - ) - } - - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - @Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> Valid(Ior.Left(a)) }, {b -> fa(b).map { Ior.Right(it) } }, { a, b -> fa(b).map { Ior.Both(a, it) } })", - "arrow.core.Ior" - ) - ) - public inline fun traverse(fa: (B) -> Validated): Validated> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold( - { a -> Valid(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } } - ) - } - - @Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseValidated(fa: (B) -> Validated): Validated> = - fold( - { a -> Valid(Left(a)) }, - { b -> fa(b).map { Right(it) } }, - { a, b -> fa(b).map { Both(a, it) } }) - - @Deprecated( - NicheAPI + "Prefer using map", - ReplaceWith("map { }") - ) - public fun void(): Ior = map { } } -@Deprecated( - "$SemigroupDeprecation.", - ReplaceWith("this.flatMap({a, b -> a + b}, f)") -) -public inline fun Ior.flatMap(SG: Semigroup, f: (B) -> Ior): Ior = - flatMap(SG::combine, f) - /** * Binds the given function across [Ior.Right]. * @@ -929,15 +411,6 @@ public inline fun Ior.flatMap(combine: (A, A) -> A, f: (B) -> Io ) } -@Deprecated( - RedundantAPI + "This API is overloaded with an API with a single argument", - level = DeprecationLevel.HIDDEN -) -public inline fun Ior.getOrElse(default: () -> B): B { - contract { callsInPlace(default, InvocationKind.AT_MOST_ONCE) } - return fold({ default() }, ::identity, { _, b -> b }) -} - public inline fun Ior.getOrElse(default: (A) -> B): B { contract { callsInPlace(default, InvocationKind.AT_MOST_ONCE) } return fold(default, ::identity) { _, b -> b } @@ -950,69 +423,6 @@ public fun A.leftIor(): Ior = Ior.Left(this) public fun A.rightIor(): Ior = Ior.Right(this) -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "this.fold>>({ a: List -> a.map> { Ior.Left(it) } }, {b: List -> b.map>{ Ior.Right(it) } }, { a, b -> a.zip>(b) { aa, c -> Ior.Both(aa, c) } })", - "arrow.core.Ior" - ) -) -public fun Ior, Iterable>.bisequence(): List> = - fold({ a -> a.map { Left(it) } }, - { b -> b.map { Right(it) } }, - { a, b -> a.zip(b) { aa, c -> Both(aa, c) } }) - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "this.fold>>({ a -> a.map> { Ior.Left(it) } }, {b -> b.map>{ Ior.Right(it) } }, { a: Either, b: Either -> either> { Ior.Both(a.bind(), b.bind()) } })", - "arrow.core.Ior", - "arrow.core.raise.either" - ) -) -public fun Ior, Either>.bisequenceEither(): Either> = - fold({ a -> a.map { Left(it) } }, - { b -> b.map { Right(it) } }, - { a, b -> either { Both(a.bind(), b.bind()) } }) - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "this.fold>>({ a -> a.map> { Ior.Left(it) } }, {b -> b.map>{ Ior.Right(it) } }, { a, b -> option> { Ior.Both(a.bind(), b.bind()) } })", - "arrow.core.Ior", - "arrow.core.raise.option" - ) -) -public fun Ior, Option>.bisequenceOption(): Option> = - fold({ a -> a.map { Left(it) } }, - { b -> b.map { Right(it) } }, - { a, b -> option { Both(a.bind(), b.bind()) } }) - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> a?.let>{ Ior.Left(it) } }, {b -> b?.let>{ Ior.Right(it) } }, { a, b -> nullable> { Ior.Both(a.bind(), b.bind()) } })", - "arrow.core.Ior", - "arrow.core.raise.nullable" - ) -) -public fun Ior.bisequenceNullable(): Ior? = - fold( - { a -> a?.let { Left(it) } }, - { b -> b?.let { Right(it) } }, - { a, b -> nullable { Both(a.bind(), b.bind()) } }) - -@Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") -public fun Ior, Validated>.bisequenceValidated(SA: Semigroup): Validated> = - bitraverseValidated(SA, ::identity, ::identity) - -@Deprecated( - "$SemigroupDeprecation", - ReplaceWith("combine(other, {a1, a2 -> a1 + a2}, {b1, b2 -> b1 + b2} )") -) -public fun Ior.combine(SA: Semigroup, SB: Semigroup, other: Ior): Ior = - combine(other, SA::combine, SB::combine) - public fun Ior.combine(other: Ior, combineA: (A, A) -> A, combineB: (B, B) -> B): Ior = when (this) { is Ior.Left -> when (other) { @@ -1037,131 +447,6 @@ public fun Ior.combine(other: Ior, combineA: (A, A) -> A, com public inline fun Ior>.flatten(combine: (A, A) -> A): Ior = flatMap(combine, ::identity) -@Suppress("NOTHING_TO_INLINE") -@Deprecated( - "$SemigroupDeprecation.", - ReplaceWith("this.flatten{a1, a2 -> a1 + a2}") -) -public inline fun Ior>.flatten(SA: Semigroup): Ior = - flatMap(SA, ::identity) - -@Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") -public fun Ior.replicate(SA: Semigroup, n: Int): Ior> = - if (n <= 0) Ior.Right(emptyList()) - else when (this) { - is Ior.Right -> Ior.Right(List(n) { value }) - is Ior.Left -> this - is Ior.Both -> map { List(n) { rightValue } }.mapLeft { List(n - 1) { leftValue }.fold(leftValue) { acc, a -> SA.run { acc + a } } } - } - -@Deprecated(NicheAPI + "Prefer using Ior DSL, or explicit fold, or when. See the Arrow web migration guide for more info.") -public fun Ior.replicate(SA: Semigroup, n: Int, MB: Monoid): Ior = - if (n <= 0) Ior.Right(MB.empty()) - else when (this) { - is Ior.Right -> Ior.Right(MB.run { List(n) { value }.fold() }) - is Ior.Left -> this - is Ior.Both -> map { MB.run { List(n) { rightValue }.fold() } }.mapLeft { - List(n - 1) { leftValue }.fold( - leftValue - ) { acc, a -> SA.run { acc + a } } - } - } - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> listOf>(Ior.Left(a)) }, {b -> b.map>{ Ior.Right(it) } }, { a, b -> b.map>{ Ior.Both(a, it) } })", - "arrow.core.Ior" - ) -) -public fun Ior>.sequence(): List> = - fold( - { a -> listOf(Left(a)) }, - { b -> b.map { Right(it) } }, - { a, b -> b.map { Both(a, it) } }) - -@Deprecated( - "sequenceEither is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Ior>.sequenceEither(): Either> = - sequence() - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> Either.Right>(Ior.Left(a)) }, {b -> b.map> { Ior.Right(it) } }, { a, b -> b.map>{ Ior.Both(a, it) } })", - "arrow.core.Ior" - ) -) -public fun Ior>.sequence(): Either> = - fold( - { a -> Either.Right(Left(a)) }, - { b -> b.map { Right(it) } }, - { a, b -> b.map { Both(a, it) } }) - -@Deprecated( - "sequenceOption is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Ior>.sequenceOption(): Option> = - sequence() - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> Some>(Ior.Left(a)) }, {b -> b.map> { Ior.Right(it) } }, { a, b -> b.map>{ Ior.Both(a, it) } })", - "arrow.core.Ior", - "arrow.core.Some" - ) -) -public fun Ior>.sequence(): Option> = - fold( - { a -> Some(Left(a)) }, - { b -> b.map { Right(it) } }, - { a, b -> b.map { Both(a, it) } }) - -@Deprecated( - "sequenceOption is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Ior.sequenceNullable(): Ior? = - sequence() - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> Ior.Left(a) }, {b -> b?.let> { Ior.Right(it) } }, { a, b -> b?.let>{ Ior.Both(a, it) } })", - "arrow.core.Ior" - ) -) -public fun Ior.sequence(): Ior? = - fold( - { a -> Left(a) }, - { b -> b?.let { Right(it) } }, - { a, b -> b?.let { Both(a, it) } }) - -@Deprecated( - "sequenceValidated is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Ior>.sequenceValidated(): Validated> = - sequence() - -@Deprecated( - NicheAPI + "Prefer using Ior DSL, or explicit fold, or when", - ReplaceWith( - "fold({ a -> Valid>(Ior.Left(a)) }, {b -> b.map> { Ior.Right(it) } }, { a, b -> b.map> { Ior.Both(a, it) } })", - "arrow.core.Ior", - "arrow.core.Valid" - ) -) -public fun Ior>.sequence(): Validated> = - fold( - { a -> Valid(Left(a)) }, - { b -> b.map { Right(it) } }, - { a, b -> b.map { Both(a, it) } }) - /** * Given an [Ior] with an error type [A], returns an [IorNel] with the same * error type. Wraps the original error in a [NonEmptyList] so that it can be @@ -1170,298 +455,6 @@ public fun Ior>.sequence(): Validated> public fun Ior.toIorNel(): IorNel = mapLeft { it.nel() } -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [B] is a sub type of [C], re-type this value from Ior to Ior - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val string: Ior = Ior.Right("Hello") - * val chars: Ior = - * string.widen() - * //sampleEnd - * println(chars) - * } - * ``` - * - */ -public fun Ior.widen(): Ior = - this - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -public fun Ior.leftWiden(): Ior = - this - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { Pair(this.bind(), fb.bind()) }", - "arrow.core.raise.ior", - "arrow.typeclasses.combine" - ) -) -public fun Ior.zip(SA: Semigroup, fb: Ior): Ior> = - ior(SA::combine) { Pair(this@zip.bind(), fb.bind()) } - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith("ior({a, b -> a + b}) { map(this.bind(), c.bind()) }", "arrow.core.raise.ior") -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - map: (B, C) -> D -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith("ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()) }", "arrow.core.raise.ior") -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - map: (B, C, D) -> E -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith("ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind() }", "arrow.core.raise.ior") -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - map: (B, C, D, E) -> F -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - map: (B, C, D, E, F) -> G -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind(), f.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind(), g.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - g: Ior, - map: (B, C, D, E, F, G) -> H -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind(), g.bind(), h.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - g: Ior, - h: Ior, - map: (B, C, D, E, F, G, H) -> I -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind(), g.bind(), h.bind(), i.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - g: Ior, - h: Ior, - i: Ior, - map: (B, C, D, E, F, G, H, I) -> J -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - g: Ior, - h: Ior, - i: Ior, - j: Ior, - map: (B, C, D, E, F, G, H, I, J) -> K -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return ior(SA::combine) { - map(this@zip.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) - } -} - -@Deprecated( - NicheAPI + "Prefer using the inline ior DSL", - ReplaceWith( - "ior({a, b -> a + b}) { map(this.bind(), c.bind(), d.bind()), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind(), k.bind() }", - "arrow.core.raise.ior" - ) -) -public inline fun Ior.zip( - SA: Semigroup, - c: Ior, - d: Ior, - e: Ior, - f: Ior, - g: Ior, - h: Ior, - i: Ior, - j: Ior, - k: Ior, - map: (B, C, D, E, F, G, H, I, J, K) -> L -): Ior { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - // If any of the values is Right or Both then we can calculate L otherwise it results in MY_NULL - val rightValue: Any? = if ( - (this@zip.isRight() || this@zip.isBoth()) && - (c.isRight() || c.isBoth()) && - (d.isRight() || d.isBoth()) && - (e.isRight() || e.isBoth()) && - (f.isRight() || f.isBoth()) && - (g.isRight() || g.isBoth()) && - (h.isRight() || h.isBoth()) && - (i.isRight() || i.isBoth()) && - (j.isRight() || j.isBoth()) && - (k.isRight() || k.isBoth()) - ) { - map( - this@zip.orNull() as B, - c.orNull() as C, - d.orNull() as D, - e.orNull() as E, - f.orNull() as F, - g.orNull() as G, - h.orNull() as H, - i.orNull() as I, - j.orNull() as J, - k.orNull() as K - ) - } else EmptyValue - - val leftValue: Any? = SA.run { - var accumulatedLeft: Any? = EmptyValue - - if (this@zip is Left) return@zip Left(this@zip.value) - accumulatedLeft = - if (this@zip is Both) this@zip.leftValue else accumulatedLeft - - if (c is Left) return@zip Left(emptyCombine(accumulatedLeft, c.value)) - accumulatedLeft = if (c is Both) emptyCombine(accumulatedLeft, c.leftValue) else accumulatedLeft - - if (d is Left) return@zip Left(emptyCombine(accumulatedLeft, d.value)) - accumulatedLeft = if (d is Both) emptyCombine(accumulatedLeft, d.leftValue) else accumulatedLeft - - if (e is Left) return@zip Left(emptyCombine(accumulatedLeft, e.value)) - accumulatedLeft = if (e is Both) emptyCombine(accumulatedLeft, e.leftValue) else accumulatedLeft - - if (f is Left) return@zip Left(emptyCombine(accumulatedLeft, f.value)) - accumulatedLeft = if (f is Both) emptyCombine(accumulatedLeft, f.leftValue) else accumulatedLeft - - if (g is Left) return@zip Left(emptyCombine(accumulatedLeft, g.value)) - accumulatedLeft = if (g is Both) emptyCombine(accumulatedLeft, g.leftValue) else accumulatedLeft - - if (h is Left) return@zip Left(emptyCombine(accumulatedLeft, h.value)) - accumulatedLeft = if (h is Both) emptyCombine(accumulatedLeft, h.leftValue) else accumulatedLeft - - if (i is Left) return@zip Left(emptyCombine(accumulatedLeft, i.value)) - accumulatedLeft = if (i is Both) emptyCombine(accumulatedLeft, i.leftValue) else accumulatedLeft - - if (j is Left) return@zip Left(emptyCombine(accumulatedLeft, j.value)) - accumulatedLeft = if (j is Both) emptyCombine(accumulatedLeft, j.leftValue) else accumulatedLeft - - if (k is Left) return@zip Left(emptyCombine(accumulatedLeft, k.value)) - accumulatedLeft = if (k is Both) emptyCombine(accumulatedLeft, k.leftValue) else accumulatedLeft - - accumulatedLeft - } - - return when { - rightValue != EmptyValue && leftValue == EmptyValue -> Right(rightValue as L) - rightValue != EmptyValue && leftValue != EmptyValue -> Both(leftValue as A, rightValue as L) - rightValue == EmptyValue && leftValue != EmptyValue -> Left(leftValue as A) - else -> throw ArrowCoreInternalException - } -} - public operator fun , B : Comparable> Ior.compareTo(other: Ior): Int = fold( { a1 -> other.fold({ a2 -> a1.compareTo(a2) }, { -1 }, { _, _ -> -1 }) }, { b1 -> other.fold({ 1 }, { b2 -> b1.compareTo(b2) }, { _, _ -> -1 }) }, diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt index c77ed96e427..7afb7eab552 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Iterable.kt @@ -11,14 +11,6 @@ import arrow.core.raise.Raise import arrow.core.raise.either import arrow.core.raise.RaiseAccumulate import arrow.core.raise.mapOrAccumulate -import arrow.core.raise.nullable -import arrow.core.raise.option -import arrow.core.raise.result -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmName import kotlin.collections.unzip as stdlibUnzip @@ -296,222 +288,6 @@ public inline fun Iterable.zip( public fun Iterable.collectionSizeOrDefault(default: Int): Int = if (this is Collection<*>) this.size else default -@Deprecated( - "Traverse for Either is being deprecated in favor of Either DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Either>> { l -> either> { l.map { f(it).bind() } } }", "arrow.core.raise.either") -) -public inline fun Iterable.traverseEither(f: (A) -> Either): Either> = - let { l -> either { l.map { f(it).bind() } } } - -@Deprecated( - "Traverse for Either is being deprecated in favor of Either DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Either>> { l -> either> { l.map { f(it).bind() } } }", "arrow.core.raise.either") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(f: (A) -> Either): Either> = - let { l -> either { l.map { f(it).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the either DSL.", - ReplaceWith("let { l -> either> { l.bindAll() } }", "arrow.core.raise.either") -) -public fun Iterable>.sequenceEither(): Either> = - let { l -> either { l.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the either DSL.", - ReplaceWith("let { l -> either> { l.bindAll() } }", "arrow.core.raise.either") -) -public fun Iterable>.sequence(): Either> = - let { l -> either { l.bindAll() } } - -@Deprecated( - "Traverse for Result is being deprecated in favor of Result DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Result>> { l -> result> { l.map { f(it).bind() } } }", "arrow.core.raise.result") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(f: (A) -> Result): Result> = - let { l -> result { l.map { f(it).bind() } } } - -@Deprecated( - "Traverse for Result is being deprecated in favor of Result DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Result>> { l -> result> { l.map { f(it).bind() } } }", "arrow.core.raise.result") -) -public inline fun Iterable.traverseResult(f: (A) -> Result): Result> = - let { l -> result { l.map { f(it).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the result DSL.", - ReplaceWith("let { l -> result> { l.bindAll() } }", "arrow.core.raise.result") -) -public fun Iterable>.sequenceResult(): Result> = - let { l -> result { l.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the result DSL.", - ReplaceWith("let { l -> result> { l.bindAll() } }", "arrow.core.raise.result") -) -public fun Iterable>.sequence(): Result> = - let { l -> result { l.bindAll() } } - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public inline fun Iterable.traverseValidated( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate { f(it).bindNel() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public inline fun Iterable.traverseValidated(f: (A) -> ValidatedNel): ValidatedNel> = - mapOrAccumulate { f(it).bindNel() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate { f(it).bindNel() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(f: (A) -> ValidatedNel): ValidatedNel> = - mapOrAccumulate { f(it).bindNel() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun Iterable>.sequenceValidated(semigroup: Semigroup): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun Iterable>.sequence(semigroup: Semigroup): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate, A> { it.bindNel() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun Iterable>.sequenceValidated(): ValidatedNel> = - mapOrAccumulate { it.bindNel() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate, A> { it.bindNel() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun Iterable>.sequence(): ValidatedNel> = - mapOrAccumulate { it.bindNel() }.toValidated() - -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Option>> { l -> option> { l.map { f(it).bind() } } }", "arrow.core.raise.option") -) -public inline fun Iterable.traverseOption(f: (A) -> Option): Option> = - let { l -> option { l.map { f(it).bind() } } } - -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + Iterable.map.\n$NicheAPI", - ReplaceWith("let, Option>> { l -> option> { l.map { f(it).bind() } } }", "arrow.core.raise.option") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(f: (A) -> Option): Option> = - let { l -> option { l.map { f(it).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the option DSL.", - ReplaceWith("let { l -> option> { l.bindAll() } }", "arrow.core.raise.option") -) -public fun Iterable>.sequenceOption(): Option> = - let { l -> option { l.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the option DSL.", - ReplaceWith("let { l -> option> { l.bindAll() } }", "arrow.core.raise.option") -) -public fun Iterable>.sequence(): Option> = - let { l -> option { l.bindAll() } } - -@Deprecated( - "Traverse for nullable is being deprecated in favor of Nullable DSL + Iterable.map.\n$NicheAPI", - ReplaceWith( - "let, List?> { l -> nullable> { l.map { f(it).bind() } } }", - "arrow.core.raise.nullable" - ) -) -public inline fun Iterable.traverseNullable(f: (A) -> B?): List? = - traverse(f) - -@Deprecated( - "Traverse for nullable is being deprecated in favor of Nullable DSL + Iterable.map.\n$NicheAPI", - ReplaceWith( - "let, List?> { l -> nullable> { l.map { f(it).bind() } } }", - "arrow.core.raise.nullable" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(f: (A) -> B?): List? = - let { l -> nullable { l.map { f(it).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the nullable DSL.", - ReplaceWith("let { l -> nullable> { l.bindAll() } }", "arrow.core.raise.nullable") -) -public fun Iterable.sequenceNullable(): List? = - let { l -> nullable { l.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the nullable DSL.", - ReplaceWith("let { l -> nullable> { l.bindAll() } }", "arrow.core.raise.nullable") -) -public fun Iterable.sequence(): List? = - let { l -> nullable { l.bindAll() } } - /** * Returns [Either] a [List] containing the results of applying the given [transform] function to each element in the original collection, * **or** accumulate all the _logical errors_ that were _raised_ while transforming the collection using the [combine] function is used to accumulate all the _logical errors_. @@ -615,13 +391,6 @@ public fun Iterable>.flattenOrAccumulate(): Either Iterable>.flattenOrAccumulate(): Either, List> = mapOrAccumulate { it.bindNel() } -@Deprecated( - "Void is being deprecated in favor of simple Iterable.map.\n$NicheAPI", - ReplaceWith("map { }") -) -public fun Iterable.void(): List = - map { } - public inline fun Iterable.reduceOrNull(initial: (A) -> B, operation: (acc: B, A) -> B): B? { val iterator = this.iterator() if (!iterator.hasNext()) return null @@ -820,15 +589,6 @@ public inline fun Iterable.align(b: Iterable, fa: (Ior) -> public fun Iterable.align(b: Iterable): List> = this.align(b, ::identity) -/** - * aligns two structures and combine them with the given [Semigroup.combine] - */ -@Deprecated(SemigroupDeprecation, ReplaceWith("this.padZip(other, { it }, { it }, {a1, a2 -> a1 + a2})")) -public fun Iterable.salign( - SG: Semigroup, - other: Iterable -): Iterable = padZip(other, { it }, { it }, SG::combine) - /** * unzips the structure holding the resulting elements in an `Pair` * @@ -904,11 +664,14 @@ public fun Iterable>.separateIor(): Pair, List> = ) } -@Deprecated( - "The current unalign function is renamed to separateIor, and a new unalign function is going to be added to Arrow 2.0.0.", - ReplaceWith("separateIor()", "arrow.core.separateIor") -) -public fun Iterable>.unalign(): Pair, List> = separateIor() +public fun Iterable>.unalign(): Pair, List> = + fold(emptyList() to emptyList()) { (l, r), x -> + x.fold( + { Pair(l + it, r + null) }, + { Pair(l + null, r + it) }, + { a, b -> Pair(l + a, r + b) } + ) + } /** * after applying the given function, splits the resulting union shaped structure into its components parts @@ -921,23 +684,15 @@ public fun Iterable>.unalign(): Pair, List> = separa * listOf(1, 2, 3, 4).unalign { * if(it % 2 == 0) it.rightIor() * else it.leftIor() - * } shouldBe Pair(listOf(1, 3), listOf(2, 4)) + * } shouldBe Pair(listOf(1, null, 3, null), listOf(null, 2, null, 4)) * } * ``` * * */ -@Deprecated( - "The current unalign function is renamed to separateIor, and a new unalign function is going to be added to Arrow 2.0.0.", - ReplaceWith("map(fa).separateIor()", "arrow.core.separateIor") -) -public inline fun Iterable.unalign(fa: (C) -> Ior): Pair, List> = +public inline fun Iterable.unalign(fa: (C) -> Ior): Pair, List> = map(fa).unalign() -@Deprecated("Use fold from Kotlin Std instead", ReplaceWith("this.fold(initial){a1, a2 -> a1 + a2}")) -public fun Iterable.combineAll(MA: Monoid): A = - fold(MA.empty(), MA::combine) - /** * Returns the first element as [Some], or [None] if the iterable is empty. */ @@ -1115,47 +870,6 @@ public fun Iterable.unweave(ffa: (A) -> Iterable): List = ffa(a).interleave(fa.unweave(ffa)) } ?: emptyList() -/** - * Logical conditional. The equivalent of Prolog's soft-cut. - * If its first argument succeeds at all, then the results will be - * fed into the success branch. Otherwise, the failure branch is taken. - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val result = - * listOf(1,2,3).ifThen(listOf("empty")) { i -> - * listOf("$i, ${i + 1}") - * } - * //sampleEnd - * println(result) - * } - * ``` - * - */ -@Deprecated( - "Use flatMap and ifEmpty instead.\n$NicheAPI", - ReplaceWith("flatMap(ffa).ifEmpty, Iterable> { fb }") -) -public inline fun Iterable.ifThen(fb: Iterable, ffa: (A) -> Iterable): Iterable = - flatMap(ffa).ifEmpty { fb } - -@Deprecated( - "Use mapNotNull and getOrNull instead.\n$NicheAPI", - ReplaceWith("mapNotNull { it.getOrNull() }") -) -public fun Iterable>.uniteEither(): List = - mapNotNull { it.getOrNull() } - -@Deprecated( - "${ValidatedDeprMsg}Use mapNotNull and orNull instead.", - ReplaceWith("mapNotNull { it.orNull() }", "arrow.core.orNull") -) -public fun Iterable>.uniteValidated(): List = - mapNotNull { it.orNull() } - /** * Separate the inner [Either] values into the [Either.Left] and [Either.Right]. * @@ -1168,7 +882,7 @@ public fun Iterable>.uniteValidated(): List = * .separateEither() shouldBe Pair(listOf("A", "C"), listOf(2, 4)) * } * ``` - * + * * */ public fun Iterable>.separateEither(): Pair, List> = @@ -1190,7 +904,7 @@ public fun Iterable>.separateEither(): Pair, List * } shouldBe Pair(listOf("odd: 1", "odd: 3"), listOf("even: 2", "even: 4")) * } * ``` - * + * * */ public inline fun Iterable.separateEither(f: (T) -> Either): Pair, List> { @@ -1207,72 +921,9 @@ public inline fun Iterable.separateEither(f: (T) -> Either): return Pair(left, right) } -/** - * Separate the inner [Validated] values into the [Validated.Invalid] and [Validated.Valid]. - * - * @receiver Iterable of Validated - * @return a tuple containing List with [Validated.Invalid] and another List with its [Validated.Valid] values. - */ -@Deprecated( - "${ValidatedDeprMsg}Use separateEither instead.", - ReplaceWith("map { it.toEither() }.separateEither()") -) -public fun Iterable>.separateValidated(): Pair, List> { - val invalids = ArrayList(collectionSizeOrDefault(10)) - val valids = ArrayList(collectionSizeOrDefault(10)) - - for (validated in this) - when (validated) { - is Invalid -> invalids.add(validated.value) - is Valid -> valids.add(validated.value) - } - - return Pair(invalids, valids) -} - public fun Iterable>.flatten(): List = flatMap(::identity) -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [A] is a subtype of [B], re-type this value from Iterable to Iterable - * - * ```kotlin - * import arrow.core.* - * - * fun test() { - * val original: List = listOf("Hello", ",", "World") - * val result: Iterable = original.widen() - * } - * ``` - */ -public fun Iterable.widen(): Iterable = - this - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [A] is a subtype of [B], re-type this value from List to List - * - * ```kotlin - * import arrow.core.* - * - * fun main() { - * val original: List = listOf("Hello", ",", "World") - * val result: Iterable = original.widen() - * } - * ``` - */ -public fun List.widen(): List = - this - -@Deprecated(MonoidDeprecation, ReplaceWith("this.fold(initial, {a1, a2 -> a1 + a2})")) -public fun Iterable.fold(MA: Monoid): A = - fold(MA.empty(), MA::combine) - -@Deprecated(MonoidDeprecation, ReplaceWith("this.fold(initial) { acc, a -> combine(acc, f(a)) }")) -public fun Iterable.foldMap(MB: Monoid, f: (A) -> B): B = - fold(MB.empty()) { acc, a -> MB.run { acc.combine(f(a)) } } - public fun Iterable.crosswalk(f: (A) -> Iterable): List> = fold(emptyList()) { bs, a -> f(a).align(bs) { ior -> @@ -1304,23 +955,6 @@ public fun Iterable.crosswalkNull(f: (A) -> B?): List? = ) } -@Deprecated("Not being used anymore. Will be removed from the binary in 2.0.0") -@PublishedApi -internal val listUnit: List = - listOf(Unit) - -@Deprecated( - NicheAPI, - ReplaceWith("toList().let { l -> List(n) { l } }") -) -public fun Iterable.replicate(n: Int): List> = - toList().let { l -> List(n) { l } } - -@Deprecated(NicheAPI) -public fun Iterable.replicate(n: Int, MA: Monoid): List = - if (n <= 0) listOf(MA.empty()) - else this@replicate.zip(replicate(n - 1, MA)) { a, xs -> MA.run { a + xs } } - public operator fun > Iterable.compareTo(other: Iterable): Int = align(other) { ior -> ior.fold({ 1 }, { -1 }, { a1, a2 -> a1.compareTo(a2) }) } .fold(0) { acc, i -> diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt index 8ea4104e146..546ec1c3627 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt @@ -3,14 +3,10 @@ package arrow.core import arrow.core.raise.RaiseAccumulate -import arrow.core.raise.either -import arrow.core.raise.option -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmStatic import kotlin.collections.unzip as stdlibUnzip +import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmInline +import kotlin.jvm.JvmName public typealias Nel = NonEmptyList @@ -153,48 +149,56 @@ public typealias Nel = NonEmptyList * - `a.zip(b, c) { ... }` can be used to compute over multiple `NonEmptyList` values preserving type information and __abstracting over arity__ with `zip` * */ -public class NonEmptyList( - public override val head: A, - public val tail: List -) : AbstractList(), NonEmptyCollection { - - private constructor(list: List) : this(list[0], list.drop(1)) - - override val size: Int = - 1 + tail.size - +@JvmInline +public value class NonEmptyList @PublishedApi internal constructor( public val all: List - get() = toList() +) : List by all, NonEmptyCollection { + + public constructor(head: A, tail: List): this(listOf(head) + tail) - public override operator fun get(index: Int): A { - if (index < 0 || index >= size) throw IndexOutOfBoundsException("$index is not in 1..${size - 1}") - return if (index == 0) head else tail[index - 1] + @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") + override fun equals(other: Any?): Boolean = when (other) { + is NonEmptyList<*> -> this.all == other.all + else -> this.all == other } + @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") + override fun hashCode(): Int = all.hashCode() + override fun isEmpty(): Boolean = false - public fun toList(): List = listOf(head) + tail + public fun toList(): List = all + + public override val head: A + get() = all.first() + + public val tail: List + get() = all.drop(1) override fun lastOrNull(): A = when { tail.isNotEmpty() -> tail.last() else -> head } + @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") + public override inline fun distinct(): NonEmptyList = + NonEmptyList(all.distinct()) + @Suppress("OVERRIDE_BY_INLINE") - public override inline fun map(transform: (A) -> B): NonEmptyList = - NonEmptyList(transform(head), tail.map(transform)) + public override inline fun distinctBy(selector: (A) -> K): NonEmptyList = + NonEmptyList(all.distinctBy(selector)) @Suppress("OVERRIDE_BY_INLINE") - public override inline fun mapIndexed(transform: (index: Int, A) -> B): NonEmptyList = - NonEmptyList(transform(0, head), tail.mapIndexed { ix, e -> transform(ix + 1, e) }) + public override inline fun map(transform: (A) -> B): NonEmptyList = + NonEmptyList(all.map(transform)) @Suppress("OVERRIDE_BY_INLINE") public override inline fun flatMap(transform: (A) -> NonEmptyCollection): NonEmptyList = - transform(head).toNonEmptyList() + tail.flatMap(transform) + NonEmptyList(all.flatMap(transform)) @Suppress("OVERRIDE_BY_INLINE") - public override inline fun distinctBy(selector: (A) -> K): NonEmptyList = - all.distinctBy(selector).toNonEmptyListOrNull()!! + public override inline fun mapIndexed(transform: (index: Int, A) -> B): NonEmptyList = + NonEmptyList(transform(0, head), tail.mapIndexed { ix, e -> transform(ix + 1, e) }) public operator fun plus(l: NonEmptyList<@UnsafeVariance A>): NonEmptyList = this + l.all @@ -206,39 +210,25 @@ public class NonEmptyList( NonEmptyList(all + element) public inline fun foldLeft(b: B, f: (B, A) -> B): B = - this.tail.fold(f(b, this.head), f) - - public fun coflatMap(f: (NonEmptyList) -> B): NonEmptyList { - val buf = mutableListOf() - tailrec fun consume(list: List): List = - if (list.isEmpty()) { - buf - } else { - val tail = list.subList(1, list.size) - buf += f(NonEmptyList(list[0], tail)) - consume(tail) + all.fold(b, f) + + public fun coflatMap(f: (NonEmptyList) -> B): NonEmptyList = + buildList { + var current = all + while (current.isNotEmpty()) { + add(f(NonEmptyList(current))) + current = current.drop(1) } - return NonEmptyList(f(this), consume(this.tail)) - } + }.let(::NonEmptyList) public fun extract(): A = this.head - override fun equals(other: Any?): Boolean = - super.equals(other) - - override fun hashCode(): Int = - super.hashCode() - override fun toString(): String = "NonEmptyList(${all.joinToString()})" public fun align(b: NonEmptyList): NonEmptyList> = - NonEmptyList(Ior.Both(head, b.head), tail.align(b.tail)) - - @Deprecated(SemigroupDeprecation, ReplaceWith("padZip(b, ::identity, ::identity, {a1, a2 -> a1 + a2})")) - public fun salign(SA: Semigroup<@UnsafeVariance A>, b: NonEmptyList<@UnsafeVariance A>): NonEmptyList = - padZip(b, ::identity, ::identity, SA::combine) + NonEmptyList(all.align(b)) public fun padZip(other: NonEmptyList): NonEmptyList> = padZip(other, { it to null }, { null to it }, { a, b -> a to b }) @@ -247,30 +237,6 @@ public class NonEmptyList( NonEmptyList(both(head, other.head), tail.padZip(other.tail, left, right, both)) public companion object { - - @Deprecated( - "Use toNonEmptyListOrNull instead", - ReplaceWith( - "l.toNonEmptyListOrNull().toOption()", - "import arrow.core.toNonEmptyListOrNull", - "import arrow.core.toOption" - ) - ) - @JvmStatic - public fun fromList(l: List): Option> = - if (l.isEmpty()) None else Some(NonEmptyList(l)) - - @Deprecated( - "Use toNonEmptyListOrNull instead", - ReplaceWith( - "l.toNonEmptyListOrNull() ?: throw IndexOutOfBoundsException(\"Empty list doesn't contain element at index 0.\")", - "import arrow.core.toNonEmptyListOrNull" - ) - ) - @JvmStatic - public fun fromListUnsafe(l: List): NonEmptyList = - NonEmptyList(l) - @PublishedApi internal val unit: NonEmptyList = nonEmptyListOf(Unit) @@ -283,20 +249,14 @@ public class NonEmptyList( b: NonEmptyList, map: (A, B) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head), - tail.zip(b.tail, map) - ) + NonEmptyList(all.zip(b.all, map)) public inline fun zip( b: NonEmptyList, c: NonEmptyList, map: (A, B, C) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head), - tail.zip(b.tail, c.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, map)) public inline fun zip( b: NonEmptyList, @@ -304,10 +264,7 @@ public class NonEmptyList( d: NonEmptyList, map: (A, B, C, D) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head), - tail.zip(b.tail, c.tail, d.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, map)) public inline fun zip( b: NonEmptyList, @@ -316,10 +273,7 @@ public class NonEmptyList( e: NonEmptyList, map: (A, B, C, D, E) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, map)) public inline fun zip( b: NonEmptyList, @@ -329,10 +283,7 @@ public class NonEmptyList( f: NonEmptyList, map: (A, B, C, D, E, F) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, map)) public inline fun zip( b: NonEmptyList, @@ -343,10 +294,7 @@ public class NonEmptyList( g: NonEmptyList, map: (A, B, C, D, E, F, G) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, map)) public inline fun zip( b: NonEmptyList, @@ -358,10 +306,7 @@ public class NonEmptyList( h: NonEmptyList, map: (A, B, C, D, E, F, G, H) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, map)) public inline fun zip( b: NonEmptyList, @@ -374,10 +319,7 @@ public class NonEmptyList( i: NonEmptyList, map: (A, B, C, D, E, F, G, H, I) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head, i.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, i.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, map)) public inline fun zip( b: NonEmptyList, @@ -391,17 +333,17 @@ public class NonEmptyList( j: NonEmptyList, map: (A, B, C, D, E, F, G, H, I, J) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head, i.head, j.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, i.tail, j.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, j.all, map)) } +@JvmName("nonEmptyListOf") public fun nonEmptyListOf(head: A, vararg t: A): NonEmptyList = - NonEmptyList(head, t.asList()) + NonEmptyList(listOf(head) + t) +@JvmName("nel") +@Suppress("NOTHING_TO_INLINE") public inline fun A.nel(): NonEmptyList = - nonEmptyListOf(this) + NonEmptyList(listOf(this)) public operator fun > NonEmptyList.compareTo(other: NonEmptyList): Int = all.compareTo(other.all) @@ -415,9 +357,11 @@ public inline fun > NonEmptyList.minBy(selector: (A) -> public inline fun > NonEmptyList.maxBy(selector: (A) -> B): A = maxByOrNull(selector)!! +@Suppress("NOTHING_TO_INLINE") public inline fun > NonEmptyList.min(): T = minOrNull()!! +@Suppress("NOTHING_TO_INLINE") public inline fun > NonEmptyList.max(): T = maxOrNull()!! @@ -429,88 +373,6 @@ public fun NonEmptyList.unzip(f: (C) -> Pair): Pair, Either>> { nel -> either> { nel.map { f(it).bind() } } }", - "arrow.core.raise.either") -) -public inline fun NonEmptyList.traverseEither(f: (A) -> Either): Either> = - traverse(f) - -@Deprecated( - "Traverse for Either is being deprecated in favor of Either DSL + NonEmptyList.map.\n$NicheAPI", - ReplaceWith( - "let, Either>> { nel -> either> { nel.map { f(it).bind() } } }", - "arrow.core.raise.either") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun NonEmptyList.traverse(f: (A) -> Either): Either> = - let { nel -> either { nel.map { f(it).bind() } } } - -@Deprecated( - "Sequence for Either is being deprecated in favor of Either DSL + NonEmptyList.map.\n$NicheAPI", - ReplaceWith("either> { this.map { it.bind() } }", "arrow.core.raise.either") -) -public fun NonEmptyList>.sequenceEither(): Either> = - sequence() - -@Deprecated( - "Sequence for Either is being deprecated in favor of Either DSL + NonEmptyList.map.\n$NicheAPI", - ReplaceWith("either> { this.map { it.bind() } }", "arrow.core.raise.either") -) -public fun NonEmptyList>.sequence(): Either> = - traverse(::identity) - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({ a, b -> a + b}) { f(it).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public inline fun NonEmptyList.traverseValidated( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({ a, b -> a + b}) { f(it).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun NonEmptyList.traverse( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({ e1, e2 -> e1 + e2 }) { it.bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun NonEmptyList>.sequenceValidated(semigroup: Semigroup): Validated> = - mapOrAccumulate(semigroup::combine) { it.bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({ e1, e2 -> e1 + e2 }) { it.bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun NonEmptyList>.sequence(semigroup: Semigroup): Validated> = - mapOrAccumulate(semigroup::combine) { it.bind() }.toValidated() - public inline fun NonEmptyList.mapOrAccumulate( combine: (E, E) -> E, @BuilderInference transform: RaiseAccumulate.(A) -> B @@ -522,49 +384,13 @@ public inline fun NonEmptyList.mapOrAccumulate( ): Either, NonEmptyList> = all.mapOrAccumulate(transform).map { requireNotNull(it.toNonEmptyListOrNull()) } -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + NonEmptyList.map.\\n$NicheAPI", - ReplaceWith( - "let, Option>> { nel -> option> { nel.map { f(it).bind() } } }", - "arrow.core.raise.option") -) -public inline fun NonEmptyList.traverseOption(f: (A) -> Option): Option> = - traverse(f) - -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + NonEmptyList.map.\\n$NicheAPI", - ReplaceWith( - "let, Option>> { nel -> option> { nel.map { f(it).bind() } } }", - "arrow.core.raise.option") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun NonEmptyList.traverse(f: (A) -> Option): Option> = - let { nel -> option { nel.map { f(it).bind() } } } - -@Deprecated( - "Sequence for Option is being deprecated in favor of Option DSL + NonEmptyList.map.\\n$NicheAPI", - ReplaceWith( - "option> { this.map { it.bind() } }", - "arrow.core.raise.option") -) -public fun NonEmptyList>.sequenceOption(): Option> = - sequence() - -@Deprecated( - "Sequence for Option is being deprecated in favor of Option DSL + NonEmptyList.map.\\n$NicheAPI", - ReplaceWith( - "option> { this.map { it.bind() } }", - "arrow.core.raise.option") -) -public fun NonEmptyList>.sequence(): Option> = - traverse(::identity) - +@JvmName("toNonEmptyListOrNull") public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? { val iter = iterator() if (!iter.hasNext()) return null return NonEmptyList(iter.next(), Iterable { iter }.toList()) } +@JvmName("toNonEmptyListOrNone") public fun Iterable.toNonEmptyListOrNone(): Option> = toNonEmptyListOrNull().toOption() diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 78abd143452..2f50cbfd989 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -21,25 +21,6 @@ public value class NonEmptySet private constructor( override fun lastOrNull(): A = elements.last() - @Suppress("OVERRIDE_BY_INLINE") - public override inline fun map(transform: (A) -> B): NonEmptyList = - elements.map(transform).toNonEmptyListOrNull()!! - - @Suppress("OVERRIDE_BY_INLINE") - public override inline fun mapIndexed(transform: (index: Int, A) -> B): NonEmptyList = - elements.mapIndexed(transform).toNonEmptyListOrNull()!! - - @Suppress("OVERRIDE_BY_INLINE") - public override inline fun flatMap(transform: (A) -> NonEmptyCollection): NonEmptyList = - elements.flatMap(transform).toNonEmptyListOrNull()!! - - override fun distinct(): NonEmptyList = - toNonEmptyList() - - @Suppress("OVERRIDE_BY_INLINE") - public override inline fun distinctBy(selector: (A) -> K): NonEmptyList = - elements.distinctBy(selector).toNonEmptyListOrNull()!! - override fun toString(): String = "NonEmptySet(${this.joinToString()})" @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") @@ -49,6 +30,24 @@ public value class NonEmptySet private constructor( @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") override fun hashCode(): Int = elements.hashCode() + + public override fun distinct(): NonEmptyList = + NonEmptyList(elements.distinct()) + + public override fun distinctBy(selector: (A) -> K): NonEmptyList = + NonEmptyList(elements.distinctBy(selector)) + + public override fun map(transform: (A) -> B): NonEmptyList = + NonEmptyList(elements.map(transform)) + + public override fun flatMap(transform: (A) -> NonEmptyCollection): NonEmptyList = + NonEmptyList(elements.flatMap(transform)) + + public override fun mapIndexed(transform: (index:Int, A) -> B): NonEmptyList = + NonEmptyList(elements.mapIndexed(transform)) + + override fun zip(other: NonEmptyCollection): NonEmptyList> = + NonEmptyList(elements.zip(other)) } public fun nonEmptySetOf(first: A, vararg rest: A): NonEmptySet = diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonFatal.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonFatal.kt index 05493d03e06..7740e42794f 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonFatal.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonFatal.kt @@ -24,7 +24,7 @@ import kotlin.coroutines.cancellation.CancellationException * else -> "Hello" * } * - * fun main(args: Array) { + * fun main() { * val nonFatal: Either = * //sampleStart * try { diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Nullable.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Nullable.kt deleted file mode 100644 index 9c7d9e6f864..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Nullable.kt +++ /dev/null @@ -1,165 +0,0 @@ -@file:Suppress("NAME_SHADOWING") - -package arrow.core - -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract -import kotlin.jvm.JvmStatic - -@OptIn(ExperimentalContracts::class) -public object Nullable { - - @JvmStatic - @Deprecated( - "Prefer using the let", - ReplaceWith("a?.let(fn)" - ) - ) - public inline fun zip(a: A?, fn: (A) -> R): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, Unit) { a, _ -> fn(a) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith("nullable { fn(a.bind(), b.bind()) }", "arrow.core.raise.nullable") - ) - public inline fun zip(a: A?, b: B?, fn: (A, B) -> R): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, Unit) { a, b, _ -> fn(a, b) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind()) }", "arrow.core.raise.nullable" - ) - ) - public inline fun zip(a: A?, b: B?, c: C?, fn: (A, B, C) -> R): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, Unit) { a, b, c, _ -> fn(a, b, c) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind()) }", "arrow.core.raise.nullable" - ) - ) - public inline fun zip(a: A?, b: B?, c: C?, d: D?, fn: (A, B, C, D) -> R): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, Unit) { a, b, c, d, _ -> fn(a, b, c, d) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip(a: A?, b: B?, c: C?, d: D?, e: E?, fn: (A, B, C, D, E) -> R): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, e, Unit) { a, b, c, d, e, _ -> fn(a, b, c, d, e) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip( - a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, fn: (A, B, C, D, E, F) -> R - ): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, e, f, Unit) { a, b, c, d, e, f, _ -> fn(a, b, c, d, e, f) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip( - a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, fn: (A, B, C, D, E, F, G) -> R - ): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, e, f, g, Unit) { a, b, c, d, e, f, g, _ -> fn(a, b, c, d, e, f, g) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip( - a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, h: H?, fn: (A, B, C, D, E, F, G, H) -> R - ): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, e, f, g, h, Unit) { a, b, c, d, e, f, g, h, _ -> fn(a, b, c, d, e, f, g, h) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip( - a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, h: H?, i: I?, fn: (A, B, C, D, E, F, G, H, I) -> R - ): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return zip(a, b, c, d, e, f, g, h, i, Unit) { a, b, c, d, e, f, g, h, i, _ -> fn(a, b, c, d, e, f, g, h, i) } - } - - @JvmStatic - @Deprecated( - "Prefer using the inline nullable DSL", - ReplaceWith( - "nullable { fn(a.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) }", - "arrow.core.raise.nullable" - ) - ) - public inline fun zip( - a: A?, b: B?, c: C?, d: D?, e: E?, f: F?, g: G?, h: H?, i: I?, j: J?, fn: (A, B, C, D, E, F, G, H, I, J) -> R - ): R? { - contract { callsInPlace(fn, InvocationKind.AT_MOST_ONCE) } - return a?.let { a -> - b?.let { b -> - c?.let { c -> - d?.let { d -> - e?.let { e -> - f?.let { f -> - g?.let { g -> - h?.let { h -> - i?.let { i -> - j?.let { j -> - fn(a, b, c, d, e, f, g, h, i, j) - } - } - } - } - } - } - } - } - } - } - } -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt index a98980daf1f..d445d134165 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Option.kt @@ -1,20 +1,13 @@ @file:OptIn(ExperimentalContracts::class) package arrow.core -import arrow.core.Either.Right import arrow.core.raise.EagerEffect import arrow.core.raise.Effect -import arrow.core.raise.OptionRaise +import arrow.core.raise.SingletonRaise import arrow.core.raise.option -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -296,64 +289,6 @@ import kotlin.jvm.JvmStatic * ``` * * - * ### Computing over independent values - * - * ```kotlin - * import arrow.core.Some - * - * val value = - * //sampleStart - * Some(1).zip(Some("Hello"), Some(20.0), ::Triple) - * //sampleEnd - * fun main() { - * println(value) - * } - * ``` - * - * - * ### Computing over dependent values ignoring absence - * - * ```kotlin - * import arrow.core.computations.option - * import arrow.core.Some - * import arrow.core.Option - * - * suspend fun value(): Option = - * //sampleStart - * option { - * val a = Some(1).bind() - * val b = Some(1 + a).bind() - * val c = Some(1 + b).bind() - * a + b + c - * } - * //sampleEnd - * suspend fun main() { - * println(value()) - * } - * ``` - * - * - * ```kotlin - * import arrow.core.computations.option - * import arrow.core.Some - * import arrow.core.none - * import arrow.core.Option - * - * suspend fun value(): Option = - * //sampleStart - * option { - * val x = none().bind() - * val y = Some(1 + x).bind() - * val z = Some(1 + y).bind() - * x + y + z - * } - * //sampleEnd - * suspend fun main() { - * println(value()) - * } - * ``` - * - * * ## Credits * * Contents partially adapted from [Scala Exercises Option Tutorial](https://www.scala-exercises.org/std_lib/options) @@ -376,15 +311,14 @@ public sealed class Option { */ public inline fun catch(f: () -> A): Option { contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - val recover: (Throwable) -> Option = { None } - return catch(recover, f) + return catch({ None }, f) } @JvmStatic @JvmName("tryCatch") public inline fun catch(recover: (Throwable) -> Option, f: () -> A): Option { contract { - callsInPlace(f, InvocationKind.EXACTLY_ONCE) + callsInPlace(f, InvocationKind.AT_MOST_ONCE) callsInPlace(recover, InvocationKind.AT_MOST_ONCE) } return try { @@ -393,55 +327,6 @@ public sealed class Option { recover(t.nonFatalOrThrow()) } } - - @JvmStatic - @Deprecated( - RedundantAPI + "Prefer explicitly creating lambdas", - ReplaceWith("{ it.map(f) }") - ) - public fun lift(f: (A) -> B): (Option) -> Option = - { it.map(f) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { Pair(bind(), b.bind()) }", - "arrow.core.raise.option" - ) - ) - public fun zip(other: Option): Option> = - zip(other, ::Pair) - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - map: (A, B) -> C - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - map: (A, B, C) -> D - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind()) } } /** @@ -460,13 +345,13 @@ public sealed class Option { * none().onNone { println("flower") } // Result: prints "flower" and returns: None * } * ``` - * + * */ public inline fun onNone(action: () -> Unit): Option { contract { callsInPlace(action, InvocationKind.AT_MOST_ONCE) } - return also { if (it.isEmpty()) action() } + return also { if (it.isNone()) action() } } /** @@ -485,229 +370,13 @@ public sealed class Option { * none().onSome { println("flower") } // Result: None * } * ``` - * + * */ public inline fun onSome(action: (A) -> Unit): Option { contract { callsInPlace(action, InvocationKind.AT_MOST_ONCE) } - return also { if (it.isNotEmpty()) action(it.value) } - } - - /** - * The given function is applied as a fire and forget effect - * if this is a `None`. - * When applied the result is ignored and the original - * None value is returned - * - * Example: - * ```kotlin - * import arrow.core.Some - * import arrow.core.none - * - * fun main() { - * Some(12).tapNone { println("flower") } // Result: Some(12) - * none().tapNone { println("flower") } // Result: prints "flower" and returns: None - * } - * ``` - * - */ - @Deprecated( - "tapNone is being renamed to onNone to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("onNone(f)") - ) - public inline fun tapNone(f: () -> Unit): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return onNone(f) - } - - /** - * The given function is applied as a fire and forget effect - * if this is a `some`. - * When applied the result is ignored and the original - * Some value is returned - * - * Example: - * ```kotlin - * import arrow.core.Some - * import arrow.core.none - * - * fun main() { - * Some(12).tap { println("flower") } // Result: prints "flower" and returns: Some(12) - * none().tap { println("flower") } // Result: None - * } - * ``` - * - */ - @Deprecated( - "tap is being renamed to onSome to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("onSome(f)") - ) - public inline fun tap(f: (A) -> Unit): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return onSome(f) - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - map: (A, B, C, D) -> E - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - map: (A, B, C, D, E) -> F - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - map: (A, B, C, D, E, F) -> G - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - g: Option, - map: (A, B, C, D, E, F, G) -> H - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - g: Option, - h: Option, - map: (A, B, C, D, E, F, G, H) -> I - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - g: Option, - h: Option, - i: Option, - map: (A, B, C, D, E, F, G, H, I) -> J - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) } - } - - @Deprecated( - "Prefer using the inline option DSL", - ReplaceWith( - "option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) }", - "arrow.core.raise.option" - ) - ) - public inline fun zip( - b: Option, - c: Option, - d: Option, - e: Option, - f: Option, - g: Option, - h: Option, - i: Option, - j: Option, - map: (A, B, C, D, E, F, G, H, I, J) -> K - ): Option { - contract { callsInPlace(map, InvocationKind.AT_MOST_ONCE) } - return option { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) } - } - - /** - * Returns true if the option is [None], false otherwise. - * @note Used only for performance instead of fold. - */ - @Deprecated( - "Duplicated API. Please use Option's member function isNone. This will be removed towards Arrow 2.0", - ReplaceWith("isNone()") - ) - public abstract fun isEmpty(): Boolean - - @Deprecated( - "Duplicated API. Please use Option's member function isSome. This will be removed towards Arrow 2.0", - ReplaceWith("isSome()") - ) - public fun isNotEmpty(): Boolean { - contract { - returns(true) implies (this@Option is Some) - returns(false) implies (this@Option is None) - } - return this@Option is Some + return also { if (it.isSome()) action(it.value) } } /** @@ -753,47 +422,17 @@ public sealed class Option { * none.isSome { it > 10 } // Result: false * } * ``` - * + * * * @param predicate the predicate to test */ public inline fun isSome(predicate: (A) -> Boolean): Boolean { contract { - callsInPlace(predicate, InvocationKind.EXACTLY_ONCE) + callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) returns(true) implies (this@Option is Some) } return this@Option is Some && predicate(value) } - /** - * alias for [isDefined] - */ - @Deprecated( - "Duplicated API. Please use Option's member function isSome. This will be removed towards Arrow 2.0", - ReplaceWith("isSome()") - ) - public fun nonEmpty(): Boolean = isDefined() - - /** - * Returns true if the option is an instance of [Some], false otherwise. - * @note Used only for performance instead of fold. - */ - @Deprecated( - "Duplicated API. Please use Option's member function isSome. This will be removed towards Arrow 2.0", - ReplaceWith("isSome()") - ) - public fun isDefined(): Boolean = !isEmpty() - - @Deprecated( - "orNull is being renamed to getOrNull to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNull()") - ) - public fun orNull(): A? { - contract { - returns(null) implies (this@Option is None) - returnsNotNull() implies (this@Option is Some) - } - return fold({ null }, ::identity) - } /** * Returns the encapsulated value [A] if this instance represents [Some] or `null` if it is [None]. @@ -808,7 +447,7 @@ public sealed class Option { * None.getOrNull() shouldBe null * } * ``` - * + * */ public fun getOrNull(): A? { contract { @@ -844,27 +483,6 @@ public sealed class Option { } } - /** - * Returns $none if the result of applying $f to this $option's value is null. - * Otherwise returns the result. - * - * @note This is similar to `.flatMap { Option.fromNullable(null)) }` - * and primarily for convenience. - * - * @param f the function to apply. - * */ - @Deprecated( - NicheAPI + "Prefer using the Option DSL, or fold or map", - ReplaceWith( - "flatMap { fromNullable(f(it)) }", - "arrow.core.Option.Companion.fromNullable" - ) - ) - public inline fun mapNotNull(f: (A) -> B?): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return flatMap { a -> fromNullable(f(a)) } - } - /** * Returns the result of applying $f to this $option's value if * this $option is nonempty. @@ -883,91 +501,6 @@ public sealed class Option { } } - /** - * Align two options (`this` on the left and [b] on the right) as one Option of [Ior]. - */ - @Deprecated(NicheAPI + "Prefer using a simple fold, or when expression") - public infix fun align(b: Option): Option> = - when (this) { - None -> when (b) { - None -> None - is Some -> Some(b.value.rightIor()) - } - - is Some -> when (b) { - None -> Some(this.value.leftIor()) - is Some -> Some(Pair(this.value, b.value).bothIor()) - } - } - - /** - * Align two options (`this` on the left and [b] on the right) as one Option of [Ior], and then, if it's not [None], map it using [f]. - * - * @note This function works like a regular `align` function, but is then mapped by the `map` function. - */ - @Deprecated(NicheAPI + "Prefer using a simple fold, or when expression") - public inline fun align(b: Option, f: (Ior) -> C): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return align(b).map(f) - } - - /** - * Returns true if this option is empty '''or''' the predicate - * $predicate returns true when applied to this $option's value. - * - * @param predicate the predicate to test - */ - @Deprecated( - NicheAPI + "Prefer using the Option DSL, or fold or map", - ReplaceWith("fold({ true }, predicate)") - ) - public inline fun all(predicate: (A) -> Boolean): Boolean { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return fold({ true }, predicate) - } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or fold", - ReplaceWith( - "fold>>({ None }) { value -> f(value).map(::Some) }", - "arrow.core.None", - "arrow.core.Option", - "arrow.core.Some" - ) - ) - public inline fun crosswalk(f: (A) -> Option): Option> = - when (this) { - is None -> this - is Some -> f(value).map { Some(it) } - } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or fold", - ReplaceWith( - "fold>>({ emptyMap() }) { value -> f(value).mapValues { Some(it.value) } }", - "arrow.core.Option", - "arrow.core.Some" - ) - ) - public inline fun crosswalkMap(f: (A) -> Map): Map> = - when (this) { - is None -> emptyMap() - is Some -> f(value).mapValues { Some(it.value) } - } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or fold", - ReplaceWith( - "getOrNull()?.let { value -> f(value)?.let(::Some) }", - "arrow.core.Some" - ) - ) - public inline fun crosswalkNull(f: (A) -> B?): Option? = - when (this) { - is None -> null - is Some -> f(value)?.let { Some(it) } - } - /** * Returns this $option if it is nonempty '''and''' applying the predicate $p to * this $option's value returns true. Otherwise, return $none. @@ -990,202 +523,6 @@ public sealed class Option { return flatMap { a -> if (!predicate(a)) Some(a) else None } } - /** - * Returns true if this option is nonempty '''and''' the predicate - * $p returns true when applied to this $option's value. - * Otherwise, returns false. - * - * Example: - * ```kotlin - * import arrow.core.Some - * import arrow.core.None - * import arrow.core.Option - * - * fun main() { - * Some(12).exists { it > 10 } // Result: true - * Some(7).exists { it > 10 } // Result: false - * - * val none: Option = None - * none.exists { it > 10 } // Result: false - * } - * ``` - * - * - * @param predicate the predicate to test - */ - @Deprecated( - RedundantAPI + "Please use Option's member function isSome. This will be removed towards Arrow 2.0", - ReplaceWith("isSome(predicate)") - ) - public inline fun exists(predicate: (A) -> Boolean): Boolean { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return fold({ false }, predicate) - } - - /** - * Returns the $option's value if this option is nonempty '''and''' the predicate - * $p returns true when applied to this $option's value. - * Otherwise, returns null. - * - * Example: - * ```kotlin - * import arrow.core.Some - * import arrow.core.None - * import arrow.core.Option - * - * fun main() { - * Some(12).exists { it > 10 } // Result: 12 - * Some(7).exists { it > 10 } // Result: null - * - * val none: Option = None - * none.exists { it > 10 } // Result: null - * } - * ``` - * - */ - @Deprecated( - NicheAPI + "Prefer Kotlin nullable syntax instead", - ReplaceWith("getOrNull()?.takeIf(predicate)") - ) - public inline fun findOrNull(predicate: (A) -> Boolean): A? { - contract { callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) } - return when (this) { - is Some -> if (predicate(value)) value else null - is None -> null - } - } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ ifEmpty }, f)") - ) - public inline fun foldMap(MB: Monoid, f: (A) -> B): B = - fold({ MB.empty() }, f) - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("fold({ initial }) { operation(initial, it) }") - ) - public inline fun foldLeft(initial: B, operation: (B, A) -> B): B = - when (this) { - is Some -> operation(initial, value) - is None -> initial - } - - @Deprecated(NicheAPI + "Prefer using a simple fold, or when expression") - public fun padZip(other: Option): Option> = - align(other) { ior -> - ior.fold( - { it to null }, - { null to it }, - { a, b -> a to b } - ) - } - - @Deprecated(NicheAPI + "Prefer using a simple fold, or when expression") - public inline fun padZip(other: Option, f: (A?, B?) -> C): Option = - align(other) { ior -> - ior.fold( - { f(it, null) }, - { f(null, it) }, - { a, b -> f(a, b) } - ) - } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith("getOrNull()?.let { value -> operation(initial(value), value) }") - ) - public inline fun reduceOrNull(initial: (A) -> B, operation: (acc: B, A) -> B): B? = - when (this) { - is None -> null - is Some -> operation(initial(value), value) - } - - @Deprecated( - NicheAPI + "Prefer when or fold instead", - ReplaceWith( - "fold({ Eval.now(null) }) { value -> operation(value, Eval.now(initial(value))) }", - "arrow.core.Eval" - ) - ) - public inline fun reduceRightEvalOrNull( - initial: (A) -> B, - operation: (A, acc: Eval) -> Eval - ): Eval = - when (this) { - is None -> Eval.now(null) - is Some -> operation(value, Eval.now(initial(value))) - } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or map", - ReplaceWith("map { List(n) { it } }") - ) - public fun replicate(n: Int): Option> = - if (n <= 0) Some(emptyList()) else map { a -> List(n) { a } } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ listOf(None) }) { a -> fa(a).map(::Some) }", - "arrow.core.None", - "arrow.core.Some" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Iterable): List> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return fold({ listOf(None) }, { a -> fa(a).map { Some(it) } }) - } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ Right(None) }) { a -> fa(a).map(::Some) }", - "arrow.core.Either.Right", - "arrow.core.None", - "arrow.core.Some" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Either): Either> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return when (this) { - is Some -> fa(value).map { Some(it) } - is None -> Right(this) - } - } - - @Deprecated("traverseEither is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseEither(fa: (A) -> Either): Either> = - traverse(fa) - - @Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ Valid(None) }) { a -> fa(a).map(::Some) }", - "arrow.core.Valid", - "arrow.core.None", - "arrow.core.Some" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Validated): Validated> { - contract { callsInPlace(fa, InvocationKind.AT_MOST_ONCE) } - return when (this) { - is Some -> fa(value).map { Some(it) } - is None -> Valid(this) - } - } - - @Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseValidated(fa: (A) -> Validated): Validated> = - traverse(fa) - public inline fun toEither(ifEmpty: () -> L): Either { contract { callsInPlace(ifEmpty, InvocationKind.AT_MOST_ONCE) } return fold({ ifEmpty().left() }, { it.right() }) @@ -1193,35 +530,6 @@ public sealed class Option { public fun toList(): List = fold(::emptyList) { listOf(it) } - @Deprecated( - RedundantAPI + "Replace with map with Unit", - ReplaceWith("map { }") - ) - public fun void(): Option = - map { } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or map", - ReplaceWith("map { left to it }") - ) - public fun pairLeft(left: L): Option> = this.map { left to it } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or map", - ReplaceWith("map { it to right }") - ) - public fun pairRight(right: R): Option> = this.map { it to right } - - @Deprecated( - NicheAPI + "Prefer using the Option DSL or flatMap", - ReplaceWith("flatMap { value }") - ) - public infix fun and(value: Option): Option = if (isEmpty()) { - None - } else { - value - } - override fun toString(): String = fold( { "Option.None" }, { "Option.Some($it)" } @@ -1229,29 +537,13 @@ public sealed class Option { } public object None : Option() { - @Deprecated( - "Duplicated API. Please use Option's member function isNone. This will be removed towards Arrow 2.0", - replaceWith = ReplaceWith("isNone()") - ) - public override fun isEmpty(): Boolean = true - override fun toString(): String = "Option.None" } public data class Some(val value: T) : Option() { - @Deprecated( - "Duplicated API. Please use Option's member function isNone. This will be removed towards Arrow 2.0", - replaceWith = ReplaceWith("isNone()") - ) - public override fun isEmpty(): Boolean = false - override fun toString(): String = "Option.Some($value)" - public companion object { - @PublishedApi - @Deprecated("Unused, will be removed from bytecode in Arrow 2.x.x", ReplaceWith("Some(Unit)")) - internal val unit: Option = Some(Unit) - } + public companion object } /** @@ -1262,29 +554,12 @@ public data class Some(val value: T) : Option() { */ public inline fun Option.getOrElse(default: () -> T): T { contract { callsInPlace(default, InvocationKind.AT_MOST_ONCE) } - return fold({ default() }, ::identity) + return when (this) { + is Some -> value + else -> default() + } } -/** - * Returns this option's if the option is nonempty, otherwise - * returns another option provided lazily by `default`. - * - * @param alternative the default option if this is empty. - */ -@Deprecated( - NicheAPI + "Prefer using the recover method", - ReplaceWith("recover { alternative().bind() }", "arrow.core.recover") -) -public inline fun Option.orElse(alternative: () -> Option): Option = - recover { alternative().bind() } - -@Deprecated( - NicheAPI + "Prefer using the recover method", - ReplaceWith("recover { value.bind() }", "arrow.core.recover") -) -public infix fun Option.or(value: Option): Option = - recover { value.bind() } - public fun T?.toOption(): Option = this?.let { Some(it) } ?: None /** Run the [Effect] by returning [Option] of [A], or [None] if raised with [None]. */ @@ -1293,60 +568,10 @@ public suspend fun Effect.toOption(): Option = option { invoke() /** Run the [EagerEffect] by returning [Option] of [A], or [None] if raised with [None]. */ public fun EagerEffect.toOption(): Option = option { invoke() } -@Deprecated( - NicheAPI + "Prefer using if-else statement", - ReplaceWith( - "if (this) { Some(f()) } else { None }", - "arrow.core.None", - "arrow.core.Some" - ) -) -public inline fun Boolean.maybe(f: () -> A): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return if (this) { - Some(f()) - } else { - None - } -} - public fun A.some(): Option = Some(this) public fun none(): Option = None -@Deprecated(SemigroupDeprecation, ReplaceWith("fold(none()) { x, y -> x.combine(y){a1, a2 -> a1 + a2} }")) -public fun Iterable>.combineAll(MA: Monoid): Option = - fold(none()) { x, y -> x.combine(y, MA::combine) } - -@Deprecated("use getOrElse instead", ReplaceWith("getOrElse { empty }")) -public fun Option.combineAll(MA: Monoid): A = - getOrElse { MA.empty() } - -@Deprecated( - RedundantAPI + "Prefer if-else statement inside option DSL, or replace with explicit flatMap", - ReplaceWith( - "this.flatMap { b -> b.takeIf(predicate)?.let(::Some) ?: None.also(error) }", - "arrow.core.Some", - "arrow.core.None" - ) -) -public inline fun Option.ensure(error: () -> Unit, predicate: (A) -> Boolean): Option { - contract { - callsInPlace(predicate, InvocationKind.AT_MOST_ONCE) - callsInPlace(error, InvocationKind.AT_MOST_ONCE) - } - return when (this) { - is Some -> - if (predicate(value)) this - else { - error() - None - } - - is None -> this - } -} - /** * Returns an Option containing all elements that are instances of specified type parameter [B]. */ @@ -1358,273 +583,9 @@ public inline fun Option<*>.filterIsInstance(): Option = } } -@Deprecated( - NicheAPI + "Prefer using the orElse method", - ReplaceWith( - "recover { f(Unit) }", - "arrow.core.recover" - ) -) -public inline fun Option.handleError(f: (Unit) -> A): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return recover { f(Unit) } -} - -@Deprecated( - NicheAPI + "Prefer using the orElse method", - ReplaceWith( - "recover { f(Unit).bind() }", - "arrow.core.recover" - ) -) -public inline fun Option.handleErrorWith(f: (Unit) -> Option): Option { - contract { callsInPlace(f, InvocationKind.AT_MOST_ONCE) } - return recover { f(Unit).bind() } -} - public fun Option>.flatten(): Option = flatMap(::identity) -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit fold with some", - ReplaceWith( - "fold({ fe(Unit) }, fb).some()", - "arrow.core.some" - ) -) -public inline fun Option.redeem(fe: (Unit) -> B, fb: (A) -> B): Option { - contract { - callsInPlace(fe, InvocationKind.AT_MOST_ONCE) - callsInPlace(fb, InvocationKind.AT_MOST_ONCE) - } - return fold({ fe(Unit) }, fb).some() -} - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit flatMap with orElse", - ReplaceWith( - "flatMap(fb).recover { fe(Unit).bind() }", - "arrow.core.recover" - ) -) -public inline fun Option.redeemWith(fe: (Unit) -> Option, fb: (A) -> Option): Option { - contract { - callsInPlace(fe, InvocationKind.AT_MOST_ONCE) - callsInPlace(fb, InvocationKind.AT_MOST_ONCE) - } - return flatMap(fb).recover { fe(Unit).bind() } -} - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or map", - ReplaceWith("this.map { a -> List(n) { a }.fold(initial){a1, a2 -> a1 + a2} }") -) -public fun Option.replicate(n: Int, MA: Monoid): Option = - map { a -> List(n) { a }.fold(MA.empty(), MA::combine) } - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit flatmap", - ReplaceWith( - "flatMap { it.fold({ None }, { a -> Some(a) }) }", - "arrow.core.None", "arrow.core.Some" - ) -) -public fun Option>.rethrow(): Option = - flatMap { it.fold({ None }, { a -> Some(a) }) } - -@Deprecated(NicheAPI + "Prefer using a simple fold, or when expression") -public fun Option.salign(SA: Semigroup, b: Option): Option = - align(b) { - it.fold(::identity, ::identity) { a, b -> - SA.run { a.combine(b) } - } - } - -/** - * Separate the inner [Either] value into the [Either.Left] and [Either.Right]. - * - * @receiver Option of Either - * @return a tuple containing Option of [Either.Left] and another Option of its [Either.Right] value. - */ -@Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ None to None }) { either -> either.fold, Option>>({ Some(it) to None }, { None to Some(it) }) }", - "arrow.core.None", "arrow.core.Some", "arrow.core.Option" - ) -) -public fun Option>.separateEither(): Pair, Option> = - fold({ None to None }) { either -> - either.fold( - { Some(it) to None }, - { None to Some(it) } - ) - } - -/** - * Separate the inner [Validated] value into the [Validated.Invalid] and [Validated.Valid]. - * - * @receiver Option of Either - * @return a tuple containing Option of [Validated.Invalid] and another Option of its [Validated.Valid] value. - */ -@Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ None to None }) { validated -> validated.fold, Option>>({ Some(it) to None }, { None to Some(it) }) }", - "arrow.core.None", "arrow.core.Some", "arrow.core.Option" - ) -) -public fun Option>.separateValidated(): Pair, Option> = - fold({ None to None }) { validated -> - validated.fold( - { Some(it) to None }, - { None to Some(it) } - ) - } - -@Deprecated( - "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ emptyList() }) { a -> fa(a).map(::Some) }", - "arrow.core.Some", - ) -) -public fun Option>.sequence(): List> = - traverse(::identity) - -@Deprecated( - "sequenceEither is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Option>.sequenceEither(): Either> = - sequence() - -@Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ Right(None) }) { a -> fa(a).map(::Some) }", - "arrow.core.Either.Right", - "arrow.core.None", - "arrow.core.Some" - ) -) -public fun Option>.sequence(): Either> = - traverse(::identity) - -@Deprecated( - "sequenceValidated is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Option>.sequenceValidated(): Validated> = - sequence() - -@Deprecated( - NicheAPI + "Prefer using the Option DSL, or explicit fold or when", - ReplaceWith( - "fold({ Valid(None) }) { a -> fa(a).map(::Some) }", - "arrow.core.Valid", - "arrow.core.None", - "arrow.core.Some" - ) -) -public fun Option>.sequence(): Validated> = - traverse(::identity) - -@Deprecated(NicheAPI + "Prefer using a when expression") -public fun Option>.unalign(): Pair, Option> = - unalign(::identity) - -@Deprecated(NicheAPI + "Prefer using a when expression") -public inline fun Option.unalign(f: (C) -> Ior): Pair, Option> = - when (val option = this.map(f)) { - is None -> None to None - is Some -> when (val v = option.value) { - is Ior.Left -> Some(v.value) to None - is Ior.Right -> None to Some(v.value) - is Ior.Both -> Some(v.leftValue) to Some(v.rightValue) - } - } - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit map", - ReplaceWith( - "map { iterable -> iterable.fold(MA) }", - "arrow.typeclasses.Monoid" - ) -) -public fun Option>.unite(MA: Monoid): Option = - map { iterable -> - iterable.fold(MA) - } - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit flatMap", - ReplaceWith( - "flatMap { either -> either.fold>({ None }, ::Some) }", - "arrow.core.Option", "arrow.core.Some", "arrow.core.None" - ) -) -public fun Option>.uniteEither(): Option = - flatMap { either -> - either.fold({ None }, { b -> Some(b) }) - } - -@Deprecated( - NicheAPI + "Prefer using the Option DSL or explicit flatMap", - ReplaceWith( - "flatMap { validated -> validated.fold>({ None }, ::Some) }", - "arrow.core.Option", "arrow.core.Some", "arrow.core.None" - ) -) -public fun Option>.uniteValidated(): Option = - flatMap { validated -> - validated.fold({ None }, { b -> Some(b) }) - } - -@Deprecated( - NicheAPI + "Prefer using fold, when or Option DSL", - ReplaceWith( - "fold({ None to None }, { (a, b) -> Some(a) to Some(b) })", - "arrow.core.Option", "arrow.core.Some", "arrow.core.None" - ) -) -public fun Option>.unzip(): Pair, Option> = - fold({ None to None }, { (a, b) -> Some(a) to Some(b) }) - -@Deprecated( - NicheAPI + "Prefer using fold, when or Option DSL", - ReplaceWith( - "fold({ None to None }, { f(it).let { (a, b) -> Some(a) to Some(b) } })", - "arrow.core.Option", "arrow.core.Some", "arrow.core.None" - ) -) -public inline fun Option.unzip(f: (C) -> Pair): Pair, Option> = - fold({ None to None }, { f(it).let { (a, b) -> Some(a) to Some(b) } }) - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [A] is a sub type of [B], re-type this value from Option to Option - * - * Option -> Option - * - * ```kotlin - * import arrow.core.Option - * import arrow.core.some - * import arrow.core.widen - * - * fun main(args: Array) { - * val result: Option = - * //sampleStart - * "Hello".some().map({ "$it World" }).widen() - * //sampleEnd - * println(result) - * } - * ``` - * - */ -public fun Option.widen(): Option = - this - public fun Option>.toMap(): Map = this.toList().toMap() public fun Option.combine(other: Option, combine: (A, A) -> A): Option = @@ -1636,10 +597,6 @@ public fun Option.combine(other: Option, combine: (A, A) -> A): Option None -> other } -@Deprecated(SemigroupDeprecation, ReplaceWith("this.combine(b){a1, a2 -> a1 + a2}")) -public fun Option.combine(SGA: Semigroup, b: Option): Option = - combine(b, SGA::combine) - public operator fun > Option.compareTo(other: Option): Int = fold( { other.fold({ 0 }, { -1 }) }, { a1 -> @@ -1667,7 +624,7 @@ public operator fun > Option.compareTo(other: Option): I * fallback shouldBe Some(5) * } * ``` - * + * * * * When shifting a new error [None] into the [Option]: @@ -1688,11 +645,11 @@ public operator fun > Option.compareTo(other: Option): I * error.recover { failure().bind() } shouldBe none() * } * ``` - * + * * */ -public inline fun Option.recover(recover: OptionRaise.(None) -> A): Option = +public inline fun Option.recover(recover: SingletonRaise.() -> A): Option = when (this@recover) { - is None -> option { recover(this, None) } + is None -> option { recover() } is Some -> this@recover } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Pair.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Pair.kt index 9fea3c74ed9..8ee2e2f6f3d 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Pair.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Pair.kt @@ -3,9 +3,6 @@ package arrow.core -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -14,14 +11,3 @@ public operator fun , B : Comparable> Pair.compareTo( return if (first == 0) second.compareTo(other.second) else first } - - -@Deprecated( - "$SemigroupDeprecation\n$NicheAPI", - ReplaceWith( - "Pair(SA.combine(first, b.first), SB.combine(second, b.second))", - "arrow.typeclasses.combine" - ) -) -public fun Pair.combine(SA: Semigroup, SB: Semigroup, b: Pair): Pair = - Pair(SA.combine(first, b.first), SB.combine(second, b.second)) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Result.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Result.kt index 5a4ba04e090..cf0c3e3c949 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Result.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Result.kt @@ -3,19 +3,10 @@ package arrow.core import kotlin.Result.Companion.failure -import kotlin.Result.Companion.success import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract -@PublishedApi internal const val deprecateZip: String = - "Prefer using the inline result DSL + bind(). Please, be aware that all the errors are no longer accumulated, just the first error found is considered." + - "In case you think this behaviour should stay, please provide feedback and your use-case on https://github.com/arrow-kt/arrow/issues" - -@PublishedApi -internal inline val UnitResult: Result - inline get() = success(Unit) - /** * Compose a [transform] operation on the success value [A] into [B] whilst flattening [Result]. * @see mapCatching if you want run a function that catches and maps with `(A) -> B` @@ -24,317 +15,3 @@ public inline fun Result.flatMap(transform: (value: A) -> Result): contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } return map(transform).fold(::identity, ::failure) } - -/** - * Compose a recovering [transform] operation on the failure value [Throwable] whilst flattening [Result]. - * @see recoverCatching if you want run a function that catches and maps recovers with `(Throwable) -> A`. - */ -@Deprecated( - "Prefer Kotlin Std Result.recoverCatching instead of handleErrorWith", - ReplaceWith("recoverCatching { transform(it).getOrThrow() }") -) -public inline fun Result.handleErrorWith(transform: (throwable: Throwable) -> Result): Result = - recoverCatching { transform(it).getOrThrow() } - -/** - * Compose both: - * - a [transform] operation on the success value [A] into [B] whilst flattening [Result]. - * - a recovering [transform] operation on the failure value [Throwable] whilst flattening [Result]. - * - * Combining the powers of [flatMap] and [handleErrorWith]. - */ -@Deprecated( - "Prefer Kotlin Std Result.fold instead of redeemWith", - ReplaceWith("fold(transform, handleErrorWith)") -) -public inline fun Result.redeemWith( - handleErrorWith: (throwable: Throwable) -> Result, - transform: (value: A) -> Result -): Result { - contract { - callsInPlace(handleErrorWith, InvocationKind.AT_MOST_ONCE) - callsInPlace(transform, InvocationKind.AT_MOST_ONCE) - } - return fold(transform, handleErrorWith) -} - -/** - * Combines n-arity independent [Result] values with a [transform] function. - */ -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip(b: Result, transform: (A, B) -> C): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip( - b, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult - ) { a, b, _, _, _, _, _, _, _, _ -> transform(a, b) } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip(b: Result, c: Result, transform: (A, B, C) -> D): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip( - b, - c, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult - ) { a, b, c, _, _, _, _, _, _, _ -> transform(a, b, c) } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - transform: (A, B, C, D) -> E -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip( - b, - c, - d, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult, - UnitResult - ) { a, b, c, d, _, _, _, _, _, _ -> transform(a, b, c, d) } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - transform: (A, B, C, D, E) -> F -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip(b, c, d, e, UnitResult, UnitResult, UnitResult, UnitResult, UnitResult) { a, b, c, d, e, f, _, _, _, _ -> - transform( - a, - b, - c, - d, - e - ) - } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - f: Result, - transform: (A, B, C, D, E, F) -> G -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip(b, c, d, e, f, UnitResult, UnitResult, UnitResult, UnitResult) { a, b, c, d, e, f, _, _, _, _ -> - transform( - a, - b, - c, - d, - e, - f - ) - } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - f: Result, - g: Result, - transform: (A, B, C, D, E, F, G) -> H -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip(b, c, d, e, f, g, UnitResult, UnitResult, UnitResult) { a, b, c, d, e, f, g, _, _, _ -> - transform( - a, - b, - c, - d, - e, - f, - g - ) - } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - f: Result, - g: Result, - h: Result, - transform: (A, B, C, D, E, F, G, H) -> I -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip(b, c, d, e, f, g, h, UnitResult, UnitResult) { a, b, c, d, e, f, g, h, _, _ -> - transform( - a, - b, - c, - d, - e, - f, - g, - h - ) - } -} - -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - f: Result, - g: Result, - h: Result, - i: Result, - transform: (A, B, C, D, E, F, G, H, I) -> J -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return zip(b, c, d, e, f, g, h, i, UnitResult) { a, b, c, d, e, f, g, h, i, _ -> - transform( - a, - b, - c, - d, - e, - f, - g, - h, - i - ) - } -} - -@Suppress("UNCHECKED_CAST") -@Deprecated( - deprecateZip, - ReplaceWith( - "result {transform(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), k.bind()) }", - "arrow.core.raise.result" - ) -) -public inline fun Result.zip( - b: Result, - c: Result, - d: Result, - e: Result, - f: Result, - g: Result, - h: Result, - i: Result, - j: Result, - transform: (A, B, C, D, E, F, G, H, I, J) -> K, -): Result { - contract { callsInPlace(transform, InvocationKind.AT_MOST_ONCE) } - return if (isSuccess && b.isSuccess && c.isSuccess && d.isSuccess && e.isSuccess && f.isSuccess && g.isSuccess && h.isSuccess && i.isSuccess && j.isSuccess) - success( - transform( - getOrNull() as A, - b.getOrNull() as B, - c.getOrNull() as C, - d.getOrNull() as D, - e.getOrNull() as E, - f.getOrNull() as F, - g.getOrNull() as G, - h.getOrNull() as H, - i.getOrNull() as I, - j.getOrNull() as J - ) - ) else - composeErrors( - exceptionOrNull(), - b.exceptionOrNull(), - c.exceptionOrNull(), - d.exceptionOrNull(), - e.exceptionOrNull(), - f.exceptionOrNull(), - g.exceptionOrNull(), - h.exceptionOrNull(), - i.exceptionOrNull(), - j.exceptionOrNull(), - )!!.let(::failure) -} - -@PublishedApi -internal fun composeErrors(vararg other: Throwable?): Throwable? = - other.reduceOrNull { a, b -> - Nullable.zip(a, b, Throwable::addSuppressed) - a ?: b - } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt index d9ae12396d5..dcb096161d3 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Sequence.kt @@ -10,14 +10,7 @@ import arrow.core.Either.Right import arrow.core.raise.RaiseAccumulate import arrow.core.raise.either import arrow.core.raise.mapOrAccumulate -import arrow.core.raise.option -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation -import arrow.typeclasses.combine import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName /** Adds [kotlin.sequences.zip] support for 3 parameters */ public fun Sequence.zip( @@ -343,27 +336,7 @@ private fun alignRec( } } -@Deprecated("use fold instead", ReplaceWith("fold(MA)", "arrow.core.fold")) -public fun Sequence.combineAll(MA: Monoid): A = - fold(MA) - -@Deprecated( - "This function is actually terminal. Use crosswalk(f:A -> List) instead.", - ReplaceWith("this.crosswalk{a -> f(a).toList()}") -) -public fun Sequence.crosswalk(f: (A) -> Sequence): Sequence> = - fold(emptySequence()) { bs, a -> - f(a).align(bs) { ior -> - ior.fold( - { sequenceOf(it) }, - ::identity, - { l, r -> sequenceOf(l) + r } - ) - } - } - @OverloadResolutionByLambdaReturnType -@JvmName("crosswalkT") public fun Sequence.crosswalk(f: (A) -> Iterable): List> = fold(emptyList()) { bs, a -> f(a).align(bs) { ior -> @@ -375,81 +348,18 @@ public fun Sequence.crosswalk(f: (A) -> Iterable): List> = } } - -@Deprecated( - "This function is actually terminal. Use crosswalk(f:A -> List) instead.", - ReplaceWith("this.crosswalk{a -> f(a).toList()}") -) -public fun Sequence.crosswalkMap(f: (A) -> Map): Map> = - fold(emptyMap()) { bs, a -> - f(a).align(bs) { (_, ior) -> - ior.fold( - { sequenceOf(it) }, - ::identity, - { l, r -> sequenceOf(l) + r } - ) - } - } - -public fun Sequence.crosswalkNull(f: (A) -> B?): Sequence? = - fold?>(emptySequence()) { bs, a -> +public fun Sequence.crosswalkNull(f: (A) -> B?): List? = + fold?>(emptyList()) { bs, a -> Ior.fromNullables(f(a), bs)?.fold( - { sequenceOf(it) }, + { listOf(it) }, ::identity, - { l, r -> sequenceOf(l) + r } + { l, r -> listOf(l) + r } ) } public fun Sequence>.flatten(): Sequence = flatMap(::identity) -@Deprecated( - "$MonoidDeprecation\n$NicheAPI", - ReplaceWith("this.fold(initial){ acc, a -> acc + a }", "arrow.core.sequence") -) -public fun Sequence.fold(MA: Monoid): A = MA.run { - this@fold.fold(empty()) { acc, a -> - acc.combine(a) - } -} - -@Deprecated( - "$MonoidDeprecation\n$NicheAPI", - ReplaceWith("this.fold(initial){ acc, a -> acc + f(a) }") -) -public fun Sequence.foldMap(MB: Monoid, f: (A) -> B): B = MB.run { - this@foldMap.fold(empty()) { acc, a -> - acc.combine(f(a)) - } -} - -/** - * Logical conditional. The equivalent of Prolog's soft-cut. - * If its first argument succeeds at all, then the results will be - * fed into the success branch. Otherwise, the failure branch is taken. - * - * ```kotlin - * import arrow.core.ifThen - * - * fun main(args: Array) { - * //sampleStart - * val result = - * sequenceOf(1,2,3).ifThen(sequenceOf("empty")) { i -> - * sequenceOf("$i, ${i + 1}") - * } - * //sampleEnd - * println(result.toList()) - * } - * ``` - * - */ -@Deprecated( - "Use flatMap and ifEmpty instead.\n$NicheAPI", - ReplaceWith("flatMap(ffa).ifEmpty { fb }") -) -public fun Sequence.ifThen(fb: Sequence, ffa: (A) -> Sequence): Sequence = - flatMap(ffa).ifEmpty { fb } - /** * Interleaves the elements of `this` [Sequence] with those of [other] [Sequence]. * Elements of `this` and [other] are taken in turn, and the resulting list is the concatenation of the interleaved elements. @@ -465,7 +375,7 @@ public fun Sequence.ifThen(fb: Sequence, ffa: (A) -> Sequence): * tags.interleave(numbers).toList() shouldBe listOf("#", 0, "#", 1, "#", 2, "#", "#") * } * ``` - * + * * */ public fun Sequence.interleave(other: Sequence): Sequence = @@ -501,7 +411,7 @@ public fun Sequence.interleave(other: Sequence): Sequence = * println("both = $both") * } * ``` - * + * */ public fun Sequence.leftPadZip(other: Sequence, fab: (A?, B) -> C): Sequence = padZip(other) { a: A?, b: B? -> b?.let { fab(a, it) } }.mapNotNull(::identity) @@ -526,7 +436,7 @@ public fun Sequence.leftPadZip(other: Sequence, fab: (A?, B) -> * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Sequence.leftPadZip(other: Sequence): Sequence> = this.leftPadZip(other) { a, b -> a to b } @@ -557,7 +467,7 @@ public fun Sequence.once(): Sequence = * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Sequence.padZip(other: Sequence): Sequence> = alignRec( @@ -586,7 +496,7 @@ public fun Sequence.padZip(other: Sequence): Sequence> * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Sequence.padZip(other: Sequence, fa: (A?, B?) -> C): Sequence = alignRec( @@ -597,18 +507,6 @@ public fun Sequence.padZip(other: Sequence, fa: (A?, B?) -> C): { a, b -> fa(a, b) } ) -@Deprecated( - "$SemigroupDeprecation\n$NicheAPI", - ReplaceWith("Sequence> { List>(n) { this }.iterator() }") -) -public fun Sequence.replicate(n: Int): Sequence> = - Sequence { List(n) { this@replicate }.iterator() } - -@Deprecated(NicheAPI) -public fun Sequence.replicate(n: Int, MA: Monoid): Sequence = - if (n <= 0) sequenceOf(MA.empty()) - else this@replicate.zip(replicate(n - 1, MA)) { a, xs -> MA.run { a + xs } } - /** * Returns a [Sequence] containing the result of applying some transformation `(A, B?) -> C` * on a zip, excluding all cases where the left value is null. @@ -629,7 +527,7 @@ public fun Sequence.replicate(n: Int, MA: Monoid): Sequence = * println("both = $both") * } * ``` - * + * */ public fun Sequence.rightPadZip(other: Sequence, fa: (A, B?) -> C): Sequence = other.leftPadZip(this) { a, b -> fa(b, a) } @@ -654,7 +552,7 @@ public fun Sequence.rightPadZip(other: Sequence, fa: (A, B?) -> * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Sequence.rightPadZip(other: Sequence): Sequence> = this.rightPadZip(other) { a, b -> a to b } @@ -668,15 +566,6 @@ public fun Sequence.salign( ): Sequence = align(other) { it.fold(::identity, ::identity, combine) } -/** - * aligns two structures and combine them with the given [Semigroup.combine] - */ -@Deprecated(SemigroupDeprecation, ReplaceWith("salign(other, {a, b -> a + b})", "arrow.typeclasses.combine")) -public fun Sequence.salign( - SG: Semigroup, - other: Sequence -): Sequence = - salign(other, SG::combine) /** * Separate the inner [Either] values into the [Either.Left] and [Either.Right]. @@ -684,82 +573,14 @@ public fun Sequence.salign( * @receiver Iterable of [Either] * @return a tuple containing Sequence with [Either.Left] and another Sequence with its [Either.Right] values. */ -public fun Sequence>.separateEither(): Pair, Sequence> = - fold(sequenceOf() to sequenceOf()) { (lefts, rights), either -> +public fun Sequence>.separateEither(): Pair, List> = + fold(listOf() to listOf()) { (lefts, rights), either -> when (either) { is Left -> lefts + either.value to rights is Right -> lefts to rights + either.value } } -/** - * Separate the inner [Validated] values into the [Validated.Invalid] and [Validated.Valid]. - * - * @receiver Iterable of Validated - * @return a tuple containing Sequence with [Validated.Invalid] and another Sequence with its [Validated.Valid] values. - */ -@Deprecated( - "${ValidatedDeprMsg}SemigroupDeprecation\n$NicheAPI", - ReplaceWith("separateEither()") -) -public fun Sequence>.separateValidated(): Pair, Sequence> = - fold(sequenceOf() to sequenceOf()) { (invalids, valids), validated -> - when (validated) { - is Valid -> invalids to valids + validated.value - is Invalid -> invalids + validated.value to valids - } - } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the DSL.\n$NicheAPI", - ReplaceWith("let>, Either>> { s -> either> { s.map, A> { it.bind() }.toList() } }", "arrow.core.raise.either") -) -public fun Sequence>.sequence(): Either> = - let { s -> either { s.map { it.bind() }.toList() } } - -@Deprecated( - "sequenceEither is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence().map { it.asSequence() }", "arrow.core.sequence") -) -public fun Sequence>.sequenceEither(): Either> = - sequence().map { it.asSequence() } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the Option DSL.\n$NicheAPI", - ReplaceWith("let>, Option>> { s -> option> { s.map, A> { it.bind() }.toList() } }", "arrow.core.raise.option") -) -public fun Sequence>.sequence(): Option> = - let { s -> option { s.map { it.bind() }.toList() } } - -@Deprecated( - "sequenceOption is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence().map { it.asSequence() }", "arrow.core.sequence") -) -public fun Sequence>.sequenceOption(): Option> = - sequence().map { it.asSequence() } - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate, Validated, A>({e1, e2 -> e1 + e1}) { it.bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public fun Sequence>.sequence(semigroup: Semigroup): Validated> = - mapOrAccumulate(semigroup::combine) { it.bind() }.toValidated() - -@Deprecated( - "sequenceValidated is being renamed to sequence to simplify the Arrow API", - ReplaceWith("this.mapOrAccumulate, Validated, A>({e1, e2 -> e1 + e1}) { it.bind() }.toValidated().map { it.asSequence() }", "arrow.core.mapOrAccumulate") -) -public fun Sequence>.sequenceValidated(semigroup: Semigroup): Validated> = - sequence(semigroup).map { it.asSequence() } - -@Deprecated("some is being deprecated in favor of map", ReplaceWith("map { generateSequence { this } }")) -public fun Sequence.some(): Sequence> = - if (none()) emptySequence() - else map { generateSequence { it } } - /** * attempt to split the computation, giving access to the first result. * @@ -775,7 +596,7 @@ public fun Sequence.some(): Sequence> = * emptySequence().split() shouldBe null * } * ``` - * + * * */ public fun Sequence.split(): Pair, A>? = @@ -787,53 +608,6 @@ public fun Sequence.split(): Pair, A>? = public fun Sequence.tail(): Sequence = drop(1) -@Deprecated( - "Traverse for Sequence is being deprecated in favor of Either DSL.\n$NicheAPI", - ReplaceWith("let, Either>> { s -> either> { s.map { f(it).bind() }.toList() } }", "arrow.core.raise.either") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public fun Sequence.traverse(f: (A) -> Either): Either> = - let { s -> either { s.map { f(it).bind() }.toList() } } - -@Deprecated( - "traverseEither is being renamed to traverse to simplify the Arrow API", - ReplaceWith("traverse(f).map { it.asSequence() }", "arrow.core.traverse") -) -public fun Sequence.traverseEither(f: (A) -> Either): Either> = - traverse(f).map { it.asSequence() } - -@Deprecated( - "Traverse for Sequence is being deprecated in favor of Either DSL.\n$NicheAPI", - ReplaceWith("let, Option>> { s -> option> { s.map { f(it).bind() }.toList() } }", "arrow.core.raise.option") -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public fun Sequence.traverse(f: (A) -> Option): Option> = - let { s -> option { s.map { f(it).bind() }.toList() } } - -@Deprecated( - "traverseOption is being renamed to traverse to simplify the Arrow API", - ReplaceWith("traverse(f).map { it.asSequence() }", "arrow.core.traverse") -) -public fun Sequence.traverseOption(f: (A) -> Option): Option> = - traverse(f).map { it.asSequence() } - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({e1, e2 -> e1 + e2}) { f(it).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public fun Sequence.traverse( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate(semigroup::combine) { f(it).bind() }.toValidated() - public fun Sequence.mapOrAccumulate( combine: (Error, Error) -> Error, @BuilderInference transform: RaiseAccumulate.(A) -> B @@ -847,19 +621,6 @@ public fun Sequence.mapOrAccumulate( mapOrAccumulate(this@mapOrAccumulate, transform) } -@Deprecated( - "traverseValidated is being renamed to traverse to simplify the Arrow API", - ReplaceWith( - "mapOrAccumulate{e1, e2 -> e1 + e2} { f(it).bind() }.toValidated().map { it.asSequence() }", - "`arrow.core.mapOrAccumulate`" - ) -) -public fun Sequence.traverseValidated( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - traverse(semigroup, f).map { it.asSequence() } - /** * splits an union into its component parts. * @@ -868,14 +629,14 @@ public fun Sequence.traverseValidated( * import arrow.core.leftIor * import arrow.core.unalign * - * fun main(args: Array) { + * fun main() { * //sampleStart * val result = sequenceOf(("A" to 1).bothIor(), ("B" to 2).bothIor(), "C".leftIor()).unalign() * //sampleEnd * println("(${result.first}, ${result.second})") * } * ``` - * + * */ public fun Sequence>.unalign(): Pair, Sequence> = fold(emptySequence() to emptySequence()) { (l, r), x -> @@ -893,55 +654,32 @@ public fun Sequence>.unalign(): Pair, Sequence> * import arrow.core.leftIor * import arrow.core.unalign * - * fun main(args: Array) { + * fun main() { * //sampleStart * val result = sequenceOf(1, 2, 3).unalign { it.leftIor() } * //sampleEnd * println("(${result.first.toList()}, ${result.second.toList()})") * } * ``` - * + * */ public fun Sequence.unalign(fa: (C) -> Ior): Pair, Sequence> = map(fa).unalign() -@Deprecated( - NicheAPI + "Prefer using flatMap + fold", - ReplaceWith( - "flatMap { either -> either.fold>({ emptySequence() }, { b -> sequenceOf(b) }) }" - ) -) -public fun Sequence>.uniteEither(): Sequence = - flatMap { either -> - either.fold({ emptySequence() }, { b -> sequenceOf(b) }) - } - -@Deprecated( - ValidatedDeprMsg, - ReplaceWith( - "flatMap { validated -> validated.toEither().fold>({ emptySequence() }, { b -> sequenceOf(b) })}", - "arrow.core.traverse" - ) -) -public fun Sequence>.uniteValidated(): Sequence = - flatMap { validated -> - validated.fold({ emptySequence() }, { b -> sequenceOf(b) }) - } - /** * Fair conjunction. Similarly to interleave * * ```kotlin * import arrow.core.unweave * - * fun main(args: Array) { + * fun main() { * //sampleStart * val result = sequenceOf(1,2,3).unweave { i -> sequenceOf("$i, ${i + 1}") } * //sampleEnd * println(result.toList()) * } * ``` - * + * */ public fun Sequence.unweave(ffa: (A) -> Sequence): Sequence = split()?.let { (fa, a) -> @@ -954,14 +692,14 @@ public fun Sequence.unweave(ffa: (A) -> Sequence): Sequence = * ```kotlin * import arrow.core.unzip * - * fun main(args: Array) { + * fun main() { * //sampleStart * val result = sequenceOf("A" to 1, "B" to 2).unzip() * //sampleEnd * println("(${result.first}, ${result.second})") * } * ``` - * + * */ public fun Sequence>.unzip(): Pair, Sequence> = fold(emptySequence() to emptySequence()) { (l, r), x -> @@ -974,7 +712,7 @@ public fun Sequence>.unzip(): Pair, Sequence> = * ```kotlin * import arrow.core.unzip * - * fun main(args: Array) { + * fun main() { * //sampleStart * val result = * sequenceOf("A:1", "B:2", "C:3").unzip { e -> @@ -986,35 +724,11 @@ public fun Sequence>.unzip(): Pair, Sequence> = * println("(${result.first}, ${result.second})") * } * ``` - * + * */ public fun Sequence.unzip(fc: (C) -> Pair): Pair, Sequence> = map(fc).unzip() -@Deprecated( - "void is being deprecated in favor of simple Iterable.map.\n$NicheAPI", - ReplaceWith("map { }") -) -public fun Sequence.void(): Sequence = - map { Unit } - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -/** - * Given [A] is a subtype of [B], re-type this value from Sequence to Sequence - * - * ```kotlin - * import arrow.core.widen - * - * fun main(args: Array) { - * val original: Sequence = sequenceOf("Hello World") - * val result: Sequence = original.widen() - * } - * ``` - * - */ -public fun Sequence.widen(): Sequence = - this - /** * Filters out all elements that are [None], * and unwraps the remaining elements [Some] values. @@ -1033,7 +747,7 @@ public fun Sequence.widen(): Sequence = * .toList() shouldBe listOf(0, 2, 4, 6, 8) * } * ``` - * + * * */ public fun Sequence>.filterOption(): Sequence = diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Tuple10.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Tuple10.kt deleted file mode 100644 index 5c81d2ab261..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Tuple10.kt +++ /dev/null @@ -1,57 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("TupleNKt") - -package arrow.core - -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName - -public data class Tuple10( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J -) { - - override fun toString(): String = - "($first, $second, $third, $fourth, $fifth, $sixth, $seventh, $eighth, $ninth, $tenth)" - - public companion object -} - -public operator fun , B : Comparable, C : Comparable, D : Comparable, E : Comparable, F : Comparable, G : Comparable, H : Comparable, I : Comparable, J : Comparable> -Tuple10.compareTo(other: Tuple10): Int { - val first = first.compareTo(other.first) - return if (first == 0) { - val second = second.compareTo(other.second) - if (second == 0) { - val third = third.compareTo(other.third) - if (third == 0) { - val fourth = fourth.compareTo(other.fourth) - if (fourth == 0) { - val fifth = fifth.compareTo(other.fifth) - if (fifth == 0) { - val sixth = sixth.compareTo(other.sixth) - if (sixth == 0) { - val seventh = seventh.compareTo(other.seventh) - if (seventh == 0) { - val eighth = eighth.compareTo(other.eighth) - if (eighth == 0) { - val ninth = ninth.compareTo(other.ninth) - if (ninth == 0) tenth.compareTo(other.tenth) - else ninth - } else eighth - } else seventh - } else sixth - } else fifth - } else fourth - } else third - } else second - } else first -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/TupleN.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/TupleN.kt index a75f0c357af..1fbff275366 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/TupleN.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/TupleN.kt @@ -6,274 +6,6 @@ package arrow.core import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName -public data class Tuple11( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, -) { - public companion object -} - -public data class Tuple12( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L -) { - public companion object -} - -public data class Tuple13( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M -) { - - public companion object -} - -public data class Tuple14( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N -) { - - public companion object -} - -public data class Tuple15( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O -) { - - public companion object -} - -public data class Tuple16( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P -) { - - public companion object -} - -public data class Tuple17( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q -) { - - public companion object -} - -public data class Tuple18( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q, - val eighteenth: R -) { - - public companion object -} - -public data class Tuple19( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q, - val eighteenth: R, - val nineteenth: S -) { - - public companion object -} - -public data class Tuple20( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q, - val eighteenth: R, - val nineteenth: S, - val twentieth: T -) { - - public companion object -} - -public data class Tuple21( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q, - val eighteenth: R, - val nineteenth: S, - val twentieth: T, - val twentyFirst: U -) { - public companion object -} - -public data class Tuple22( - val first: A, - val second: B, - val third: C, - val fourth: D, - val fifth: E, - val sixth: F, - val seventh: G, - val eighth: H, - val ninth: I, - val tenth: J, - val eleventh: K, - val twelfth: L, - val thirteenth: M, - val fourteenth: N, - val fifteenth: O, - val sixteenth: P, - val seventeenth: Q, - val eighteenth: R, - val nineteenth: S, - val twentieth: T, - val twentyFirst: U, - val twentySecond: V -) { - public companion object -} - -private const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 - public operator fun Pair.plus(c: C): Triple = Triple(this.first, this.second, c) public operator fun Triple.plus(d: D): Tuple4 = Tuple4(this.first, this.second, this.third, d) public operator fun Tuple4.plus(e: E): Tuple5 = Tuple5(this.first, this.second, this.third, this.fourth, e) @@ -281,19 +13,8 @@ public operator fun Tuple5.plus(f: F): Tuple6< public operator fun Tuple6.plus(g: G): Tuple7 = Tuple7(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, g) public operator fun Tuple7.plus(h: H): Tuple8 = Tuple8(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, h) public operator fun Tuple8.plus(i: I): Tuple9 = Tuple9(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, i) -public operator fun Tuple9.plus(j: J): Tuple10 = Tuple10(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, j) -public operator fun Tuple10.plus(k: K): Tuple11 = Tuple11(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, k) -public operator fun Tuple11.plus(l: L): Tuple12 = Tuple12(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, l) -public operator fun Tuple12.plus(m: M): Tuple13 = Tuple13(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, m) -public operator fun Tuple13.plus(n: N): Tuple14 = Tuple14(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, n) -public operator fun Tuple14.plus(o: O): Tuple15 = Tuple15(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, o) -public operator fun Tuple15.plus(p: P): Tuple16 = Tuple16(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, p) -public operator fun Tuple16.plus(q: Q): Tuple17 = Tuple17(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, q) -public operator fun Tuple17.plus(r: R): Tuple18 = Tuple18(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, this.seventeenth, r) -public operator fun Tuple18.plus(s: S): Tuple19 = Tuple19(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, this.seventeenth, this.eighteenth, s) -public operator fun Tuple19.plus(t: T): Tuple20 = Tuple20(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, this.seventeenth, this.eighteenth, this.nineteenth, t) -public operator fun Tuple20.plus(u: U): Tuple21 = Tuple21(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, this.seventeenth, this.eighteenth, this.nineteenth, this.twentieth, u) -public operator fun Tuple21.plus(v: V): Tuple22 = Tuple22(this.first, this.second, this.third, this.fourth, this.fifth, this.sixth, this.seventh, this.eighth, this.ninth, this.tenth, this.eleventh, this.twelfth, this.thirteenth, this.fourteenth, this.fifteenth, this.sixteenth, this.seventeenth, this.eighteenth, this.nineteenth, this.twentieth, this.twentyFirst, v) + +private const val INT_MAX_POWER_OF_TWO: Int = Int.MAX_VALUE / 2 + 1 internal fun mapCapacity(expectedSize: Int): Int = when { diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt deleted file mode 100644 index 3b32ddf28f0..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt +++ /dev/null @@ -1,1306 +0,0 @@ -package arrow.core - -import arrow.typeclasses.Monoid -import arrow.typeclasses.Semigroup -import arrow.core.Either.Left -import arrow.core.Either.Right -import arrow.typeclasses.MonoidDeprecation -import arrow.typeclasses.combine -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic - -@Deprecated( - ValidatedDeprMsg + "ValidatedNel is being replaced by EitherNel", - ReplaceWith("EitherNel", "arrow.core.EitherNel") -) -public typealias ValidatedNel = Validated, A> - -@Deprecated( - ValidatedDeprMsg + "Use Right to construct Either values instead", - ReplaceWith("Either.Right", "arrow.core.Either") -) -public typealias Valid = Validated.Valid - -@Deprecated( - ValidatedDeprMsg + "Use Left to construct Either values instead", - ReplaceWith("Either.Left", "arrow.core.Either") -) -public typealias Invalid = Validated.Invalid - -@Deprecated(ValidatedDeprMsg + "You can find more details about how to migrate on the Github release page, or the 1.2.0 release post.") -public sealed class Validated { - - public companion object { - - @Deprecated( - ValidatedDeprMsg + "Use leftNel instead to construct the equivalent Either value", - ReplaceWith("e.leftNel()", "arrow.core.leftNel") - ) - @JvmStatic - public fun invalidNel(e: E): ValidatedNel = Invalid(nonEmptyListOf(e)) - - @Deprecated( - ValidatedDeprMsg + "Use right instead to construct the equivalent Either value", - ReplaceWith("a.right()", "arrow.core.right") - ) - @JvmStatic - public fun validNel(a: A): ValidatedNel = Valid(a) - - /** - * Converts an `Either` to a `Validated`. - */ - @Deprecated(ValidatedDeprMsg) - @JvmStatic - public fun fromEither(e: Either): Validated = e.fold({ Invalid(it) }, { Valid(it) }) - - /** - * Converts an `Option` to a `Validated`, where the provided `ifNone` output value is returned as [Invalid] - * when the specified `Option` is `None`. - */ - @Deprecated( - DeprAndNicheMsg + "Prefer using toEither on Option instead", - ReplaceWith("o.toEither(ifNone).toValidated()") - ) - @JvmStatic - public inline fun fromOption(o: Option, ifNone: () -> E): Validated = - o.fold( - { Invalid(ifNone()) }, - { Valid(it) } - ) - - /** - * Converts a nullable `A?` to a `Validated`, where the provided `ifNull` output value is returned as [Invalid] - * when the specified value is null. - */ - @Deprecated( - DeprAndNicheMsg + "Prefer Kotlin nullable syntax, or ensureNotNull inside Either DSL", - ReplaceWith("value?.valid() ?: ifNull().invalid()") - ) - @JvmStatic - public inline fun fromNullable(value: A?, ifNull: () -> E): Validated = - value?.let(::Valid) ?: Invalid(ifNull()) - - @Deprecated( - ValidatedDeprMsg + "Use Either.catch instead", - ReplaceWith("Either.catch(f).toValidated()") - ) - @JvmStatic - @JvmName("tryCatch") - public inline fun catch(f: () -> A): Validated = - try { - f().valid() - } catch (e: Throwable) { - e.nonFatalOrThrow().invalid() - } - - @Deprecated( - DeprAndNicheMsg + "Use Either.catch and mapLeft instead", - ReplaceWith("Either.catch(f).mapLeft(recover).toValidated()") - ) - @JvmStatic - @JvmName("tryCatch") - public inline fun catch(recover: (Throwable) -> E, f: () -> A): Validated = - catch(f).mapLeft(recover) - - @Deprecated( - DeprAndNicheMsg + "Use Either.catch and toEitherNel instead", - ReplaceWith("Either.catch(f).toEitherNel().toValidated()") - ) - @JvmStatic - public inline fun catchNel(f: () -> A): ValidatedNel = - try { - f().validNel() - } catch (e: Throwable) { - e.nonFatalOrThrow().invalidNel() - } - - @Deprecated( - DeprAndNicheMsg + "Prefer creating explicit lambdas instead", - ReplaceWith("{ it.map(f) }") - ) - @JvmStatic - public inline fun lift(crossinline f: (A) -> B): (Validated) -> Validated = - { fa -> fa.map(f) } - - /** - * Lifts two functions to the Bifunctor type. - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val f = Validated.lift(String::toUpperCase, Int::inc) - * val res1 = f("test".invalid()) - * val res2 = f(1.valid()) - * //sampleEnd - * println("res1: $res1") - * println("res2: $res2") - * } - * ``` - * - */ - @Deprecated( - DeprAndNicheMsg + "Prefer creating explicit lambdas instead", - ReplaceWith("{ it.bimap(fl, fr) }") - ) - @JvmStatic - public inline fun lift( - crossinline fl: (A) -> C, - crossinline fr: (B) -> D - ): (Validated) -> Validated = - { fa -> fa.bimap(fl, fr) } - } - - /** - * Discards the [A] value inside [Validated] signaling this container may be pointing to a noop - * or an effect whose return value is deliberately ignored. The singleton value [Unit] serves as signal. - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * val result = - * //sampleStart - * "Hello World".valid().void() - * //sampleEnd - * println(result) - * } - * ``` - * - */ - @Deprecated( - DeprAndNicheMsg + "Use map on Either after refactoring instead", - ReplaceWith("toEither().map { }.toValidated()") - ) - public fun void(): Validated = - map { Unit } - - @Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ emptyList() }, { fa(it).map(::Valid) })", - "arrow.core.Valid" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Iterable): List> = - fold({ emptyList() }, { a -> fa(a).map { Valid(it) } }) - - @Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ it.invalid().right() }, { fa(it).map(::Valid) })", - "arrow.core.invalid", "arrow.core.right", "arrow.core.Valid" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Either): Either> = - when (this) { - is Valid -> fa(this.value).map { Valid(it) } - is Invalid -> this.right() - } - - @Deprecated("traverseEither is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseEither(fa: (A) -> Either): Either> = - traverse(fa) - - @Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ None }, { fa(it).map(::Valid) })", - "arrow.core.None", "arrow.core.Valid" - ) - ) - @OptIn(ExperimentalTypeInference::class) - @OverloadResolutionByLambdaReturnType - public inline fun traverse(fa: (A) -> Option): Option> = - when (this) { - is Valid -> fa(this.value).map { Valid(it) } - is Invalid -> None - } - - @Deprecated("traverseOption is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) - public inline fun traverseOption(fa: (A) -> Option): Option> = - traverse(fa) - - @Deprecated( - DeprAndNicheMsg + "Use orNull() and Kotlin nullable types", - ReplaceWith("orNull()?.let(fa)?.valid()", "arrow.core.valid") - ) - public inline fun traverseNullable(fa: (A) -> B?): Validated? = - when (this) { - is Valid -> fa(this.value)?.let { Valid(it) } - is Invalid -> null - } - - @Deprecated( - DeprAndNicheMsg + "Prefer when or fold instead", - ReplaceWith("fold({ fe(c, it) }, { fa(c, it) })") - ) - public inline fun bifoldLeft( - c: B, - fe: (B, E) -> B, - fa: (B, A) -> B - ): B = - fold({ fe(c, it) }, { fa(c, it) }) - - @Deprecated( - DeprAndNicheMsg + "Prefer when or fold instead", - ReplaceWith("fold(g, f)") - ) - public inline fun bifoldMap(MN: Monoid, g: (E) -> B, f: (A) -> B): B = - fold(g, f) - - @Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } })", - "arrow.core.Valid", "arrow.core.Invalid" - ) - ) - public inline fun bitraverse(fe: (E) -> Iterable, fa: (A) -> Iterable): List> = - fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } }) - - @Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } })", - "arrow.core.Valid", "arrow.core.Invalid" - ) - ) - public inline fun bitraverseEither( - fe: (E) -> Either, - fa: (A) -> Either - ): Either> = - fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } }) - - @Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ fe(it).map(::Invalid) }, { fa(it).map(::Valid) })", - "arrow.core.Valid", "arrow.core.Invalid" - ) - ) - public inline fun bitraverseOption( - fe: (E) -> Option, - fa: (A) -> Option - ): Option> = - fold({ fe(it).map(::Invalid) }, { fa(it).map(::Valid) }) - - @Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ fe(it)?.let(::Invalid) }, { fa(it)?.let(::Valid) })", - "arrow.core.Valid", "arrow.core.Invalid" - ) - ) - public inline fun bitraverseNullable( - fe: (E) -> B?, - fa: (A) -> C? - ): Validated? = - fold({ fe(it)?.let(::Invalid) }, { fa(it)?.let(::Valid) }) - - @Deprecated( - ValidatedDeprMsg + "Use fold on Either after refactoring instead", - ReplaceWith("toEither().fold({ invalidValue }, f)") - ) - public inline fun foldMap(MB: Monoid, f: (A) -> B): B = - fold({ MB.empty() }, f) - - override fun toString(): String = fold( - { "Validated.Invalid($it)" }, - { "Validated.Valid($it)" } - ) - - @Deprecated( - ValidatedDeprMsg + "Use Right to construct Either values instead", - ReplaceWith("Either.Right", "arrow.core.Either") - ) - public data class Valid(val value: A) : Validated() { - override fun toString(): String = "Validated.Valid($value)" - - public companion object { - @PublishedApi - internal val unit: Validated = - Validated.Valid(Unit) - } - } - - @Deprecated( - ValidatedDeprMsg + "Use Left to construct Either values instead", - ReplaceWith("Either.Left", "arrow.core.Either") - ) - public data class Invalid(val value: E) : Validated() { - override fun toString(): String = "Validated.Invalid($value)" - } - - @Deprecated( - ValidatedDeprMsg + "Use fold on Either after refactoring", - ReplaceWith("toEither().fold(fe, fa)") - ) - public inline fun fold(fe: (E) -> B, fa: (A) -> B): B = - when (this) { - is Valid -> fa(value) - is Invalid -> (fe(value)) - } - - @Deprecated( - ValidatedDeprMsg + "Use isRight on Either after refactoring", - ReplaceWith("toEither().isRight()") - ) - public val isValid: Boolean = - fold({ false }, { true }) - - @Deprecated( - ValidatedDeprMsg + "Use isLeft on Either after refactoring", - ReplaceWith("toEither().isLeft()") - ) - public val isInvalid: Boolean = - fold({ true }, { false }) - - /** - * Is this Valid and matching the given predicate - */ - @Deprecated( - ValidatedDeprMsg + "Use isRight on Either after refactoring", - ReplaceWith("toEither().isRight(predicate)") - ) - public inline fun exist(predicate: (A) -> Boolean): Boolean = - fold({ false }, predicate) - - @Deprecated( - DeprAndNicheMsg + "Use getOrNull and takeIf on Either after refactoring", - ReplaceWith("toEither().getOrNull()?.takeIf(predicate)") - ) - public inline fun findOrNull(predicate: (A) -> Boolean): A? = - when (this) { - is Valid -> if (predicate(this.value)) this.value else null - is Invalid -> null - } - - @Deprecated( - DeprAndNicheMsg + "Use fold on Either after refactoring", - ReplaceWith("toEither().fold({ true }, predicate)") - ) - public inline fun all(predicate: (A) -> Boolean): Boolean = - fold({ true }, predicate) - - @Deprecated( - ValidatedDeprMsg + "Use isRight on Either after refactoring", - ReplaceWith("toEither().isLeft()") - ) - public fun isEmpty(): Boolean = isInvalid - - @Deprecated( - ValidatedDeprMsg + "Use isRight on Either after refactoring", - ReplaceWith("toEither().isRight()") - ) - public fun isNotEmpty(): Boolean = isValid - - /** - * Converts the value to an Either - */ - @Deprecated(ValidatedDeprMsg + "Drop this call after refactoring") - public fun toEither(): Either = - fold(::Left, ::Right) - - /** - * Returns Valid values wrapped in Some, and None for Invalid values - */ - @Deprecated( - ValidatedDeprMsg + "Use getOrNone on Either after refactoring", - ReplaceWith("toEither().getOrNone()") - ) - public fun toOption(): Option = - fold({ None }, ::Some) - - /** - * Convert this value to a single element List if it is Valid, - * otherwise return an empty List - */ - @Deprecated( - DeprAndNicheMsg + "Use fold instead", - ReplaceWith("fold({ emptyList() }, ::listOf)") - ) - public fun toList(): List = - fold({ listOf() }, ::listOf) - - /** Lift the Invalid value into a NonEmptyList. */ - @Deprecated( - ValidatedDeprMsg + "Use toEitherNel directly instead", - ReplaceWith("toEither().toEitherNel().toValidated()") - ) - public fun toValidatedNel(): ValidatedNel = - fold({ invalidNel(it) }, ::Valid) - - /** - * Convert to an Either, apply a function, convert back. This is handy - * when you want to use the Monadic properties of the Either type. - */ - @Deprecated( - ValidatedDeprMsg + "Use Either directly instead", - ReplaceWith("toEither().let(f).toValidated()") - ) - public inline fun withEither(f: (Either) -> Either): Validated = - fromEither(f(toEither())) - - /** - * From [arrow.typeclasses.Bifunctor], maps both types of this Validated. - * - * Apply a function to an Invalid or Valid value, returning a new Invalid or Valid value respectively. - */ - @Deprecated( - ValidatedDeprMsg + "Use map and mapLeft on Either after refactoring", - ReplaceWith("toEither().mapLeft(fe).map(fa)") - ) - public inline fun bimap(fe: (E) -> EE, fa: (A) -> B): Validated = - fold({ Invalid(fe(it)) }, { Valid(fa(it)) }) - - /** - * Apply a function to a Valid value, returning a new Valid value - */ - @Deprecated( - ValidatedDeprMsg + "Use map on Either after refactoring", - ReplaceWith("toEither().map(f).toValidated()") - ) - public inline fun map(f: (A) -> B): Validated = - bimap(::identity, f) - - /** - * Apply a function to an Invalid value, returning a new Invalid value. - * Or, if the original valid was Valid, return it. - */ - @Deprecated( - ValidatedDeprMsg + "Use mapLeft on Either after refactoring", - ReplaceWith("toEither().mapLeft(f).toValidated()") - ) - public inline fun mapLeft(f: (E) -> EE): Validated = - bimap(f, ::identity) - - /** - * The given function is applied as a fire and forget effect - * if this is `Invalid`. - * When applied the result is ignored and the original - * Validated value is returned - * - * Example: - * ```kotlin - * import arrow.core.Validated - * - * fun main() { - * Validated.Valid(12).tapInvalid { println("flower") } // Result: Valid(12) - * Validated.Invalid(12).tapInvalid { println("flower") } // Result: prints "flower" and returns: Invalid(12) - * } - * ``` - * - */ - @Deprecated( - ValidatedDeprMsg + "Use onLeft on Either after refactoring", - ReplaceWith("toEither().onLeft(f).toValidated()") - ) - public inline fun tapInvalid(f: (E) -> Unit): Validated = - when (this) { - is Invalid -> { - f(this.value) - this - } - - is Valid -> this - } - - /** - * The given function is applied as a fire and forget effect - * if this is `Valid`. - * When applied the result is ignored and the original - * Validated value is returned - * - * Example: - * ```kotlin - * import arrow.core.Validated - * - * fun main() { - * Validated.Valid(12).tap { println("flower") } // Result: prints "flower" and returns: Valid(12) - * Validated.Invalid(12).tap { println("flower") } // Result: Invalid(12) - * } - * ``` - * - */ - @Deprecated( - ValidatedDeprMsg + "Use onRight on Either after refactoring", - ReplaceWith("toEither().onRight(f).toValidated()") - ) - public inline fun tap(f: (A) -> Unit): Validated = - when (this) { - is Invalid -> this - is Valid -> { - f(this.value) - this - } - } - - /** - * apply the given function to the value with the given B when - * valid, otherwise return the given B - */ - @Deprecated( - ValidatedDeprMsg + "Use fold on Either after refactoring", - ReplaceWith("toEither().fold({ b }) { f(b, it) }") - ) - public inline fun foldLeft(b: B, f: (B, A) -> B): B = - fold({ b }, { f(b, it) }) - - @Deprecated( - ValidatedDeprMsg + "Use swap on Either after refactoring", - ReplaceWith("toEither().swap()") - ) - public fun swap(): Validated = - fold(::Valid, ::Invalid) -} - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), fb.toEither(), ::Pair).toValidated()", - "arrow.core.Either" - ) -) -public fun Validated.zip(SE: Semigroup, fb: Validated): Validated> = - Either.zipOrAccumulate(SE::combine, toEither(), fb.toEither(), ::Pair).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - f: (A, B) -> Z -): Validated = - Either.zipOrAccumulate(SE::combine, toEither(), b.toEither(), f).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - f: (A, B, C) -> Z -): Validated = - Either.zipOrAccumulate(SE::combine, toEither(), b.toEither(), c.toEither(), f).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - f: (A, B, C, D) -> Z -): Validated = - Either.zipOrAccumulate(SE::combine, toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - f: (A, B, C, D, EE) -> Z -): Validated = - Either.zipOrAccumulate(SE::combine, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f) - .toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - ff: Validated, - f: (A, B, C, D, EE, FF) -> Z -): Validated = - Either.zipOrAccumulate( - SE::combine, - toEither(), - b.toEither(), - c.toEither(), - d.toEither(), - e.toEither(), - ff.toEither(), - f - ).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - ff: Validated, - g: Validated, - f: (A, B, C, D, EE, F, G) -> Z -): Validated = - Either.zipOrAccumulate( - SE::combine, - toEither(), - b.toEither(), - c.toEither(), - d.toEither(), - e.toEither(), - ff.toEither(), - g.toEither(), - f - ).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - ff: Validated, - g: Validated, - h: Validated, - f: (A, B, C, D, EE, F, G, H) -> Z -): Validated = - Either.zipOrAccumulate( - SE::combine, - toEither(), - b.toEither(), - c.toEither(), - d.toEither(), - e.toEither(), - ff.toEither(), - g.toEither(), - h.toEither(), - f - ).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - ff: Validated, - g: Validated, - h: Validated, - i: Validated, - f: (A, B, C, D, EE, F, G, H, I) -> Z -): Validated = - Either.zipOrAccumulate( - SE::combine, - toEither(), - b.toEither(), - c.toEither(), - d.toEither(), - e.toEither(), - ff.toEither(), - g.toEither(), - h.toEither(), - i.toEither(), - f - ).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate({ e1, e2 -> e1 + e2 }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), j.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun Validated.zip( - SE: Semigroup, - b: Validated, - c: Validated, - d: Validated, - e: Validated, - ff: Validated, - g: Validated, - h: Validated, - i: Validated, - j: Validated, - f: (A, B, C, D, EE, F, G, H, I, J) -> Z -): Validated = - Either.zipOrAccumulate( - SE::combine, - toEither(), - b.toEither(), - c.toEither(), - d.toEither(), - e.toEither(), - ff.toEither(), - g.toEither(), - h.toEither(), - i.toEither(), - j.toEither(), - f - ).toValidated() - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - f: (A, B) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - f: (A, B, C) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - f: (A, B, C, D) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - f: (A, B, C, D, EE) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - ff: ValidatedNel, - f: (A, B, C, D, EE, FF) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, ff, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - ff: ValidatedNel, - g: ValidatedNel, - f: (A, B, C, D, EE, F, G) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - ff: ValidatedNel, - g: ValidatedNel, - h: ValidatedNel, - f: (A, B, C, D, EE, F, G, H) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, h, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - ff: ValidatedNel, - g: ValidatedNel, - h: ValidatedNel, - i: ValidatedNel, - f: (A, B, C, D, EE, F, G, H, I) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, h, i, f) - -@Deprecated( - ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", - ReplaceWith( - "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), j.toEither(), f).toValidated()", - "arrow.core.Either" - ) -) -public inline fun ValidatedNel.zip( - b: ValidatedNel, - c: ValidatedNel, - d: ValidatedNel, - e: ValidatedNel, - ff: ValidatedNel, - g: ValidatedNel, - h: ValidatedNel, - i: ValidatedNel, - j: ValidatedNel, - f: (A, B, C, D, EE, F, G, H, I, J) -> Z -): ValidatedNel = - zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, h, i, j, f) - -/** - * Given [A] is a sub type of [B], re-type this value from Validated to Validated - * - * ```kotlin - * import arrow.core.* - * - * fun main(args: Array) { - * //sampleStart - * val string: Validated = "Hello".valid() - * val chars: Validated = - * string.widen() - * //sampleEnd - * println(chars) - * } - * ``` - * - */ -@Deprecated(ValidatedDeprMsg + DeprecatedWiden, ReplaceWith("this.toEither()")) -public fun Validated.widen(): Validated = - this - -@Deprecated(ValidatedDeprMsg + DeprecatedWiden, ReplaceWith("this.toEither()")) -public fun Validated.leftWiden(): Validated = - this - -@Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or map", - ReplaceWith( - "(0 until (n.coerceAtLeast(0))).mapOrAccumulate({ e1, e2 -> e1 + e2 }) { bind() }.toValidated()" - ) -) -public fun Validated.replicate(SE: Semigroup, n: Int): Validated> = - if (n <= 0) emptyList().valid() - else this.zip(SE, replicate(SE, n - 1)) { a, xs -> listOf(a) + xs } - -@Deprecated(DeprAndNicheMsg) -public fun Validated.replicate(SE: Semigroup, n: Int, MA: Monoid): Validated = - if (n <= 0) MA.empty().valid() - else this@replicate.zip(SE, replicate(SE, n - 1, MA)) { a, xs -> MA.run { a + xs } } - -@Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ it.map { Invalid(it) } }, { it.map { Valid(it) } })", - "arrow.core.Valid", "arrow.core.Invalid" - ) -) -public fun Validated, Iterable>.bisequence(): List> = - bitraverse(::identity, ::identity) - -@Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ it.map { Invalid(it) } }, { it.map { Valid(it) } })", - "arrow.core.Valid", "arrow.core.Invalid" - ) -) -public fun Validated, Either>.bisequenceEither(): Either> = - bitraverseEither(::identity, ::identity) - -@Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ it.map(::Invalid) }, { it.map(::Valid) })", - "arrow.core.Valid", "arrow.core.Invalid" - ) -) -public fun Validated, Option>.bisequenceOption(): Option> = - bitraverseOption(::identity, ::identity) - -@Deprecated( - DeprAndNicheMsg + "Prefer explicit fold instead", - ReplaceWith( - "fold({ it?.let(::Invalid) }, { it?.let(::Valid) })", - "arrow.core.Valid", "arrow.core.Invalid" - ) -) -public fun Validated.bisequenceNullable(): Validated? = - bitraverseNullable(::identity, ::identity) - -@Deprecated( - "$MonoidDeprecation\n$DeprAndNicheMsg\nUse fold on Either after refactoring", - ReplaceWith("fold({ invalidValue }, ::identity)") -) -public fun Validated.fold(MA: Monoid): A = - fold({ MA.empty() }, ::identity) - -@Deprecated( - "$MonoidDeprecation\n$DeprAndNicheMsg\nUse fold on Either after refactoring", - ReplaceWith("fold({ invalidValue }, ::identity)", "arrow.core.fold") -) -public fun Validated.combineAll(MA: Monoid): A = - fold(MA) - -@Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ emptyList() }, { it.map(::Valid) })", - "arrow.core.Valid" - ) -) -public fun Validated>.sequence(): List> = - traverse(::identity) - -@Deprecated( - "sequenceEither is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Validated>.sequenceEither(): Either> = - sequence() - -@Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ it.invalid().right() }, { it.map(::Valid) })", - "arrow.core.invalid", "arrow.core.right", "arrow.core.Valid" - ) -) -public fun Validated>.sequence(): Either> = - traverse(::identity) - -@Deprecated( - "sequenceOption is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Validated>.sequenceOption(): Option> = - sequence() - -@Deprecated( - DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", - ReplaceWith( - "fold({ None }, { it.map(::Valid) })", - "arrow.core.None", "arrow.core.Valid" - ) -) -public fun Validated>.sequence(): Option> = - traverse(::identity) - -@Deprecated( - "sequenceNullable is being renamed to sequence to simplify the Arrow API", - ReplaceWith("sequence()", "arrow.core.sequence") -) -public fun Validated.sequenceNullable(): Validated? = - sequence() - -@Deprecated( - DeprAndNicheMsg + "Use orNull() and Kotlin nullable types", - ReplaceWith("orNull()?.valid()", "arrow.core.valid") -) -public fun Validated.sequence(): Validated? = - traverseNullable(::identity) - -@Deprecated( - ValidatedDeprMsg + "Use compareTo on Either after refactoring", - ReplaceWith("toEither(). compareTo(other.toEither())") -) -public operator fun , A : Comparable> Validated.compareTo(other: Validated): Int = - fold( - { l1 -> other.fold({ l2 -> l1.compareTo(l2) }, { -1 }) }, - { r1 -> other.fold({ 1 }, { r2 -> r1.compareTo(r2) }) } - ) - -/** - * Return the Valid value, or the default if Invalid - */ -@Deprecated( - ValidatedDeprMsg + "Use getOrElse on Either after refactoring", - ReplaceWith("toEither().getOrElse { default() }") -) -public inline fun Validated.getOrElse(default: () -> A): A = - fold({ default() }, ::identity) - -/** - * Return the Valid value, or null if Invalid - */ -@Deprecated( - ValidatedDeprMsg + "Use getOrNull on Either after refactoring", - ReplaceWith("toEither().getOrNull()") -) -public fun Validated.orNull(): A? = - getOrElse { null } - -@Deprecated( - ValidatedDeprMsg + "Use getOrNone on Either after refactoring", - ReplaceWith("toEither().getOrNone()") -) -public fun Validated.orNone(): Option = - fold({ None }, { Some(it) }) - -/** - * Return the Valid value, or the result of f if Invalid - */ -@Deprecated( - ValidatedDeprMsg + "Use getOrElse on Either after refactoring", - ReplaceWith("toEither().getOrElse(f)") -) -public inline fun Validated.valueOr(f: (E) -> A): A = - fold({ f(it) }, ::identity) - -/** - * If `this` is valid return `this`, otherwise if `that` is valid return `that`, otherwise combine the failures. - * This is similar to [orElse] except that here failures are accumulated. - */ -@Deprecated( - DeprAndNicheMsg + "Use recover on Either after refactoring", - ReplaceWith( - "toEither().recover { e -> that().mapLeft { ee -> e + ee }.bind() }.toValidated()", - "arrow.core.recover" - ) -) -public inline fun Validated.findValid(SE: Semigroup, that: () -> Validated): Validated = - toEither().recover { e -> that().mapLeft { ee -> SE.combine(e, ee) }.bind() }.toValidated() - -/** - * Apply a function to a Valid value, returning a new Validation that may be valid or invalid - * - * Example: - * ```kotlin - * import arrow.core.Validated - * import arrow.core.andThen - * - * fun main() { - * Validated.Valid(5).andThen { Validated.Valid(10) } // Result: Valid(10) - * Validated.Valid(5).andThen { Validated.Invalid(10) } // Result: Invalid(10) - * Validated.Invalid(5).andThen { Validated.Valid(10) } // Result: Invalid(5) - * } - * ``` - * - */ -@Deprecated( - ValidatedDeprMsg + "Use Either DSL or flatMap instead after refactoring.", - ReplaceWith("toEither().flatMap { f(it).toEither() }.toValidated()") -) -public inline fun Validated.andThen(f: (A) -> Validated): Validated = - when (this) { - is Validated.Valid -> f(value) - is Validated.Invalid -> this - } - -/** - * Return this if it is Valid, or else fall back to the given default. - * The functionality is similar to that of [findValid] except for failure accumulation, - * where here only the error on the right is preserved and the error on the left is ignored. - */ -@Deprecated( - ValidatedDeprMsg + "Use recover on Either instead after refactoring.", - ReplaceWith("toEither().recover { default().bind() }.toValidated()") -) -public inline fun Validated.orElse(default: () -> Validated): Validated = - fold( - { default() }, - { Valid(it) } - ) - -@Deprecated( - ValidatedDeprMsg + "Use recover on Either instead after refactoring.", - ReplaceWith("toEither().recover { e -> f(e).bind() }.toValidated()") -) -public inline fun Validated.handleErrorWith(f: (E) -> Validated): Validated = - when (this) { - is Validated.Valid -> this - is Validated.Invalid -> f(this.value) - } - -@Deprecated( - ValidatedDeprMsg + "Use recover on Either instead after refactoring.", - ReplaceWith("toEither().recover { e -> f(e) }.toValidated()") -) -public inline fun Validated.handleError(f: (E) -> A): Validated = - when (this) { - is Validated.Valid -> this - is Validated.Invalid -> Valid(f(this.value)) - } - -@Deprecated( - ValidatedDeprMsg + "Use fold on Either instead after refactoring.", - ReplaceWith("fold(fe, fa).valid()") -) -public inline fun Validated.redeem(fe: (E) -> B, fa: (A) -> B): Validated = - when (this) { - is Validated.Valid -> map(fa) - is Validated.Invalid -> Valid(fe(this.value)) - } - -@Deprecated( - ValidatedDeprMsg + "Validated is deprecated in favor of Either", - ReplaceWith("toEither().valid()") -) -public fun Validated.attempt(): Validated> = - map { Right(it) }.handleError { Left(it) } - -@Deprecated( - ValidatedDeprMsg + "Use merge() on Either instead after refactoring.", - ReplaceWith("toEither().merge()") -) -public inline fun Validated.merge(): A = - fold(::identity, ::identity) - -@Deprecated( - ValidatedDeprMsg + "Use Either.zipOrAccumulate instead", - ReplaceWith("Either.zipOrAccumulate({e1, e2 -> e1 + e2}, this.toEither(), y.toEither(), {a1, a2 -> a1 + a2} ).toValidated()") -) -public fun Validated.combine( - SE: Semigroup, - SA: Semigroup, - y: Validated -): Validated = - Either.zipOrAccumulate(SE::combine, toEither(), y.toEither(), SA::combine).toValidated() - -@Deprecated( - DeprAndNicheMsg, - ReplaceWith( - "toEither().recover { e -> y.toEither().recover { ee -> raise { e + ee }} }.bind() }.toValidated()", - "arrow.core.recover" - ) -) -public fun Validated.combineK(SE: Semigroup, y: Validated): Validated = - toEither().recover { e -> y.toEither().recover { ee -> raise(SE.combine(e, ee)) }.bind() }.toValidated() - -/** - * Converts the value to an Ior - */ -@Deprecated( - ValidatedDeprMsg + "Use toIor on Either after refactoring Validated to Either", - ReplaceWith("toEither().toIor()") -) -public fun Validated.toIor(): Ior = - fold({ Ior.Left(it) }, { Ior.Right(it) }) - -@Deprecated( - ValidatedDeprMsg + "Use right instead to construct the equivalent Either value", - ReplaceWith("this.right()", "arrow.core.right") -) -public inline fun A.valid(): Validated = - Valid(this) - -@Deprecated( - ValidatedDeprMsg + "Use left instead to construct the equivalent Either value", - ReplaceWith("this.left()", "arrow.core.left") -) -public inline fun E.invalid(): Validated = - Invalid(this) - -@Deprecated( - ValidatedDeprMsg + "Use right instead to construct the equivalent Either value", - ReplaceWith("this.right()", "arrow.core.right") -) -public inline fun A.validNel(): ValidatedNel = - Validated.validNel(this) - -@Deprecated( - ValidatedDeprMsg + "Use leftNel instead to construct the equivalent Either value", - ReplaceWith("this.leftNel()", "arrow.core.leftNel") -) -public inline fun E.invalidNel(): ValidatedNel = - Validated.invalidNel(this) - -@PublishedApi internal const val ValidatedDeprMsg: String = - "Validated functionality is being merged into Either.\n" - -@PublishedApi internal const val DeprAndNicheMsg: String = - "Validated functionality is being merged into Either, but this API is niche and will be removed in the future. If this method is crucial for you, please let us know on the Arrow Github. Thanks!\n https://github.com/arrow-kt/arrow/issues\n" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/either.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/either.kt deleted file mode 100644 index 50a3bef68bb..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/either.kt +++ /dev/null @@ -1,130 +0,0 @@ -package arrow.core.computations - -import arrow.continuations.Effect -import arrow.core.Either -import arrow.core.Either.Left -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.identity -import arrow.core.left -import arrow.core.right -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.coroutines.RestrictsSuspension - -@Deprecated( - "EitherEffect is replaced with arrow.core.raise.Raise", - ReplaceWith("Raise", "arrow.core.raise.Raise") -) -public fun interface EitherEffect : Effect> { - - public suspend fun Either.bind(): B = - when (this) { - is Either.Right -> value - is Left -> control().shift(this@bind) - } - - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither().bind()")) - public suspend fun Validated.bind(): B = - when (this) { - is Validated.Valid -> value - is Validated.Invalid -> control().shift(Left(value)) - } - - public suspend fun Result.bind(transform: (Throwable) -> E): B = - fold(::identity) { throwable -> - control().shift(transform(throwable).left()) - } - - /** - * Ensure check if the [value] is `true`, - * and if it is it allows the `either { }` binding to continue. - * In case it is `false`, then it short-circuits the binding and returns - * the provided value by [orLeft] inside an [Either.Left]. - * - * ```kotlin - * import arrow.core.computations.either - * - * //sampleStart - * suspend fun main() { - * either { - * ensure(true) { "" } - * println("ensure(true) passes") - * ensure(false) { "failed" } - * 1 - * } - * //sampleEnd - * .let(::println) - * } - * // println: "ensure(true) passes" - * // res: Either.Left("failed") - * ``` - * - */ - public suspend fun ensure(value: Boolean, orLeft: () -> E): Unit = - if (value) Unit else orLeft().left().bind() -} - -/** - * Ensures that [value] is not null. - * When the value is not null, then it will be returned as non null and the check value is now smart-checked to non-null. - * Otherwise, if the [value] is null then the [either] binding will short-circuit with [orLeft] inside of [Either.Left]. - * - * ```kotlin - * import arrow.core.computations.either - * import arrow.core.computations.ensureNotNull - * - * //sampleStart - * suspend fun main() { - * either { - * val x: Int? = 1 - * ensureNotNull(x) { "passes" } - * println(x) - * ensureNotNull(null) { "failed" } - * } - * //sampleEnd - * .let(::println) - * } - * // println: "1" - * // res: Either.Left("failed") - * ``` - * - */ -@Deprecated( - "Replaced by Raise, replace arrow.core.computations.ensureNotNull to arrow.core.raise.ensureNotNull", - ReplaceWith( - "ensureNotNull(value, orLeft)", - "import arrow.core.raise.ensureNotNull" - ) -) -@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. -public suspend fun EitherEffect.ensureNotNull(value: B?, orLeft: () -> E): B { - contract { - returns() implies (value != null) - } - - return value ?: orLeft().left().bind() -} - -@Deprecated( - "RestrictedEitherEffect is replaced with arrow.core.raise.Raise", - ReplaceWith("Raise", "arrow.core.raise.Raise") -) -@RestrictsSuspension -public fun interface RestrictedEitherEffect : EitherEffect - -@Deprecated(eitherDSLDeprecation, ReplaceWith("either", "arrow.core.raise.either")) -@Suppress("ClassName") -public object either { - @Deprecated(eitherDSLDeprecation, ReplaceWith("either(c)", "arrow.core.raise.either")) - public inline fun eager(crossinline c: suspend RestrictedEitherEffect.() -> A): Either = - Effect.restricted(eff = { RestrictedEitherEffect { it } }, f = c, just = { it.right() }) - - @Deprecated(eitherDSLDeprecation, ReplaceWith("either(c)", "arrow.core.raise.either")) - public suspend inline operator fun invoke(crossinline c: suspend EitherEffect.() -> A): Either = - Effect.suspended(eff = { EitherEffect { it } }, f = c, just = { it.right() }) -} - -@PublishedApi internal const val eitherDSLDeprecation: String = - "The either DSL has been moved to arrow.core.raise.either.\n" + - "Replace import arrow.core.computations.* with arrow.core.raise.*" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/eval.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/eval.kt deleted file mode 100644 index 4fa6bb4894d..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/eval.kt +++ /dev/null @@ -1,31 +0,0 @@ -package arrow.core.computations - -import arrow.continuations.Effect -import arrow.core.Eval -import kotlin.coroutines.RestrictsSuspension - -@Deprecated("EvalEffect is redundant. Use Eval#value directly instead") -public fun interface EvalEffect : Effect> { - @Deprecated( - "EvalEffect is redundant. Use Eval#value directly instead", - ReplaceWith("this.value()") - ) - public suspend fun Eval.bind(): B = - value() -} - -@Deprecated("RestrictedEvalEffect is redundant. Use Eval#value directly instead") -@RestrictsSuspension -public fun interface RestrictedEvalEffect : EvalEffect - -@Deprecated("EvalEffect is redundant. Use Eval#value directly instead") -@Suppress("ClassName") -public object eval { - @Deprecated("EvalEffect is redundant. Use Eval#value directly instead") - public inline fun eager(crossinline func: suspend RestrictedEvalEffect.() -> A): Eval = - Effect.restricted(eff = { RestrictedEvalEffect { it } }, f = func, just = Eval.Companion::now) - - @Deprecated("EvalEffect is redundant. Use Eval#value) directly instead") - public suspend inline operator fun invoke(crossinline func: suspend EvalEffect<*>.() -> A): Eval = - Effect.suspended(eff = { EvalEffect { it } }, f = func, just = Eval.Companion::now) -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/nullable.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/nullable.kt deleted file mode 100644 index 0932324e801..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/nullable.kt +++ /dev/null @@ -1,111 +0,0 @@ -package arrow.core.computations - -import arrow.continuations.Effect -import arrow.core.None -import arrow.core.Option -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.coroutines.RestrictsSuspension - -@Deprecated( - "NullableEffect is replaced with arrow.core.raise.NullableRaise", - ReplaceWith("NullableRaise", "arrow.core.raise.NullableRaise") -) -public fun interface NullableEffect : Effect { - public suspend fun B?.bind(): B = - this ?: control().shift(null) - - public suspend fun Option.bind(): B = - orNull().bind() - - /** - * Ensure check if the [value] is `true`, - * and if it is it allows the `nullable { }` binding to continue. - * In case it is `false`, then it short-circuits the binding and returns `null`. - * - * ```kotlin - * import arrow.core.computations.nullable - * - * //sampleStart - * suspend fun main() { - * nullable { - * ensure(true) - * println("ensure(true) passes") - * ensure(false) - * 1 - * } - * //sampleEnd - * .let(::println) - * } - * // println: "ensure(true) passes" - * // res: null - * ``` - * - */ - public suspend fun ensure(value: Boolean): Unit = - if (value) Unit else control().shift(null) -} - -/** - * Ensures that [value] is not null. - * When the value is not null, then it will be returned as non null and the check value is now smart-checked to non-null. - * Otherwise, if the [value] is null then the [option] binding will short-circuit with [None]. - * - * ```kotlin - * import arrow.core.computations.nullable - * import arrow.core.computations.ensureNotNull - * - * //sampleStart - * suspend fun main() { - * nullable { - * val x: Int? = 1 - * ensureNotNull(x) - * println(x) - * ensureNotNull(null) - * } - * //sampleEnd - * .let(::println) - * } - * // println: "1" - * // res: null - * ``` - * - */ -@Deprecated( - "Replaced by Raise, replace arrow.core.computations.ensureNotNull to arrow.core.raise.ensureNotNull", - ReplaceWith( - "ensureNotNull(value)", - "import arrow.core.raise.ensureNotNull" - ) -) -@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. -public suspend fun NullableEffect<*>.ensureNotNull(value: B?): B { - contract { - returns() implies (value != null) - } - - return value ?: control().shift(null) -} - -@Deprecated( - "RestrictedNullableEffect is replaced with arrow.core.raise.NullableRaise", - ReplaceWith("NullableRaise", "arrow.core.raise.NullableRaise") -) -@RestrictsSuspension -public fun interface RestrictedNullableEffect : NullableEffect - -@Deprecated(nullableDSLDeprecation, ReplaceWith("nullable", "arrow.core.raise.nullable")) -@Suppress("ClassName") -public object nullable { - @Deprecated(nullableDSLDeprecation, ReplaceWith("nullable(func)", "arrow.core.raise.nullable")) - public inline fun eager(crossinline func: suspend RestrictedNullableEffect.() -> A?): A? = - Effect.restricted(eff = { RestrictedNullableEffect { it } }, f = func, just = { it }) - - @Deprecated(nullableDSLDeprecation, ReplaceWith("nullable(func)", "arrow.core.raise.nullable")) - public suspend inline operator fun invoke(crossinline func: suspend NullableEffect<*>.() -> A?): A? = - Effect.suspended(eff = { NullableEffect { it } }, f = func, just = { it }) -} - -@PublishedApi internal const val nullableDSLDeprecation: String = - "The nullable DSL has been moved to arrow.core.raise.nullable.\n" + - "Replace import arrow.core.computations.* with arrow.core.raise.*" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/option.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/option.kt deleted file mode 100644 index f65ad18c8a1..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/option.kt +++ /dev/null @@ -1,116 +0,0 @@ -package arrow.core.computations - -import arrow.continuations.Effect -import arrow.core.None -import arrow.core.Option -import arrow.core.identity -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.coroutines.RestrictsSuspension - -@Deprecated( - "OptionEffect is replaced with arrow.core.raise.OptionRaise", - ReplaceWith("OptionRaise", "arrow.core.raise.OptionRaise") -) -public fun interface OptionEffect : Effect> { - public suspend fun Option.bind(): B = - fold({ control().shift(None) }, ::identity) - - /** - * Ensure check if the [value] is `true`, - * and if it is it allows the `option { }` binding to continue. - * In case it is `false`, then it short-circuits the binding and returns [None]. - * - * ```kotlin - * import arrow.core.computations.option - * - * //sampleStart - * suspend fun main() { - * option { - * ensure(true) - * println("ensure(true) passes") - * ensure(false) - * 1 - * } - * //sampleEnd - * .let(::println) - * } - * // println: "ensure(true) passes" - * // res: None - * ``` - * - */ - public suspend fun ensure(value: Boolean): Unit = - if (value) Unit else control().shift(None) -} - -/** - * Ensures that [value] is not null. - * When the value is not null, then it will be returned as non null and the check value is now smart-checked to non-null. - * Otherwise, if the [value] is null then the [option] binding will short-circuit with [None]. - * - * ```kotlin - * import arrow.core.computations.option - * import arrow.core.computations.ensureNotNull - * - * //sampleStart - * suspend fun main() { - * option { - * val x: Int? = 1 - * ensureNotNull(x) - * println(x) - * ensureNotNull(null) - * } - * //sampleEnd - * .let(::println) - * } - * // println: "1" - * // res: None - * ``` - * - */ -@Deprecated( - "Replaced by Raise, replace arrow.core.computations.ensureNotNull to arrow.core.raise.ensureNotNull", - ReplaceWith( - "ensureNotNull(value)", - "import arrow.core.raise.ensureNotNull" - ) -) -@OptIn(ExperimentalContracts::class) // Contracts not available on open functions, so made it top-level. -public suspend fun OptionEffect<*>.ensureNotNull(value: B?): B { - contract { - returns() implies (value != null) - } - - return value ?: (this as OptionEffect).control().shift(None) -} - -@Deprecated( - "RestrictedEitherEffect is replaced with arrow.core.raise.OptionRaise", - ReplaceWith("OptionRaise", "arrow.core.raise.OptionRaise") -)@RestrictsSuspension -public fun interface RestrictedOptionEffect : OptionEffect - -@Deprecated( - optionDSLDeprecation, - ReplaceWith("option", "arrow.core.raise.option") -) -@Suppress("ClassName") -public object option { - @Deprecated( - optionDSLDeprecation, - ReplaceWith("option(func)", "arrow.core.raise.option") - ) - public inline fun eager(crossinline func: suspend RestrictedOptionEffect.() -> A): Option = - Effect.restricted(eff = { RestrictedOptionEffect { it } }, f = func, just = { Option.fromNullable(it) }) - - @Deprecated( - optionDSLDeprecation, - ReplaceWith("option(func)", "arrow.core.raise.option") - ) public suspend inline operator fun invoke(crossinline func: suspend OptionEffect<*>.() -> A?): Option = - Effect.suspended(eff = { OptionEffect { it } }, f = func, just = { Option.fromNullable(it) }) -} - -@PublishedApi internal const val optionDSLDeprecation: String = - "The option DSL has been moved to arrow.core.raise.option.\n" + - "Replace import arrow.core.computations.* with arrow.core.raise.*" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/result.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/result.kt deleted file mode 100644 index 9e41353282d..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/computations/result.kt +++ /dev/null @@ -1,70 +0,0 @@ -package arrow.core.computations - -import arrow.core.Either -import arrow.core.Validated -import arrow.core.identity - -/** - * DSL Receiver Syntax for [result]. - */ -@Deprecated( - "ResultEffect is replaced with arrow.core.raise.ResultRaise", - ReplaceWith("ResultRaise", "arrow.core.raise.ResultRaise") -) -public object ResultEffect { - - @Deprecated("This object introduces dangerous behavior.") - public fun Result.bind(): A = - getOrThrow() - - @Deprecated("This object introduces dangerous behavior.") - public fun Either.bind(): A = - fold({ throw it }, ::identity) - - @Deprecated("This object introduces dangerous behavior.") - public fun Validated.bind(): A = - fold({ throw it }, ::identity) -} - -@Deprecated(resultDSLDeprecation, ReplaceWith("result", "arrow.core.raise.result")) -@Suppress("ClassName") -public object result { - - /** - * Provides a computation block for [Result] which is build on top of Kotlin's Result Std operations. - * - * ```kotlin - * import arrow.core.* - * import arrow.core.computations.result - * - * fun main() { - * result { // We can safely use assertion based operation inside blocks - * kotlin.require(false) { "Boom" } - * } // Result.Failure(IllegalArgumentException("Boom")) - * - * result { - * Result.failure(RuntimeException("Boom")) - * .recover { 1 } - * .bind() - * } // Result.Success(1) - * - * result { - * val x = Result.success(1).bind() - * val y = Result.success(x + 1).bind() - * x + y - * } // Result.Success(3) - * } - * ``` - * - */ - @Deprecated( - resultDSLDeprecation, - ReplaceWith("result { block() }", "arrow.core.raise.result") - ) - public inline operator fun invoke(block: ResultEffect.() -> A): Result = - kotlin.runCatching { block(ResultEffect) } -} - -@PublishedApi internal const val resultDSLDeprecation: String = - "The result DSL has been moved to arrow.core.raise.result.\n" + - "Replace import arrow.core.computations.* with arrow.core.raise.*" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/AtomicRef.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/AtomicRef.kt deleted file mode 100644 index fb7e6d61e6c..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/AtomicRef.kt +++ /dev/null @@ -1,52 +0,0 @@ -package arrow.core.continuations - -public expect class AtomicRef(initialValue: V) { - public fun get(): V - public fun set(value: V) - public fun getAndSet(value: V): V - - /** - * Compare current value with expected and set to new if they're the same. Note, 'compare' is checking - * the actual object id, not 'equals'. - */ - public fun compareAndSet(expected: V, new: V): Boolean -} - -/** - * Infinite loop that reads this atomic variable and performs the specified [action] on its value. - */ -public inline fun AtomicRef.loop(action: (V) -> Unit): Nothing { - while (true) { - action(get()) - } -} - -public inline fun AtomicRef.update(function: (V) -> V) { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return - } -} - -/** - * Updates variable atomically using the specified [function] of its value and returns its old value. - */ -public inline fun AtomicRef.getAndUpdate(function: (V) -> V): V { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return cur - } -} - -/** - * Updates variable atomically using the specified [function] of its value and returns its new value. - */ -public inline fun AtomicRef.updateAndGet(function: (V) -> V): V { - while (true) { - val cur = get() - val upd = function(cur) - if (compareAndSet(cur, upd)) return upd - } -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffect.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffect.kt deleted file mode 100644 index 341be788c5a..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffect.kt +++ /dev/null @@ -1,221 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.Ior -import arrow.core.Option -import arrow.core.Some -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.identity -import arrow.core.nonFatalOrThrow -import kotlin.coroutines.Continuation -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.RestrictsSuspension - -/** - * [RestrictsSuspension] version of [Effect]. This version runs eagerly, and can be used in - * non-suspending code. - * An [effect] computation interoperates with an [EagerEffect] via `bind`. - * @see Effect - */ -@Deprecated( - "Use the arrow.core.raise.Effect type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick." -) -public interface EagerEffect { - - /** - * Runs the non-suspending computation by creating a [Continuation] with an [EmptyCoroutineContext], - * and running the `fold` function over the computation. - * - * When the [EagerEffect] 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.core.continuations.eagerEffect - * import io.kotest.matchers.shouldBe - * - * fun main() { - * val shift = eagerEffect { - * shift("Hello, World!") - * }.fold({ str: String -> str }, { int -> int.toString() }) - * shift shouldBe "Hello, World!" - * - * val res = eagerEffect { - * 1000 - * }.fold({ str: String -> str.length }, { int -> int }) - * res shouldBe 1000 - * } - * ``` - * - */ - public fun fold(recover: (R) -> B, transform: (A) -> B): B - - /** - * Like `fold` but also allows folding over any unexpected [Throwable] that might have occurred. - * @see fold - */ - public fun fold( - error: (error: Throwable) -> B, - recover: (shifted: R) -> B, - transform: (value: A) -> B - ): B = - try { - fold(recover, transform) - } catch (e: Throwable) { - error(e.nonFatalOrThrow()) - } - - /** - * [fold] the [EagerEffect] into an [Ior]. Where the shifted value [R] is mapped to [Ior.Left], and - * result value [A] is mapped to [Ior.Right]. - */ - public fun toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } - - /** - * [fold] the [EagerEffect] into an [Either]. Where the shifted value [R] is mapped to [Either.Left], and - * result value [A] is mapped to [Either.Right]. - */ - public fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } - - /** - * [fold] the [EagerEffect] into an [Validated]. Where the shifted value [R] is mapped to - * [Validated.Invalid], and result value [A] is mapped to [Validated.Valid]. - */ - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither()")) - public fun toValidated(): Validated = - fold({ Validated.Invalid(it) }) { Validated.Valid(it) } - - /** - * [fold] the [EagerEffect] into an [A?]. Where the shifted value [R] is mapped to - * [null], and result value [A]. - */ - public fun orNull(): A? = fold({ null }, ::identity) - - /** - * [fold] the [EagerEffect] 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]. - */ - public fun toOption(orElse: (R) -> Option<@UnsafeVariance A>): Option = - fold(orElse, ::Some) - - @Deprecated(deprecateMonadAppFunctorOperators, ReplaceWith("flatMap { eagerEffect { f(it) } }")) - public fun map(f: (A) -> B): EagerEffect = flatMap { a -> eagerEffect { f(a) } } - - @Deprecated(deprecateMonadAppFunctorOperators) - public fun flatMap(f: (A) -> EagerEffect<@UnsafeVariance R, B>): EagerEffect = eagerEffect { - f(bind()).bind() - } - - public fun attempt(): EagerEffect> = eagerEffect { - kotlin.runCatching { bind() } - } - - public fun handleError(f: (R) -> @UnsafeVariance A): EagerEffect = eagerEffect { - fold(f, ::identity) - } - - public fun handleErrorWith(f: (R) -> EagerEffect): EagerEffect = - eagerEffect { - toEither().fold({ r -> f(r).bind() }, ::identity) - } - - public fun redeem(f: (R) -> B, g: (A) -> B): EagerEffect = eagerEffect { - fold(f, g) - } - - public fun redeemWith( - f: (R) -> EagerEffect, - g: (A) -> EagerEffect - ): EagerEffect = eagerEffect { fold(f, g).bind() } -} - -@PublishedApi -internal class Eager(val token: Token, val shifted: Any?, val recover: (Any?) -> Any?) : - ShiftCancellationException() { - override fun toString(): String = "ShiftCancellationException($message)" -} - -/** - * DSL for constructing `EagerEffect` values - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.Validated - * import arrow.core.continuations.eagerEffect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * fun main() { - * eagerEffect { - * 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 }) - * - * eagerEffect { - * 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") }) - * } - * ``` - * - */ -@Deprecated( - "Use the arrow.core.raise.effect DSL instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith("eagerEffect(f)", "arrow.core.raise.eagerEffect") -) -public fun eagerEffect(f: suspend EagerEffectScope.() -> A): EagerEffect = DefaultEagerEffect(f) - -private class DefaultEagerEffect(private val f: suspend EagerEffectScope.() -> A) : EagerEffect { - override fun fold(recover: (R) -> B, transform: (A) -> B): B { - val token = Token() - val isActive = AtomicRef(true) - val eagerEffectScope = - object : EagerEffectScope { - // 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: EagerEffectSpec - try/catch tests - if (isActive.get()) throw Eager(token, r, recover as (Any?) -> Any?) - else throw ShiftLeakedException() - } - - return try { - suspend { - val res = f(eagerEffectScope).also { isActive.set(false) } - transform(res) - }.startCoroutineUninterceptedOrReturn(Continuation(EmptyCoroutineContext) { result -> - result.getOrElse { throwable -> - if (throwable is Eager && token == throwable.token) { - throwable.recover(throwable.shifted) as B - } else throw throwable - } - }) as B - } catch (e: Eager) { - if (token == e.token) { - isActive.set(false) - e.recover(e.shifted) as B - } else throw e - } - } -} - -private const val deprecateMonadAppFunctorOperators: String = "Operators related to Functor, Applicative or Monad hierarchies are being deprecated in favor of bind" - -public fun EagerEffect.merge(): A = fold(::identity, ::identity) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffectScope.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffectScope.kt deleted file mode 100644 index f133bfbcf61..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EagerEffectScope.kt +++ /dev/null @@ -1,285 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.EmptyValue -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.identity -import arrow.core.raise.fold -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.coroutines.RestrictsSuspension -import kotlin.experimental.ExperimentalTypeInference -import kotlin.jvm.JvmInline - -/** Context of the [EagerEffect] DSL. */ -@Deprecated( - "Use the arrow.core.raise.Raise type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith("Raise", "arrow.core.raise.Raise") -) -@RestrictsSuspension -public interface EagerEffectScope { - - /** Short-circuit the [EagerEffect] computation with value [R]. - * - * ```kotlin - * import arrow.core.continuations.eagerEffect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * fun main() { - * eagerEffect { - * shift("SHIFT ME") - * }.fold({ it shouldBe "SHIFT ME" }, { fail("Computation never finishes") }) - * } - * ``` - * - */ - public suspend fun shift(r: R): B - - /** - * Runs the [EagerEffect] to finish, returning [B] or [shift] in case of [R]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.EagerEffect - * import arrow.core.continuations.eagerEffect - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * fun Either.toEagerEffect(): EagerEffect = eagerEffect { - * fold({ e -> shift(e) }, ::identity) - * } - * - * fun main() { - * val either = Either.Left("failed") - * eagerEffect { - * val x: Int = either.toEagerEffect().bind() - * x - * }.toEither() shouldBe either - * } - * ``` - * - */ - public suspend fun EagerEffect.bind(): B { - 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)) - } - - public suspend fun arrow.core.raise.EagerEffect.bind(): B = - fold({ shift(it) }, ::identity) - - /** - * Folds [Either] into [EagerEffect], by returning [B] or a shift with [R]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.eagerEffect - * import io.kotest.matchers.shouldBe - * - * fun main() { - * val either = Either.Right(9) - * eagerEffect { - * 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 [EagerEffect], by returning [B] or a shift with [R]. - * - * ```kotlin - * import arrow.core.Validated - * import arrow.core.continuations.eagerEffect - * import io.kotest.matchers.shouldBe - * - * fun main() { - * val validated = Validated.Valid(40) - * eagerEffect { - * val x: Int = validated.bind() - * x - * }.toValidated() shouldBe validated - * } - * ``` - * - */ - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither().bind()")) - public suspend fun Validated.bind(): B = - when (this) { - is Validated.Valid -> value - is Validated.Invalid -> shift(value) - } - - /** - * Folds [Result] into [EagerEffect], by returning [B] or a transforming [Throwable] into [R] and - * shifting the result. - * - * ```kotlin - * import arrow.core.continuations.eagerEffect - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * private val default = "failed" - * fun main() { - * val result = Result.success(1) - * eagerEffect { - * val x: Int = result.bind { _: Throwable -> default } - * x - * }.fold({ default }, ::identity) shouldBe result.getOrElse { default } - * } - * ``` - * - */ - public suspend fun Result.bind(transform: (Throwable) -> R): B = - fold(::identity) { throwable -> shift(transform(throwable)) } - - /** - * Folds [Option] into [EagerEffect], by returning [B] or a transforming [None] into [R] and shifting the - * result. - * - * ```kotlin - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.continuations.eagerEffect - * import arrow.core.getOrElse - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * private val default = "failed" - * fun main() { - * val option: Option = None - * eagerEffect { - * val x: Int = option.bind { default } - * x - * }.fold({ default }, ::identity) shouldBe option.getOrElse { default } - * } - * ``` - * - */ - public suspend fun Option.bind(shift: () -> R): B = - when (this) { - None -> shift(shift()) - is Some -> value - } - - /** - * ensure that condition is `true`, if it's `false` it will `shift` with the provided value [R]. - * Monadic version of [kotlin.require]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.eagerEffect - * import io.kotest.matchers.shouldBe - * - * fun main() { - * val condition = true - * val failure = "failed" - * val int = 4 - * eagerEffect { - * 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()) - - /** - * Encloses an action for which you want to catch any `shift`. - * [attempt] is used in combination with [catch]. - * - * ``` - * attempt { ... } catch { ... } - * ``` - * - * The [f] may `shift` into a different `EagerEffectScope`, giving - * the chance for a later [catch] to change the shifted value. - * This is useful to simulate re-throwing of exceptions. - */ - @OptIn(ExperimentalTypeInference::class) - public suspend fun attempt( - @BuilderInference - f: suspend EagerEffectScope.() -> A, - ): suspend EagerEffectScope.() -> A = f - - - /** - * When the [EagerEffect] has shifted with [R] it will [recover] - * the shifted value to [A], and when it ran the computation to - * completion it will return the value [A]. - * [catch] is used in combination with [attempt]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.Validated - * import arrow.core.continuations.eagerEffect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * fun main() { - * eagerEffect { - * val x = Either.Right(1).bind() - * val y = Validated.Valid(2).bind() - * val z = - * attempt { None.bind { "Option was empty" } } catch { 0 } - * x + y + z - * }.fold({ fail("Shift can never be the result") }, { it shouldBe 3 }) - * } - * ``` - * - */ - public infix fun (suspend EagerEffectScope.() -> A).catch( - recover: EagerEffectScope.(E) -> A, - ): A = eagerEffect(this).fold({ recover(it) }, ::identity) -} - -/** - * 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 - * import arrow.core.continuations.eagerEffect - * import arrow.core.continuations.ensureNotNull - * import arrow.core.left - * import arrow.core.right - * import io.kotest.matchers.shouldBe - * - * fun main() { - * val failure = "failed" - * val int: Int? = null - * eagerEffect { - * ensureNotNull(int) { failure } - * }.toEither() shouldBe (int?.right() ?: failure.left()) - * } - * ``` - * - */ -@Deprecated( - "Use the arrow.core.raise.Raise type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith("ensureNotNull(value, shift)", "arrow.core.raise.ensureNotNull") -) -@OptIn(ExperimentalContracts::class) -public suspend fun EagerEffectScope.ensureNotNull(value: B?, shift: () -> R): B { - contract { returns() implies (value != null) } - return value ?: shift(shift()) -} - diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/Effect.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/Effect.kt deleted file mode 100644 index 87e4524989e..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/Effect.kt +++ /dev/null @@ -1,938 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.Ior -import arrow.core.NonFatal -import arrow.core.Option -import arrow.core.Some -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.identity -import arrow.core.nonFatalOrThrow -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.cancellation.CancellationException -import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn -import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException - -/** - * [Effect] represents a function of `suspend () -> A`, that short-circuit with a value of [R] (and [Throwable]), - * or completes with a value of [A]. - * - * So [Effect] is defined by `suspend fun fold(f: suspend (R) -> B, g: suspend (A) -> B): B`, - * to map both values of [R] and [A] to a value of `B`. - * - * - - * [Writing a program with Effect](#writing-a-program-with-effect) - * [Handling errors](#handling-errors) - * [Structured Concurrency](#structured-concurrency) - * [Arrow Fx Coroutines](#arrow-fx-coroutines) - * [parZip](#parzip) - * [parTraverse](#partraverse) - * [raceN](#racen) - * [bracketCase / Resource](#bracketcase--resource) - * [KotlinX](#kotlinx) - * [withContext](#withcontext) - * [async](#async) - * [launch](#launch) - * [Leaking `shift`](#leaking-shift) - - * - * - * - * ## Writing a program with Effect - * - * 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]. - * - * - * ```kotlin - * object EmptyPath - * - * fun readFile(path: String): Effect = effect { - * if (path.isEmpty()) shift(EmptyPath) else Unit - * } - * ``` - * - * Here we see how we can define an `Effect` 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 [Effect] DSL offers utility functions like [kotlin.require] - * and [kotlin.requireNotNull]. They're named [EffectScope.ensure] and [ensureNotNull] to avoid conflicts with the `kotlin` namespace. - * So let's rewrite the function from above to use the DSL instead. - * - * ```kotlin - * fun readFile2(path: String?): Effect = effect { - * ensureNotNull(path) { EmptyPath } - * ensure(path.isNotEmpty()) { EmptyPath } - * } - * ``` - * - * - * 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. - * - * - * ```kotlin - * @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" - * } - * ``` - * - * We can finish our function, but we need to refactor the return type from `Unit` to `Content` and the error type from `EmptyPath` to `FileError`. - * - * ```kotlin - * fun readFile(path: String?): Effect = effect { - * 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)) - * } - * } - * ``` - * - * The `readFile` function defines a `suspend fun` that will return: - * - * - the `Content` of a given `path` - * - a `FileError` - * - An unexpected fatal error (`OutOfMemoryException`) - * - * Since these are the properties of our `Effect` function, we can turn it into a value. - * - * ```kotlin - * suspend fun main() { - * readFile("").toEither() shouldBe Either.Left(EmptyPath) - * readFile("gradle.properties").toIor() shouldBe Ior.Left(FileNotFound("gradle.properties")) - * readFile("README.MD").toOption { None } shouldBe None - * - * readFile("build.gradle.kts").fold({ _: FileError -> null }, { it }) - * .shouldBeInstanceOf() - * .body.shouldNotBeEmpty() - * } - * ``` - * - * - * The functions above are available out of the box, but it's easy to define your own extension functions in terms - * of `fold`. Implementing the `toEither()` operator is as simple as: - * - * - * ```kotlin - * suspend fun Effect.toEither(): Either = - * fold({ Either.Left(it) }) { Either.Right(it) } - * - * suspend fun Effect.toOption(): Option = - * fold(::identity) { Some(it) } - * ``` - * - * - * Adding your own syntax to `EffectScope` is not advised, yet, but will be easy once "Multiple Receivers" become available. - * - * ``` - * context(EffectScope) - * suspend fun Either.bind(): A = - * when (this) { - * is Either.Left -> shift(value) - * is Either.Right -> value - * } - * - * context(EffectScope) - * fun Option.bind(): A = - * fold({ shift(it) }, ::identity) - * ``` - * - * ## Handling errors - * - * Handling errors of type [R] is the same as handling errors for any other data type in Arrow. - * `Effect` offers `handleError`, `handleErrorWith`, `redeem`, `redeemWith` and `attempt`. - * - * As you can see in the examples below it is possible to resolve errors of [R] or `Throwable` in `Effect` in a generic manner. - * There is no need to run `Effect` into `Either` before you can access [R], - * you can simply call the same functions on `Effect` as you would on `Either` directly. - * - * - * ```kotlin - * val failed: Effect = - * effect { shift("failed") } - * - * val resolved: Effect = - * failed.handleError { it.length } - * - * val newError: Effect, Int> = - * failed.handleErrorWith { str -> - * effect { shift(str.reversed().toList()) } - * } - * - * val redeemed: Effect = - * failed.redeem({ str -> str.length }, ::identity) - * - * val captured: Effect> = - * effect { 1 }.attempt() - * - * suspend fun main() { - * 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)) - * } - * ``` - * - * - * Note: - * Handling errors can also be done with `try/catch` but this is **not recommended**, it uses `CancellationException` which is used to cancel `Coroutine`s and is advised not to capture in Kotlin. - * The `CancellationException` from `Effect` is `ShiftCancellationException`, this a public type, thus can be distinguished from any other `CancellationException` if necessary. - * - * ## Structured Concurrency - * - * `Effect` relies on `kotlin.cancellation.CancellationException` to `shift` error values of type [R] inside the `Continuation` since it effectively cancels/short-circuits it. - * For this reason `shift` adheres to the same rules as [`Structured Concurrency`](https://kotlinlang.org/docs/coroutines-basics.html#structured-concurrency) - * - * Let's overview below how `shift` behaves with the different concurrency builders from Arrow Fx & KotlinX Coroutines. - * In the examples below we're going to be using a utility to show how _sibling tasks_ get cancelled. - * The utility function show below called `awaitExitCase` will `never` finish suspending, and completes a `Deferred` with the `ExitCase`. - * `ExitCase` is a sealed class that can be a value of `Failure(Throwable)`, `Cancelled(CancellationException)`, or `Completed`. - * Since `awaitExitCase` suspends forever, it can only result in `Cancelled(CancellationException)`. - * - * - * ```kotlin - * suspend fun awaitExitCase(exit: CompletableDeferred): A = - * guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } - * - * ``` - * - * ### Arrow Fx Coroutines - * All operators in Arrow Fx Coroutines run in place, so they have no way of leaking `shift`. - * It's there always safe to compose `effect` with any Arrow Fx combinator. Let's see some small examples below. - * - * #### parZip - * - * ```kotlin - * suspend fun main() { - * val error = "Error" - * val exit = CompletableDeferred() - * effect { - * parZip({ awaitExitCase(exit) }, { shift(error) }) { a, b -> a + b } - * }.fold({ it shouldBe error }, { fail("Int can never be the result") }) - * exit.await().shouldBeTypeOf() - * } - * ``` - * - * - * #### parTraverse - * - * ```kotlin - * suspend fun main() { - * val error = "Error" - * val exits = (0..3).map { CompletableDeferred() } - * effect> { - * (0..4).parTraverse { index -> - * if (index == 4) shift(error) - * else awaitExitCase(exits[index]) - * } - * }.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() } - * } - * ``` - * - * - * `parTraverse` will launch 5 tasks, for every element in `1..5`. - * The last task to get scheduled will `shift` with "error", and it will cancel the other launched tasks before returning. - * - * #### raceN - * - * ```kotlin - * suspend fun main() { - * val error = "Error" - * val exit = CompletableDeferred() - * effect { - * 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") }) - * // It's possible not all parallel task got launched, and in those cases awaitCancellation never ran - * exit.getOrNull()?.shouldBeTypeOf() - * } - * ``` - * - * - * `raceN` races `n` suspend functions in parallel, and cancels all participating functions when a winner is found. - * We can consider the function that `shift`s the winner of the race, except with a shifted value instead of a successful one. - * So when a function in the race `shift`s, and thus short-circuiting the race, it will cancel all the participating functions. - * - * #### bracketCase / Resource - * - * ```kotlin - * suspend fun main() { - * val error = "Error" - * val exit = CompletableDeferred() - * effect { - * 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() - * } - * ``` - * - * - * - * ```kotlin - * suspend fun main() { - * val error = "Error" - * val exit = CompletableDeferred() - * - * fun bufferedReader(path: String): Resource = - * Resource.fromAutoCloseable { File(path).bufferedReader() } - * .releaseCase { _, exitCase -> exit.complete(exitCase) } - * - * effect { - * 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() - * } - * ``` - * - * - * ### KotlinX - * #### withContext - * It's always safe to call `shift` from `withContext` since it runs _in place_, so it has no way of leaking `shift`. - * When `shift` is called from within `withContext` it will cancel all `Job`s running inside the `CoroutineScope` of `withContext`. - * - * - * ```kotlin - * suspend fun main() { - * val exit = CompletableDeferred() - * effect { - * 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() - * } - * ``` - * - * - * #### async - * - * When calling `shift` from `async` you should **always** call `await`, otherwise `shift` can leak out of its scope. - * So it's safe to call `shift` from `async` as long as you **always** call `await` on the `Deferred` returned by `async`, - * but we advise using Arrow Fx `parZip`, `raceN`, `parTraverse`, etc instead. - * - * - * ```kotlin - * suspend fun main() { - * val errorA = "ErrorA" - * val errorB = "ErrorB" - * coroutineScope { - * effect { - * val fa = async { shift(errorA) } - * val fb = async { shift(errorB) } - * fa.await() + fb.await() - * }.fold( - * { error -> - * println(error) - * error shouldBeIn listOf(errorA, errorB) - * }, - * { fail("Int can never be the result") } - * ) - * } - * } - * ``` - * - * ```text - * ErrorA - * ``` - * - * The example here will always print `ErrorA`, but never `ErrorB`. This is because `fa` is awaited first, and when it `shifts` it will cancel `fb`. - * If instead we used `awaitAll`, then it would print `ErrorA` or `ErrorB` due to both `fa` and `fb` being awaited in parallel. - * - * #### launch - * - * It's **not allowed** to call `shift` from within `launch`. This is because `launch` creates a separate unrelated child Job/Continuation. - * Any calls to `shift` inside of `launch` will be ignored by `effect` and result in an exception being thrown inside `launch`. - * Because KotlinX Coroutines ignores `CancellationException`, and thus swallows the `shift` call. - * - * - * ```kotlin - * suspend fun main() { - * val errorA = "ErrorA" - * val errorB = "ErrorB" - * effect { - * coroutineScope { - * launch { shift(errorA) } - * launch { shift(errorB) } - * 45 - * } - * }.fold({ fail("Shift can never finish") }, ::println) - * } - * ``` - * - * ```text - * 45 - * ``` - * - * As you can see from the output, the `effect` block is still executed, but the `shift` calls inside `launch` are ignored. - * - * #### Leaking `shift` - * - * **IMPORTANT:** Capturing `shift` and leaking it outside of `effect { }` and invoking it outside its scope will yield unexpected results. - * - * Below an example of the capturing of `shift` inside a `suspend lambda`, and then invoking it outside its `effect { }` scope. - * - * - * - * ```kotlin - * effect Unit> { - * suspend { shift("error") } - * }.fold({ }, { leakedShift -> leakedShift.invoke() }) - * ``` - * - * - * When we invoke `leakedShift` outside of `effect { }` a special `ShiftLeakedException` is thrown to improve the debugging experience. - * The message clearly states that `shift` was leaked outside its scope, and the stacktrace will point to the exact location where `shift` was captured. - * In this case in line `9` of `example-effect-guide-13.kt`, which is stated in the second line of the stacktrace: `invokeSuspend(example-effect-guide-13.kt:9)`. - * - * ```text - * Exception in thread "main" arrow.core.continuations.ShiftLeakedException: - * shift or bind was called outside of its DSL scope, and the DSL Scoped operator was leaked - * This is kind of usage is incorrect, make sure all calls to shift or bind occur within the lifecycle of effect { }, either { } or similar builders. - * - * See: Effect KDoc for additional information. - * at arrow.core.continuations.FoldContinuation.shift(Effect.kt:770) - * at arrow.core.examples.exampleEffectGuide13.Example_effect_guide_13Kt$main$2$1.invokeSuspend(example-effect-guide-13.kt:9) - * at arrow.core.examples.exampleEffectGuide13.Example_effect_guide_13Kt$main$2$1.invoke(example-effect-guide-13.kt) - * ``` - * - * An example with KotlinX Coroutines launch. Which can _concurrently_ leak `shift` outside of its scope. - * In this case by _delaying_ the invocation of `shift` by `3.seconds`, - * we can see that the `ShiftLeakedException` is again thrown when `shift` is invoked. - * - * - * - * ```kotlin - * effect { - * launch { - * delay(3.seconds) - * shift("error") - * } - * 1 - * }.fold(::println, ::println) - * ``` - * ```text - * 1 - * Exception in thread "main" arrow.core.continuations.ShiftLeakedException: - * shift or bind was called outside of its DSL scope, and the DSL Scoped operator was leaked - * This is kind of usage is incorrect, make sure all calls to shift or bind occur within the lifecycle of effect { }, either { } or similar builders. - * - * See: Effect KDoc for additional information. - * at arrow.core.continuations.FoldContinuation.shift(Effect.kt:780) - * at arrow.core.examples.exampleEffectGuide14.Example_effect_guide_14Kt$main$1$1$1$1.invokeSuspend(example-effect-guide-14.kt:17) - * at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) <13 internal lines> - * at arrow.core.examples.exampleEffectGuide14.Example_effect_guide_14Kt.main(example-effect-guide-14.kt:11) - * at arrow.core.examples.exampleEffectGuide14.Example_effect_guide_14Kt.main(example-effect-guide-14.kt) - * ``` - * - */ -@Deprecated( - "Use the arrow.core.raise.Effect type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick." -) -public interface Effect { - /** - * Runs the suspending computation by creating a [Continuation], and running the `fold` function - * over the computation. - * - * When the [Effect] 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.core.continuations.effect - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * val shift = effect { - * shift("Hello, World!") - * }.fold({ str: String -> str }, { int -> int.toString() }) - * shift shouldBe "Hello, World!" - * - * val res = effect { - * 1000 - * }.fold({ str: String -> str.length }, { int -> int }) - * res shouldBe 1000 - * } - * ``` - * - */ - 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 - */ - 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()) - } - - /** - * [fold] the [Effect] into an [Either]. Where the shifted value [R] is mapped to [Either.Left], and - * result value [A] is mapped to [Either.Right]. - */ - public suspend fun toEither(): Either = fold({ Either.Left(it) }) { Either.Right(it) } - - /** - * [fold] the [Effect] into an [Ior]. Where the shifted value [R] is mapped to [Ior.Left], and - * result value [A] is mapped to [Ior.Right]. - */ - public suspend fun toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } - - /** - * [fold] the [Effect] into an [Validated]. Where the shifted value [R] is mapped to - * [Validated.Invalid], and result value [A] is mapped to [Validated.Valid]. - */ - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither()")) - public suspend fun toValidated(): Validated = - fold({ Validated.Invalid(it) }) { Validated.Valid(it) } - - /** - * [fold] the [Effect] 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]. - */ - public suspend fun toOption(orElse: suspend (R) -> Option<@UnsafeVariance A>): Option = fold(orElse, ::Some) - - /** - * [fold] the [Effect] into an [A?]. Where the shifted value [R] is mapped to - * [null], and result value [A]. - */ - public suspend fun orNull(): A? = fold({ null }, ::identity) - - /** Runs the [Effect] and captures any [NonFatal] exception into [Result]. */ - public fun attempt(): Effect> = effect { - try { - Result.success(bind()) - } catch (e: Throwable) { - Result.failure(e.nonFatalOrThrow()) - } - } - - public fun handleError(recover: suspend (R) -> @UnsafeVariance A): Effect = effect { - fold(recover, ::identity) - } - - public fun handleErrorWith(recover: suspend (R) -> Effect): Effect = effect { - fold({ recover(it).bind() }, ::identity) - } - - public fun redeem(recover: suspend (R) -> B, transform: suspend (A) -> B): Effect = - effect { - fold(recover, transform) - } - - @Deprecated( - "redeemWith is being removed in the Raise API", - ReplaceWith( - "effect { fold(recover, transform).bind() }", - "arrow.core.raise.effect" - ) - ) - public fun redeemWith( - recover: suspend (R) -> Effect, - transform: suspend (A) -> Effect, - ): Effect = effect { fold(recover, transform).bind() } -} - -/** - * **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 [Effect]. - */ -public sealed class ShiftCancellationException : CancellationExceptionNoTrace() - -public expect open class CancellationExceptionNoTrace() : CancellationException - -/** - * Holds `R` and `suspend (R) -> B`, the exception that wins the race, will get to execute - * `recover`. - */ -@PublishedApi -internal class Suspend(val token: Token, val shifted: Any?, val recover: suspend (Any?) -> Any?) : - ShiftCancellationException() { - override fun toString(): String = "ShiftCancellationException($message)" -} - -/** Class that represents a unique token by hash comparison **/ -@PublishedApi -internal open class Token { - override fun toString(): String = "Token(${hashCode().toString(16)})" -} - -/** - * 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. - */ -@PublishedApi -@Deprecated( - "This will become private in Arrow 2.0, and is not going to be visible from binary anymore", - level = DeprecationLevel.WARNING -) -internal class FoldContinuation( - override val context: CoroutineContext, - private val error: suspend (Throwable) -> B, - private val parent: Continuation, -) : Continuation, Token(), EffectScope { - - constructor(ignored: Token, context: CoroutineContext, parent: Continuation) : this(context, { throw it }, parent) - constructor( - ignored: Token, - context: CoroutineContext, - error: suspend (Throwable) -> B, - parent: Continuation, - ) : this(context, error, parent) - - lateinit var recover: suspend (R) -> Any? - - private val isActive: AtomicRef = AtomicRef(true) - - internal fun complete(): Boolean = isActive.getAndSet(false) - - // 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: EffectSpec - try/catch tests - if (isActive.get()) throw Suspend(this, r, recover as suspend (Any?) -> Any?) - else throw ShiftLeakedException() - - // In contrast to `createCoroutineUnintercepted this doesn't create a new ContinuationImpl - private fun (suspend () -> B).startCoroutineUnintercepted() { - try { - when (val res = startCoroutineUninterceptedOrReturn(parent)) { - COROUTINE_SUSPENDED -> Unit - else -> parent.resume(res as B) - } - // We need to wire all immediately throw exceptions to the parent Continuation - } catch (e: Throwable) { - parent.resumeWithException(e) - } - } - - override fun resumeWith(result: Result) { - result.fold(parent::resume) { throwable -> - when { - throwable is Suspend && this === throwable.token -> { - complete() - suspend { throwable.recover(throwable.shifted) as B }.startCoroutineUnintercepted() - } - - throwable is Suspend -> parent.resumeWith(result) - else -> { - complete() - suspend { error(throwable.nonFatalOrThrow()) }.startCoroutineUnintercepted() - } - } - } - } -} - -/** - * DSL for constructing Effect values - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.Validated - * import arrow.core.continuations.effect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * effect { - * 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 }) - * - * effect { - * 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") }) - * } - * ``` - * - */ -@Deprecated( - "Use the arrow.core.raise.effect DSL instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith( - "effect(f)", - "arrow.core.raise.effect" - ) -) -public fun effect(f: suspend EffectScope.() -> A): Effect = DefaultEffect(f) - -private class DefaultEffect(val f: suspend EffectScope.() -> A) : Effect { - - override suspend fun fold( - recover: suspend (shifted: R) -> B, - transform: suspend (value: A) -> B, - ): B = fold({ throw it }, recover, transform) - - // We create a `Token` for fold Continuation, so we can properly differentiate between nested folds - override suspend fun fold( - error: suspend (error: Throwable) -> B, - recover: suspend (shifted: R) -> B, - transform: suspend (value: A) -> B, - ): B = - suspendCoroutineUninterceptedOrReturn { cont -> - val shift = FoldContinuation(cont.context, error, cont) - shift.recover = recover - try { - val fold: suspend EffectScope.() -> B = { - val res = f(this).also { shift.complete() } - transform(res) - } - fold.startCoroutineUninterceptedOrReturn(shift, shift) - } catch (e: Suspend) { - if (shift === e.token) { - shift.complete() - val f: suspend () -> B = { e.recover(e.shifted) as B } - f.startCoroutineUninterceptedOrReturn(cont) - } else throw e - } catch (e: Throwable) { - shift.complete() - val f: suspend () -> B = { error(e.nonFatalOrThrow()) } - f.startCoroutineUninterceptedOrReturn(cont) - } - } -} - -public suspend fun Effect.merge(): A = fold(::identity, ::identity) - -public class ShiftLeakedException : IllegalStateException( - """ - - shift or bind was called outside of its DSL scope, and the DSL Scoped operator was leaked - This is kind of usage is incorrect, make sure all calls to shift or bind occur within the lifecycle of effect { }, either { } or similar builders. - - See: Effect KDoc for additional information. - """.trimIndent() -) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EffectScope.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EffectScope.kt deleted file mode 100644 index a735ea07b4e..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/EffectScope.kt +++ /dev/null @@ -1,326 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.EmptyValue -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.identity -import arrow.core.raise.fold -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.experimental.ExperimentalTypeInference - -/** Context of the [Effect] DSL. */ -@Deprecated( - "Use the arrow.core.raise.Raise type instead, which is more general and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith("Raise", "arrow.core.raise.Raise") -) -public interface EffectScope { - /** - * Short-circuit the [Effect] computation with value [R]. - * - * ```kotlin - * import arrow.core.continuations.effect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * effect { - * shift("SHIFT ME") - * }.fold({ it shouldBe "SHIFT ME" }, { fail("Computation never finishes") }) - * } - * ``` - * - */ - public suspend fun shift(r: R): B - - /** - * Runs the [Effect] to finish, returning [B] or [shift] in case of [R]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.Effect - * import arrow.core.continuations.effect - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * suspend fun Either.toEffect(): Effect = effect { - * fold({ e -> shift(e) }, ::identity) - * } - * - * suspend fun main() { - * val either = Either.Left("failed") - * effect { - * val x: Int = either.toEffect().bind() - * x - * }.toEither() shouldBe either - * } - * ``` - * - */ - public suspend fun Effect.bind(): B = fold(this@EffectScope::shift, ::identity) - - /** - * Runs the [EagerEffect] to finish, returning [B] or [shift] in case of [R], - * bridging eager computations into suspending. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.EagerEffect - * import arrow.core.continuations.eagerEffect - * import arrow.core.continuations.effect - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * suspend fun Either.toEagerEffect(): EagerEffect = eagerEffect { - * fold({ e -> shift(e) }, ::identity) - * } - * - * suspend fun main() { - * val either = Either.Left("failed") - * effect { - * val x: Int = either.toEagerEffect().bind() - * x - * }.toEither() shouldBe either - * } - * ``` - * - */ - public suspend fun EagerEffect.bind(): B { - 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)) - } - - public suspend fun arrow.core.raise.Effect.bind(): B = - fold(this@EffectScope::shift, ::identity) - - public suspend fun arrow.core.raise.EagerEffect.bind(): B = - fold({ shift(it) }, ::identity) - - /** - * Folds [Either] into [Effect], by returning [B] or a shift with [R]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.effect - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * val either = Either.Right(9) - * effect { - * 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 [Effect], by returning [B] or a shift with [R]. - * - * ```kotlin - * import arrow.core.Validated - * import arrow.core.continuations.effect - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * val validated = Validated.Valid(40) - * effect { - * val x: Int = validated.bind() - * x - * }.toValidated() shouldBe validated - * } - * ``` - * - */ - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither().bind()")) - public suspend fun Validated.bind(): B = - when (this) { - is Validated.Valid -> value - is Validated.Invalid -> shift(value) - } - - /** - * Folds [Result] into [Effect], by returning [B] or a transforming [Throwable] into [R] and - * shifting the result. - * - * ```kotlin - * import arrow.core.continuations.effect - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * private val default = "failed" - * suspend fun main() { - * val result = Result.success(1) - * effect { - * val x: Int = result.bind { _: Throwable -> default } - * x - * }.fold({ default }, ::identity) shouldBe result.getOrElse { default } - * } - * ``` - * - */ - public suspend fun Result.bind(transform: (Throwable) -> R): B = - fold(::identity) { throwable -> shift(transform(throwable)) } - - /** - * Folds [Option] into [Effect], by returning [B] or a transforming [None] into [R] and shifting the - * result. - * - * ```kotlin - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.continuations.effect - * import arrow.core.getOrElse - * import arrow.core.identity - * import io.kotest.matchers.shouldBe - * - * private val default = "failed" - * suspend fun main() { - * val option: Option = None - * effect { - * val x: Int = option.bind { default } - * x - * }.fold({ default }, ::identity) shouldBe option.getOrElse { default } - * } - * ``` - * - */ - public suspend fun Option.bind(shift: () -> R): B = - when (this) { - None -> shift(shift()) - is Some -> value - } - - /** - * ensure that condition is `true`, if it's `false` it will `shift` with the provided value [R]. - * Monadic version of [kotlin.require]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.continuations.effect - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * val condition = true - * val failure = "failed" - * val int = 4 - * effect { - * 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()) - - /** - * Encloses an action for which you want to catch any `shift`. - * [attempt] is used in combination with [catch]. - * - * ``` - * attempt { ... } catch { ... } - * ``` - * - * The [f] may `shift` into a different `EffectScope`, giving - * the chance for a later [catch] to change the shifted value. - * This is useful to simulate re-throwing of exceptions. - */ - @Deprecated( - "Use the arrow.core.raise.Raise type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick. Add missing imports and you're good to go!", - ReplaceWith("effect(f)", "arrow.core.raise.effect") - ) - @OptIn(ExperimentalTypeInference::class) - public suspend fun attempt( - @BuilderInference - f: suspend EffectScope.() -> A, - ): suspend EffectScope.() -> A = f - - /** - * When the [Effect] has shifted with [R] it will [recover] - * the shifted value to [A], and when it ran the computation to - * completion it will return the value [A]. - * [catch] is used in combination with [attempt]. - * - * ```kotlin - * import arrow.core.Either - * import arrow.core.None - * import arrow.core.Option - * import arrow.core.Validated - * import arrow.core.continuations.effect - * import io.kotest.assertions.fail - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * effect { - * val x = Either.Right(1).bind() - * val y = Validated.Valid(2).bind() - * val z = - * attempt { None.bind { "Option was empty" } } catch { 0 } - * x + y + z - * }.fold({ fail("Shift can never be the result") }, { it shouldBe 3 }) - * } - * ``` - * - */ - @Deprecated( - "This method is renamed to recover in the new Raise type." + - "Apply the ReplaceWith refactor, and then a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick. Add missing imports and you're good to go!", - ReplaceWith("recover(f)") - ) - public suspend infix fun (suspend EffectScope.() -> A).catch( - recover: suspend EffectScope.(E) -> A, - ): A = effect(this).fold({ recover(it) }, ::identity) - - public suspend infix fun (suspend EffectScope.() -> A).recover( - recover: suspend EffectScope.(E) -> A, - ): A = effect(this).fold({ recover(it) }, ::identity) -} - -/** - * 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 - * import arrow.core.continuations.effect - * import arrow.core.continuations.ensureNotNull - * import arrow.core.left - * import arrow.core.right - * import io.kotest.matchers.shouldBe - * - * suspend fun main() { - * val failure = "failed" - * val int: Int? = null - * effect { - * ensureNotNull(int) { failure } - * }.toEither() shouldBe (int?.right() ?: failure.left()) - * } - * ``` - * - */ -@Deprecated( - "Use the arrow.core.raise.Raise type instead, which is more general and can be used to and can be used to raise typed errors or _logical failures_\n" + - "The Raise type is source compatible, a simple find & replace of arrow.core.continuations.* to arrow.core.raise.* will do the trick.", - ReplaceWith("ensureNotNull(value, shift)", "arrow.core.raise.ensureNotNull") -) -@OptIn(ExperimentalContracts::class) -public suspend fun EffectScope.ensureNotNull(value: B?, shift: () -> R): B { - contract { returns() implies (value != null) } - return value ?: shift(shift()) -} - diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/either.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/either.kt deleted file mode 100644 index b6cd126398f..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/either.kt +++ /dev/null @@ -1,19 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either - -@Deprecated(eitherDSLDeprecation, ReplaceWith("either", "arrow.core.raise.either")) -@Suppress("ClassName") -public object either { - @Deprecated(eitherDSLDeprecation, ReplaceWith("either(f)", "arrow.core.raise.either")) - public inline fun eager(noinline f: suspend EagerEffectScope.() -> A): Either = - eagerEffect(f).toEither() - - @Deprecated(eitherDSLDeprecation, ReplaceWith("either(f)", "arrow.core.raise.either")) - public suspend operator fun invoke(f: suspend EffectScope.() -> A): Either = - effect(f).toEither() -} - -@PublishedApi internal const val eitherDSLDeprecation: String = - "The either DSL has been moved to arrow.core.raise.either.\n" + - "Replace import arrow.core.computations.either with arrow.core.raise.either" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/ior.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/ior.kt deleted file mode 100644 index 57effe8cbf6..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/ior.kt +++ /dev/null @@ -1,98 +0,0 @@ -package arrow.core.continuations - -import arrow.core.EmptyValue -import arrow.core.Ior -import arrow.core.identity -import arrow.typeclasses.Semigroup - -@Deprecated(iorDSLDeprecation, ReplaceWith("ior", "arrow.core.raise.ior")) -@Suppress("ClassName") -public object ior { - @Deprecated(iorDSLDeprecation, ReplaceWith("ior(semigroup, f)", "arrow.core.raise.ior")) - public inline fun eager( - semigroup: Semigroup, - crossinline f: suspend IorEagerEffectScope.() -> A - ): Ior = - eagerEffect> { - val effect = IorEagerEffectScope(semigroup, this) - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - 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) - - @Deprecated(iorDSLDeprecation, ReplaceWith("ior(semigroup, f)", "arrow.core.raise.ior")) - public suspend inline operator fun invoke( - semigroup: Semigroup, - crossinline f: suspend IorEffectScope.() -> A - ): Ior = - effect> { - val effect = IorEffectScope(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) -} - -@Deprecated( - "IorEffectScope is replaced with arrow.core.raise.IorRaise", - ReplaceWith("IorRaise", "arrow.core.raise.IorRaise") -) -public class IorEffectScope(semigroup: Semigroup, private val effect: EffectScope) : - EffectScope, Semigroup by semigroup { - - @PublishedApi - 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 - - public suspend fun Ior.bind(): B = - when (this) { - is Ior.Left -> shift(value) - is Ior.Right -> value - is Ior.Both -> { - combine(leftValue) - rightValue - } - } - - override suspend fun shift(r: E): B = effect.shift(combine(r)) -} - -@Deprecated( - "IorEagerEffectScope is replaced with arrow.core.raise.IorRaise", - ReplaceWith("IorRaise", "arrow.core.raise.IorRaise") -) -public class IorEagerEffectScope(semigroup: Semigroup, private val effect: EagerEffectScope) : - EagerEffectScope, Semigroup by semigroup { - - @PublishedApi - 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 - - public suspend fun Ior.bind(): B = - when (this) { - is Ior.Left -> shift(value) - is Ior.Right -> value - is Ior.Both -> { - combine(leftValue) - rightValue - } - } - - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - override suspend fun shift(r: E): B = effect.shift(combine(r)) -} - -@PublishedApi internal const val iorDSLDeprecation: String = - "The ior DSL has been moved to arrow.core.raise.ior.\n" + - "Replace import arrow.core.computations.ior with arrow.core.raise.ior" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/nullable.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/nullable.kt deleted file mode 100644 index 5923e079957..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/nullable.kt +++ /dev/null @@ -1,82 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Option -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.jvm.JvmInline - -@Deprecated( - "NullableEffectScope is replaced with arrow.core.raise.NullableRaise", - ReplaceWith("NullableRaise", "arrow.core.raise.NullableRaise") -) -@JvmInline -public value class NullableEffectScope(private val cont: EffectScope) : EffectScope { - override suspend fun shift(r: Nothing?): B = - cont.shift(r) - - public suspend fun Option.bind(): B = - bind { null } - - @OptIn(ExperimentalContracts::class) - public suspend fun B?.bind(): B { - contract { returns() implies (this@bind != null) } - return this ?: shift(null) - } - - public suspend fun ensure(value: Boolean): Unit = - ensure(value) { null } -} - -@Deprecated( - "NullableEagerEffectScope is replaced with arrow.core.raise.NullableRaise", - ReplaceWith("NullableRaise", "arrow.core.raise.NullableRaise") -) -@JvmInline -public value class NullableEagerEffectScope(private val cont: EagerEffectScope) : EagerEffectScope { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - override suspend fun shift(r: Nothing?): B = - cont.shift(r) - - public suspend fun Option.bind(): B = - bind { null } - - @OptIn(ExperimentalContracts::class) - public suspend fun B?.bind(): B { - contract { returns() implies (this@bind != null) } - return this ?: shift(null) - } - - public suspend fun ensure(value: Boolean): Unit = - ensure(value) { null } -} - -@OptIn(ExperimentalContracts::class) -public suspend fun NullableEffectScope.ensureNotNull(value: B?): B { - contract { returns() implies (value != null) } - return ensureNotNull(value) { null } -} - -@OptIn(ExperimentalContracts::class) -public suspend fun NullableEagerEffectScope.ensureNotNull(value: B?): B { - contract { returns() implies (value != null) } - return ensureNotNull(value) { null } -} - -@Deprecated(nullableDSLDeprecation, ReplaceWith("nullable", "arrow.core.raise.nullable")) -@Suppress("ClassName") -public object nullable { - @Deprecated(nullableDSLDeprecation, ReplaceWith("nullable(f)", "arrow.core.raise.nullable")) - public inline fun eager(crossinline f: suspend NullableEagerEffectScope.() -> A): A? = - eagerEffect { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - f(NullableEagerEffectScope(this)) - }.orNull() - - @Deprecated(nullableDSLDeprecation, ReplaceWith("nullable(f)", "arrow.core.raise.nullable")) - public suspend inline operator fun invoke(crossinline f: suspend NullableEffectScope.() -> A): A? = - effect { f(NullableEffectScope(this)) }.orNull() -} - -@PublishedApi internal const val nullableDSLDeprecation: String = - "The nullable DSL has been moved to arrow.core.raise.nullable.\n" + - "Replace import arrow.core.computations.nullable with arrow.core.raise.nullable" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/option.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/option.kt deleted file mode 100644 index 6131238b622..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/option.kt +++ /dev/null @@ -1,80 +0,0 @@ -package arrow.core.continuations - -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.identity -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract -import kotlin.jvm.JvmInline - -public suspend fun Effect.toOption(): Option = - fold(::identity) { Some(it) } - -public fun EagerEffect.toOption(): Option = - fold(::identity) { Some(it) } - -@JvmInline -public value class OptionEffectScope(private val cont: EffectScope) : EffectScope { - override suspend fun shift(r: None): B = - cont.shift(r) - - public suspend fun Option.bind(): B = - bind { None } - - public suspend fun ensure(value: Boolean): Unit = - ensure(value) { None } -} - -@OptIn(ExperimentalContracts::class) -public suspend fun OptionEffectScope.ensureNotNull(value: B?): B { - contract { returns() implies (value != null) } - return ensureNotNull(value) { None } -} - -@OptIn(ExperimentalContracts::class) -public suspend fun OptionEagerEffectScope.ensureNotNull(value: B?): B { - contract { returns() implies (value != null) } - return ensureNotNull(value) { None } -} - -@JvmInline -public value class OptionEagerEffectScope(private val cont: EagerEffectScope) : EagerEffectScope { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - override suspend fun shift(r: None): B = - cont.shift(r) - - public suspend fun Option.bind(): B = - bind { None } - - public suspend fun ensure(value: Boolean): Unit = - ensure(value) { None } -} - -@Deprecated( - optionDSLDeprecation, - ReplaceWith("option", "arrow.core.raise.option") -) -@Suppress("ClassName") -public object option { - @Deprecated( - optionDSLDeprecation, - ReplaceWith("option(f)", "arrow.core.raise.option") - ) - public inline fun eager(crossinline f: suspend OptionEagerEffectScope.() -> A): Option = - eagerEffect { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - f(OptionEagerEffectScope(this)) - }.toOption() - - @Deprecated( - optionDSLDeprecation, - ReplaceWith("option(f)", "arrow.core.raise.option") - ) - public suspend inline operator fun invoke(crossinline f: suspend OptionEffectScope.() -> A): Option = - effect { f(OptionEffectScope(this)) }.toOption() -} - -@PublishedApi internal const val optionDSLDeprecation: String = - "The option DSL has been moved to arrow.core.raise.option.\n" + - "Replace import arrow.core.computations.option with arrow.core.raise.option" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/result.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/result.kt deleted file mode 100644 index 1256bf2d503..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/continuations/result.kt +++ /dev/null @@ -1,54 +0,0 @@ -package arrow.core.continuations - -import arrow.core.identity -import kotlin.jvm.JvmInline - -public suspend fun Effect.toResult(): Result = - fold({ Result.failure(it) }, { Result.success(it) }) - -public fun EagerEffect.toResult(): Result = - fold({ Result.failure(it) }, { Result.success(it) }) - -@JvmInline -public value class ResultEffectScope(private val cont: EffectScope) : EffectScope { - override suspend fun shift(r: Throwable): B = - cont.shift(r) - - public suspend fun Result.bind(): B = - fold(::identity) { shift(it) } -} - -@JvmInline -public value class ResultEagerEffectScope(private val cont: EagerEffectScope) : EagerEffectScope { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - override suspend fun shift(r: Throwable): B = - cont.shift(r) - - public suspend fun Result.bind(): B = - fold(::identity) { shift(it) } -} - -@Deprecated(resultDSLDeprecation, ReplaceWith("result", "arrow.core.raise.result")) -@Suppress("ClassName") -public object result { - @Deprecated( - resultDSLDeprecation, - ReplaceWith("result(f)", "arrow.core.raise.result") - ) - public inline fun eager(crossinline f: suspend ResultEagerEffectScope.() -> A): Result = - eagerEffect { - @Suppress("ILLEGAL_RESTRICTED_SUSPENDING_FUNCTION_CALL") - f(ResultEagerEffectScope(this)) - }.toResult() - - @Deprecated( - resultDSLDeprecation, - ReplaceWith("result(f)", "arrow.core.raise.result") - ) - public suspend inline operator fun invoke(crossinline f: suspend ResultEffectScope.() -> A): Result = - effect { f(ResultEffectScope(this)) }.toResult() -} - -@PublishedApi internal const val resultDSLDeprecation: String = - "The result DSL has been moved to arrow.core.raise.result.\n" + - "Replace import arrow.core.computations.* with arrow.core.raise.*" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/map.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/map.kt index c0adf85de4f..2ce773040f0 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/map.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/map.kt @@ -2,14 +2,10 @@ package arrow.core -import arrow.typeclasses.SemigroupDeprecation -import kotlin.experimental.ExperimentalTypeInference -import arrow.core.raise.RaiseAccumulate import arrow.core.raise.either import arrow.core.raise.mapOrAccumulate -import arrow.core.raise.option -import arrow.typeclasses.Semigroup -import arrow.typeclasses.combine +import arrow.core.raise.RaiseAccumulate +import kotlin.experimental.ExperimentalTypeInference /** * Combines to structures by taking the intersection of their shapes @@ -40,7 +36,7 @@ public fun Map.zip(other: Map): Map> = * * fun test() { * mapOf(1 to "A", 2 to "B").zip(mapOf(1 to "1", 2 to "2", 3 to "3")) { - * key, a, b -> "$a ~ $b" + * _, a, b -> "$a ~ $b" * } shouldBe mapOf(1 to "A ~ 1", 2 to "B ~ 2") * } * ``` @@ -258,72 +254,6 @@ public fun Map.flatMap(f: (Map.Entry) -> Map): Map, Either>> { m -> either> { m.mapValues { (_, a) -> f(a).bind() } } }", - "arrow.core.raise.either" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Map.traverse(f: (A) -> Either): Either> = - let { m -> either { m.mapValues { (_, a) -> f(a).bind() } } } - -@Deprecated( - "Traverse for Either is being deprecated in favor of Either DSL + Map.mapValues.\n$NicheAPI", - ReplaceWith( - "let, Either>> { m -> either> { m.mapValues { (_, a) -> f(a).bind() } } }", - "arrow.core.raise.either" - ) -) -public inline fun Map.traverseEither(f: (A) -> Either): Either> = - let { m -> either { m.mapValues { (_, a) -> f(a).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the either DSL.", - ReplaceWith("let>, Either>> { m -> either> { m.bindAll() } }", "arrow.core.raise.either") -) -public fun Map>.sequence(): Either> = - let { m -> either { m.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the either DSL.", - ReplaceWith( - "let>, Either>> { m -> either> { m.bindAll() } }", - "arrow.core.raise.either" - ) -) -public fun Map>.sequenceEither(): Either> = - let { m -> either { m.bindAll() } } - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate({e1, e2 -> e1 + e2}) { f(it.value).bind() }.toValidated()", - "arrow.core.mapOrAccumulate", - "arrow.typeclasses.combine" - ) -) -public inline fun Map.traverseValidated( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate(semigroup::combine) { f(it.value).bind() }.toValidated() - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "this.mapOrAccumulate({e1, e2 -> e1 + e2}) { f(it.value).bind() }.toValidated()", - "arrow.core.mapOrAccumulate" - ) -) -public inline fun Map.traverse( - semigroup: Semigroup, - f: (A) -> Validated -): Validated> = - mapOrAccumulate(semigroup::combine) { f(it.value).bind() }.toValidated() - public inline fun Map.mapOrAccumulate( combine: (E, E) -> E, @BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B @@ -337,81 +267,6 @@ public inline fun Map.mapOrAccumulate( mapOrAccumulate(this@mapOrAccumulate, transform) } -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate, A>({e1, e2 -> e1 + e2}) { it.value.bind() }.toValidated()", - "arrow.core.mapOrAccumulate", - "arrow.typeclasses.combine" - ) -) -public fun Map>.sequenceValidated(semigroup: Semigroup): Validated> = - sequence(semigroup) - -@Deprecated( - ValidatedDeprMsg + "Use the mapOrAccumulate API instead", - ReplaceWith( - "mapOrAccumulate, A>({e1, e2 -> e1 + e2}) { it.value.bind() }.toValidated()", - "arrow.core.mapOrAccumulate", - "arrow.typeclasses.combine" - ) -) -public fun Map>.sequence(semigroup: Semigroup): Validated> = - mapOrAccumulate(semigroup::combine) { it.value.bind() }.toValidated() - -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + Map.mapValues.\n$NicheAPI", - ReplaceWith( - "let, Option>> { m -> option> { m.mapValues { (_, a) -> f(a).bind() } } }", - "arrow.core.raise.option" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Map.traverse(f: (A) -> Option): Option> = - let { m -> option { m.mapValues { (_, a) -> f(a).bind() } } } - -@Deprecated( - "Traverse for Option is being deprecated in favor of Option DSL + Map.mapValues.\n$NicheAPI", - ReplaceWith( - "let, Option>> { m -> option> { m.mapValues { (_, a) -> f(a).bind() } } }", - "arrow.core.raise.option" - ) -) -public inline fun Map.traverseOption(f: (A) -> Option): Option> = - let { m -> option { m.mapValues { (_, a) -> f(a).bind() } } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the option DSL.", - ReplaceWith( - "let>, Option>> { m -> option> { m.bindAll() } }", - "arrow.core.raise.option" - ) -) -public fun Map>.sequenceOption(): Option> = - let { m -> option { m.bindAll() } } - -@Deprecated( - "The sequence extension function is being deprecated in favor of the option DSL.", - ReplaceWith( - "let>, Option>> { m -> option> { m.bindAll() } }", - "arrow.core.raise.option" - ) -) -public fun Map>.sequence(): Option> = - let { m -> option { m.bindAll() } } - -@Deprecated( - "Void is being deprecated in favor of simple Map.mapValues.\n$NicheAPI", - ReplaceWith("this.mapValues { }") -) -public fun Map.void(): Map = - mapValues { } - -@Deprecated(DeprecatedWiden, ReplaceWith("this")) -public fun Map.widen(): Map = - this - public fun Map.mapNotNull(transform: (Map.Entry) -> B?): Map = buildMap { this@mapNotNull.forEach { entry -> @@ -419,13 +274,6 @@ public fun Map.mapNotNull(transform: (Map.Entry) -> B?): M } } -@Deprecated( - "filterMap is being deprecated in favor of mapNotNull to align with Kotlin Std naming.", - ReplaceWith("mapNotNull { (_, a) -> f(a) }", "arrow.core.mapNotNull") -) -public fun Map.filterMap(f: (A) -> B?): Map = - mapNotNull { (_, a) -> f(a) } - public fun Map>.filterOption(): Map = buildMap { this@filterOption.forEach { (key, option) -> @@ -492,13 +340,6 @@ private class Entry(override val key: K, override val value: V) : Map.Entr public fun Map.salign(other: Map, combine: (A, A) -> A): Map = padZip(other, { _, a -> a }, { _, b -> b }) { _, a, b -> combine(a, b) } -@Deprecated( - "${SemigroupDeprecation}\n use align instead", - ReplaceWith("salign(other){a1, a2 -> a1 + a2}") -) -public fun Map.salign(SG: Semigroup, other: Map): Map = - salign(other, SG::combine) - /** * Align two structures as in zip, but filling in blanks with null. */ @@ -508,6 +349,7 @@ public fun Map.padZip(other: Map): Map> = public fun Map.padZip(other: Map, fa: (K, A?, B?) -> C): Map = padZip(other, { k, a -> fa(k, a, null) }, { k, b -> fa(k, null, b) }) { k, a, b -> fa(k, a, b) } +@Suppress("UNCHECKED_CAST") public inline fun Map.padZip( other: Map, left: (K, A) -> C, @@ -644,33 +486,8 @@ public fun Map.combine(other: Map, combine: (A, A) -> A): Map if (size < other.size) fold(other) { my, (k, b) -> my + Pair(k, my[k]?.let { combine(b, it) } ?: b) } else other.fold(this@combine) { my, (k, a) -> my + Pair(k, my[k]?.let { combine(a, it) } ?: a) } -@Deprecated(SemigroupDeprecation, ReplaceWith("combine(b){a1, a2 -> a1 + a2}")) -public fun Map.combine(SG: Semigroup, b: Map): Map = - combine(b, SG::combine) - -@Deprecated( - "Use fold & Map.combine instead.\n$NicheAPI", - ReplaceWith( - "fold(emptyMap()) { acc, map -> acc.combine(map){a1, a2 -> a1 + a2} }", - "arrow.core.combine" - ) -) -public fun Iterable>.combineAll(SG: Semigroup): Map = - fold(emptyMap()) { acc, map -> acc.combine(map, SG::combine) } - public inline fun Map.fold(initial: B, operation: (acc: B, Map.Entry) -> B): B { var accumulator = initial forEach { accumulator = operation(accumulator, it) } return accumulator } - -@Deprecated("Use fold instead foldLeft", ReplaceWith("fold(b, f)")) -public inline fun Map.foldLeft(b: B, f: (B, Map.Entry) -> B): B = - fold(b, f) - -@Deprecated("Internal method will be removed from binary in 2.0.0") -internal fun Pair?.asIterable(): Iterable> = - when (this) { - null -> emptyList() - else -> listOf(this) - } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/nonFatalOrThrow.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/nonFatalOrThrow.kt index 5a3c58883a5..12efe514998 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/nonFatalOrThrow.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/nonFatalOrThrow.kt @@ -17,7 +17,7 @@ package arrow.core * else -> "Hello" * } * - * fun main(args: Array) { + * fun main() { * val nonFatal: Either = * //sampleStart * try { diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/predef.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/predef.kt index c81db653de3..c70186c6124 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/predef.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/predef.kt @@ -1,8 +1,6 @@ package arrow.core -import arrow.typeclasses.Semigroup -import arrow.typeclasses.SemigroupDeprecation - +@Suppress("NOTHING_TO_INLINE") public inline fun identity(a: A): A = a /** @@ -23,11 +21,3 @@ public object EmptyValue { public inline fun fold(value: Any?, ifEmpty: () -> R, ifNotEmpty: (T) -> R): R = if (value === EmptyValue) ifEmpty() else ifNotEmpty(value as T) } - -/** - * Like [Semigroup.maybeCombine] but for using with [EmptyValue] - */ -@PublishedApi -@Deprecated(SemigroupDeprecation, ReplaceWith("EmptyValue.combine(first, second) { x, y -> x.combine(y) }", "arrow.core.EmptyValue")) -internal fun Semigroup.emptyCombine(first: Any?, second: T): T = - EmptyValue.combine(first, second) { x, y -> x.combine(y) } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt index 14c3111c624..1cac6b4d3cd 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Builders.kt @@ -7,6 +7,7 @@ package arrow.core.raise import arrow.atomic.Atomic import arrow.atomic.updateAndGet import arrow.core.Either +import arrow.core.EmptyValue import arrow.core.Ior import arrow.core.IorNel import arrow.core.NonEmptyList @@ -16,13 +17,27 @@ import arrow.core.Option import arrow.core.Some import arrow.core.getOrElse import arrow.core.identity -import arrow.core.EmptyValue +import arrow.core.none +import arrow.core.some import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName +@RaiseDSL +public inline fun singleton( + raise: () -> A, + @BuilderInference block: SingletonRaise.() -> A, +): A { + contract { + callsInPlace(raise, InvocationKind.AT_MOST_ONCE) + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + return recover({ block(SingletonRaise(this)) }) { raise() } +} + /** * Runs a computation [block] using [Raise], and return its outcome as [Either]. * - [Either.Right] represents success, @@ -33,8 +48,10 @@ import kotlin.jvm.JvmName * Read more about running a [Raise] computation in the * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ -public inline fun either(@BuilderInference block: Raise.() -> A): Either = - fold({ block.invoke(this) }, { Either.Left(it) }, { Either.Right(it) }) +public inline fun either(@BuilderInference block: Raise.() -> A): Either { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return fold(block, { Either.Left(it) }, { Either.Right(it) }) +} /** * Runs a computation [block] using [Raise], and return its outcome as nullable type, @@ -45,11 +62,13 @@ public inline fun either(@BuilderInference block: Raise.() -> * Read more about running a [Raise] computation in the * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). * - * @see NullableRaise.ignoreErrors By default, `nullable` only allows raising `null`. - * Calling [ignoreErrors][NullableRaise.ignoreErrors] inside `nullable` allows to raise any error, which will be returned to the caller as if `null` was raised. + * @see SingletonRaise.ignoreErrors By default, `nullable` only allows raising `null`. + * Calling [ignoreErrors][SingletonRaise.ignoreErrors] inside `nullable` allows to raise any error, which will be returned to the caller as if `null` was raised. */ -public inline fun nullable(block: NullableRaise.() -> A): A? = - merge { block(NullableRaise(this)) } +public inline fun nullable(block: SingletonRaise.() -> A): A? { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return singleton({ null }, block) +} /** * Runs a computation [block] using [Raise], and return its outcome as [Result]. @@ -58,8 +77,10 @@ public inline fun nullable(block: NullableRaise.() -> A): A? = * Read more about running a [Raise] computation in the * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ -public inline fun result(block: ResultRaise.() -> A): Result = - fold({ block(ResultRaise(this)) }, Result.Companion::failure, Result.Companion::failure, Result.Companion::success) +public inline fun result(block: ResultRaise.() -> A): Result { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return fold({ block(ResultRaise(this)) }, Result.Companion::failure, Result.Companion::failure, Result.Companion::success) +} /** * Runs a computation [block] using [Raise], and return its outcome as [Option]. @@ -71,8 +92,10 @@ public inline fun result(block: ResultRaise.() -> A): Result = * Read more about running a [Raise] computation in the * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ -public inline fun option(block: OptionRaise.() -> A): Option = - fold({ block(OptionRaise(this)) }, ::identity, ::Some) +public inline fun option(block: SingletonRaise.() -> A): Option { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return singleton(::none) { block().some() } +} /** * Runs a computation [block] using [Raise], and return its outcome as [Ior]. @@ -90,6 +113,7 @@ public inline fun option(block: OptionRaise.() -> A): Option = * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ public inline fun ior(noinline combineError: (Error, Error) -> Error, @BuilderInference block: IorRaise.() -> A): Ior { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } val state: Atomic = Atomic(EmptyValue) return fold( { block(IorRaise(combineError, state, this)) }, @@ -114,81 +138,104 @@ public inline fun ior(noinline combineError: (Error, Error) -> Error, * Read more about running a [Raise] computation in the * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ -public inline fun iorNel(noinline combineError: (NonEmptyList, NonEmptyList) -> NonEmptyList = { a, b -> a + b }, @BuilderInference block: IorRaise>.() -> A): IorNel = - ior(combineError, block) +public inline fun iorNel(noinline combineError: (NonEmptyList, NonEmptyList) -> NonEmptyList = { a, b -> a + b }, @BuilderInference block: IorRaise>.() -> A): IorNel { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return ior(combineError, block) +} /** - * Implementation of [Raise] used by `ignoreErrors`. - * You should never use this directly. + * Runs a computation [block] using [Raise], and ignore its outcome. + * + * This function re-throws any exceptions thrown within the [Raise] block. + * + * Read more about running a [Raise] computation in the + * [Arrow docs](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#running-and-inspecting-results). */ -public class IgnoreErrorsRaise( - private val raise: Raise, - private val error: () -> N -) : Raise { +public inline fun impure(block: SingletonRaise.() -> Unit) { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + return singleton({ }, block) +} + +public class SingletonRaise(private val raise: Raise): Raise { @RaiseDSL - override fun raise(r: Any?): Nothing = - raise.raise(error()) + public fun raise(): Nothing = raise.raise(Unit) @RaiseDSL - public fun ensure(value: Boolean): Unit = ensure(value) { null } + override fun raise(r: E): Nothing = raise() + + @RaiseDSL + public fun ensure(condition: Boolean) { + contract { returns() implies condition } + return if (condition) Unit else raise() + } @RaiseDSL - public fun Option.bind(): A = getOrElse { raise(null) } + public fun Option.bind(): A { + contract { returns() implies (this@bind is Some) } + return getOrElse { raise() } + } @RaiseDSL public fun A?.bind(): A { contract { returns() implies (this@bind != null) } - return this ?: raise(null) + return this ?: raise() } @RaiseDSL public fun ensureNotNull(value: A?): A { contract { returns() implies (value != null) } - return ensureNotNull(value) { null } + return value ?: raise() } -} -public typealias Null = Nothing? - -/** - * Implementation of [Raise] used by [nullable]. - * You should never use this directly. - */ -public class NullableRaise(private val raise: Raise) : Raise by raise { @RaiseDSL - public fun ensure(value: Boolean): Unit = ensure(value) { null } + @JvmName("bindAllNullable") + public fun Map.bindAll(): Map = + mapValues { (_, v) -> v.bind() } + + @JvmName("bindAllOption") + public fun Map>.bindAll(): Map = + mapValues { (_, v) -> v.bind() } @RaiseDSL - public fun Option.bind(): A = getOrElse { raise(null) } + @JvmName("bindAllNullable") + public fun Iterable.bindAll(): List = + map { it.bind() } @RaiseDSL - public fun A?.bind(): A { - contract { returns() implies (this@bind != null) } - return this ?: raise(null) - } + @JvmName("bindAllOption") + public fun Iterable>.bindAll(): List = + map { it.bind() } + @RaiseDSL @JvmName("bindAllNullable") - public fun Map.bindAll(): Map = - mapValues { (_, v) -> v.bind() } + public fun NonEmptyList.bindAll(): NonEmptyList = + map { it.bind() } @RaiseDSL - @JvmName("bindAllNullable") - public fun Iterable.bindAll(): List = + @JvmName("bindAllOption") + public fun NonEmptyList>.bindAll(): NonEmptyList = map { it.bind() } @RaiseDSL - public fun ensureNotNull(value: A?): A { - contract { returns() implies (value != null) } - return ensureNotNull(value) { null } - } + @JvmName("bindAllNullable") + public fun NonEmptySet.bindAll(): NonEmptySet = + map { it.bind() }.toNonEmptySet() + + @RaiseDSL + @JvmName("bindAllOption") + public fun NonEmptySet>.bindAll(): NonEmptySet = + map { it.bind() }.toNonEmptySet() @RaiseDSL public inline fun recover( - @BuilderInference block: NullableRaise.() -> A, + block: SingletonRaise.() -> A, recover: () -> A, - ): A = when (val nullable = nullable(block)) { - null -> recover() - else -> nullable + ): A { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + callsInPlace(recover, InvocationKind.AT_MOST_ONCE) + } + return singleton(recover) { ignoreErrors(block) } } /** @@ -197,8 +244,14 @@ public class NullableRaise(private val raise: Raise) : Raise by rais */ @RaiseDSL public inline fun ignoreErrors( - @BuilderInference block: IgnoreErrorsRaise.() -> A, - ): A = block(IgnoreErrorsRaise(this) { null }) + block: SingletonRaise.() -> A, + ): A { + contract { callsInPlace(block, InvocationKind.AT_MOST_ONCE) } + // This is safe because SingletonRaise never leaks the e from `raise(e: E)`, instead always calling `raise()`. + // and hence the type parameter of SingletonRaise merely states what errors it accepts and ignores. + @Suppress("UNCHECKED_CAST") + return block(this as SingletonRaise) + } } /** @@ -238,61 +291,6 @@ public class ResultRaise(private val raise: Raise) : Raise ) } -/** - * Implementation of [Raise] used by [option]. - * You should never use this directly. - */ -public class OptionRaise(private val raise: Raise) : Raise by raise { - @RaiseDSL - public fun Option.bind(): A = getOrElse { raise(None) } - - @JvmName("bindAllOption") - public fun Map>.bindAll(): Map = - mapValues { (_, v) -> v.bind() } - - @RaiseDSL - @JvmName("bindAllOption") - public fun Iterable>.bindAll(): List = - map { it.bind() } - - @RaiseDSL - @JvmName("bindAllOption") - public fun NonEmptyList>.bindAll(): NonEmptyList = - map { it.bind() } - - @RaiseDSL - @JvmName("bindAllOption") - public fun NonEmptySet>.bindAll(): NonEmptySet = - map { it.bind() }.toNonEmptySet() - - @RaiseDSL - public fun ensure(value: Boolean): Unit = ensure(value) { None } - - @RaiseDSL - public fun ensureNotNull(value: A?): A { - contract { returns() implies (value != null) } - return ensureNotNull(value) { None } - } - - @RaiseDSL - public inline fun recover( - @BuilderInference block: OptionRaise.() -> A, - recover: () -> A, - ): A = when (val option = option(block)) { - is None -> recover() - is Some -> option.value - } - - /** - * Introduces a scope where you can [bind] errors of any type, - * but no information is saved in the [raise] case. - */ - @RaiseDSL - public inline fun ignoreErrors( - @BuilderInference block: IgnoreErrorsRaise.() -> A, - ): A = block(IgnoreErrorsRaise(this) { None }) -} - /** * Implementation of [Raise] used by [ior]. * You should never use this directly. @@ -341,6 +339,10 @@ public class IorRaise @PublishedApi internal constructor( @BuilderInference block: IorRaise.() -> A, recover: (error: Error) -> A, ): A { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + callsInPlace(recover, InvocationKind.AT_MOST_ONCE) + } val state: Atomic = Atomic(EmptyValue) return recover({ try { diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Effect.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Effect.kt index b25c67eee4c..232f8318627 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Effect.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Effect.kt @@ -289,8 +289,8 @@ import kotlin.jvm.JvmName * ```kotlin * val default5: Effect = * foreign - * .catch { ex: RuntimeException -> -1 } - * .catch { ex: java.sql.SQLException -> -2 } + * .catch { _: RuntimeException -> -1 } + * .catch { _: java.sql.SQLException -> -2 } * ``` * * Finally, since `catch` also supports `suspend` we can safely call other `suspend` code and throw `Throwable` into the `suspend` system. @@ -366,7 +366,7 @@ import kotlin.jvm.JvmName * import arrow.core.raise.fold * import arrow.fx.coroutines.ExitCase * import arrow.fx.coroutines.guaranteeCase - * import arrow.fx.coroutines.parTraverse + * import arrow.fx.coroutines.parMap * import io.kotest.assertions.fail * import io.kotest.matchers.shouldBe * import io.kotest.matchers.types.shouldBeTypeOf @@ -384,7 +384,7 @@ import kotlin.jvm.JvmName * val error = "Error" * val exits = (0..3).map { CompletableDeferred() } * effect> { - * (0..4).parTraverse { index -> + * (0..4).parMap { index -> * if (index == 4) raise(error) * else awaitExitCase(exits[index]) * } @@ -456,7 +456,7 @@ import kotlin.jvm.JvmName * effect { * bracketCase( * acquire = { File("build.gradle.kts").bufferedReader() }, - * use = { reader: BufferedReader -> raise(error) }, + * use = { _: BufferedReader -> raise(error) }, * release = { reader, exitCase -> * reader.close() * exit.complete(exitCase) @@ -664,11 +664,13 @@ import kotlin.jvm.JvmName */ public typealias Effect = suspend Raise.() -> A +@Suppress("NOTHING_TO_INLINE") public inline fun effect(@BuilderInference noinline block: suspend Raise.() -> A): Effect = block /** The same behavior and API as [Effect] except without requiring _suspend_. */ public typealias EagerEffect = Raise.() -> A +@Suppress("NOTHING_TO_INLINE") public inline fun eagerEffect(@BuilderInference noinline block: Raise.() -> A): EagerEffect = block public suspend fun Effect.merge(): A = merge { invoke() } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/ErrorHandlers.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/ErrorHandlers.kt index dbca820ca22..fa49119e799 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/ErrorHandlers.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/ErrorHandlers.kt @@ -23,9 +23,9 @@ import kotlin.jvm.JvmName * * val error = effect { raise(Error) } // Raise(error) * - * val a = error.recover { error -> User } // Success(User) - * val b = error.recover { error -> raise("other-failure") } // Raise(other-failure) - * val c = error.recover { error -> throw RuntimeException("BOOM") } // Exception(BOOM) + * val a = error.recover { _ -> User } // Success(User) + * val b = error.recover { _ -> raise("other-failure") } // Raise(other-failure) + * val c = error.recover { _ -> throw RuntimeException("BOOM") } // Exception(BOOM) * ``` * */ @@ -93,7 +93,7 @@ public fun Effect.catch(): Effect> = catch({ Result.success(invoke()) }, Result.Companion::failure) } -public suspend inline infix fun Effect.getOrElse(recover: suspend (error: Error) -> A): A = +public suspend inline infix fun Effect.getOrElse(recover: (error: Error) -> A): A = recover({ invoke() }) { recover(it) } /** @@ -110,9 +110,9 @@ public suspend inline infix fun Effect.getOrElse(recover: s * * val error = effect { raise(Error) } // Raise(error) * - * val a = error.mapError { error -> "some-failure" } // Raise(some-failure) + * val a = error.mapError { _ -> "some-failure" } // Raise(some-failure) * val b = error.mapError(Any::toString) // Raise(Error) - * val c = error.mapError { error -> throw RuntimeException("BOOM") } // Exception(BOOM) + * val c = error.mapError { _ -> throw RuntimeException("BOOM") } // Exception(BOOM) * ``` * */ @@ -147,7 +147,7 @@ public inline infix fun EagerEffect.getOrElse(recover: (err * * val error = eagerEffect { raise(Error) } // Raise(error) * - * val a = error.mapError { error -> "some-failure" } // Raise(some-failure) + * val a = error.mapError { _ -> "some-failure" } // Raise(some-failure) * val b = error.mapError(Any::toString) // Raise(Error) * ``` * diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt index d17779492a0..a3eced1ab62 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Fold.kt @@ -107,6 +107,7 @@ public inline fun fold( transform: (value: A) -> B, ): B { contract { + callsInPlace(block, AT_MOST_ONCE) callsInPlace(recover, AT_MOST_ONCE) callsInPlace(transform, AT_MOST_ONCE) } @@ -132,6 +133,7 @@ public inline fun fold( transform: (value: A) -> B, ): B { contract { + callsInPlace(block, AT_MOST_ONCE) callsInPlace(catch, AT_MOST_ONCE) callsInPlace(recover, AT_MOST_ONCE) callsInPlace(transform, AT_MOST_ONCE) @@ -195,6 +197,10 @@ public inline fun Raise.traced( @BuilderInference block: Raise.() -> A, trace: (trace: Trace, error: Error) -> Unit ): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(trace, AT_MOST_ONCE) + } val nested = DefaultRaise(true) return try { block(nested).also { nested.complete() } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Mappers.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Mappers.kt index c6cb52e977a..aa8e8963f9a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Mappers.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Mappers.kt @@ -6,8 +6,6 @@ import arrow.core.Either import arrow.core.Ior import arrow.core.Option import arrow.core.Some -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -16,30 +14,11 @@ public suspend fun Effect.toEither(): Either = ei /** Run the [EagerEffect] by returning [Either.Right] of [A], or [Either.Left] of [Error]. */ public fun EagerEffect.toEither(): Either = either { invoke() } -/** Run the [Effect] by returning [Validated.Valid] of [A], or [Validated.Invalid] of [Error]. */ -@Deprecated(ValidatedDeprMsg, ReplaceWith("toEither()")) -public suspend fun Effect.toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } -/** Run the [EagerEffect] by returning [Validated.Valid] of [A], or [Validated.Invalid] of [Error]. */ -@Deprecated(ValidatedDeprMsg, ReplaceWith("toEither()")) -public fun EagerEffect.toValidated(): Validated = fold({ Validated.Invalid(it) }) { Validated.Valid(it) } - /** Run the [Effect] by returning [Ior.Right] of [A], or [Ior.Left] of [Error]. */ public suspend fun Effect.toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } /** Run the [EagerEffect] by returning [Ior.Right] of [A], or [Ior.Left] of [Error]. */ public fun EagerEffect.toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } -@Deprecated( - "orNull is being renamed to getOrNull to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNull()", "arrow.core.raise.getOrNull") -) -public suspend fun Effect.orNull(): A? = getOrElse { null } - -@Deprecated( - "orNull is being renamed to getOrNull to be more consistent with the Kotlin Standard Library naming", - ReplaceWith("getOrNull()", "arrow.core.raise.getOrNull") -) -public fun EagerEffect.orNull(): A? = getOrElse { null } - /** Run the [Effect] by returning [A], or `null` if raised with [Error]. */ public suspend fun Effect.getOrNull(): A? = getOrElse { null } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt index 007f6e90581..429d2ddd12d 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt @@ -1,5 +1,4 @@ @file:OptIn(ExperimentalTypeInference::class, ExperimentalContracts::class) -@file:Suppress("DEPRECATION") @file:JvmMultifileClass @file:JvmName("RaiseKt") @@ -8,9 +7,6 @@ package arrow.core.raise import arrow.core.Either import arrow.core.NonEmptyList import arrow.core.NonEmptySet -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg -import arrow.core.continuations.EffectScope import arrow.core.getOrElse import arrow.core.identity import arrow.core.nonFatalOrThrow @@ -95,7 +91,6 @@ public annotation class RaiseDSL * import arrow.core.raise.effect * import arrow.core.raise.ior * import arrow.core.raise.toEither - * import arrow.typeclasses.Semigroup * import io.kotest.matchers.shouldBe * * fun Raise.failure(): Int = raise("failed") @@ -212,35 +207,6 @@ public interface Raise { @RaiseDSL public fun raise(r: Error): Nothing - @Deprecated("Use raise instead", ReplaceWith("raise(r)")) - public fun shift(r: Error): A = raise(r) - - @RaiseDSL - public suspend fun arrow.core.continuations.Effect.bind(): A = - fold({ raise(it) }, ::identity) - - // Added for source compatibility with EffectScope / EagerScope - @RaiseDSL - public suspend fun arrow.core.continuations.EagerEffect.bind(): A = - fold({ raise(it) }, ::identity) - - @Deprecated( - "Use getOrElse on Raise, Effect or EagerEffect instead.", - ReplaceWith("effect { f() }") - ) - public suspend fun attempt( - @BuilderInference - f: suspend EffectScope.() -> A, - ): arrow.core.continuations.Effect = arrow.core.continuations.effect(f) - - @Deprecated( - "Use getOrElse on Raise, Effect or EagerEffect instead.", - ReplaceWith("fold({ recover(it) }, ::identity)") - ) - public suspend infix fun arrow.core.continuations.Effect.catch( - recover: suspend Raise.(otherError: OtherError) -> A, - ): A = fold({ recover(it) }, ::identity) - /** * Invoke an [EagerEffect] inside `this` [Raise] context. * Any _logical failure_ is raised in `this` [Raise] context, @@ -298,7 +264,7 @@ public interface Raise { * * either { * val x = one.bind() - * val y = recover({ left.bind() }) { failure : String -> 1 } + * val y = recover({ left.bind() }) { _ : String -> 1 } * x + y * } shouldBe Either.Right(2) * } @@ -320,18 +286,6 @@ public interface Raise { public fun Map>.bindAll(): Map = mapValues { (_, a) -> a.bind() } - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither().bind()")) - @RaiseDSL - public fun Validated.bind(): A = when (this) { - is Validated.Invalid -> raise(value) - is Validated.Valid -> value - } - - /** - * Extracts all the values in the [Iterable], raising every [Either.Left] - * as a _logical failure_. In other words, executed [bind] over every - * value in this [Iterable]. - */ @RaiseDSL public fun Iterable>.bindAll(): List = map { it.bind() } @@ -371,7 +325,7 @@ public interface Raise { * recover({ raise("failed") }) { str -> str.length } shouldBe 6 * * either { - * recover({ raise("failed") }) { str -> raise(-1) } + * recover({ raise("failed") }) { _ -> raise(-1) } * } shouldBe Either.Left(-1) * } * ``` @@ -382,7 +336,13 @@ public interface Raise { public inline fun recover( @BuilderInference block: Raise.() -> A, @BuilderInference recover: (error: Error) -> A, -): A = fold(block, { throw it }, recover, ::identity) +): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(recover, AT_MOST_ONCE) + } + return fold(block, { throw it }, recover, ::identity) +} /** * Execute the [Raise] context function resulting in [A] or any _logical error_ of type [Error], @@ -417,7 +377,14 @@ public inline fun recover( @BuilderInference block: Raise.() -> A, @BuilderInference recover: (error: Error) -> A, @BuilderInference catch: (throwable: Throwable) -> A, -): A = fold(block, catch, recover, ::identity) +): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(recover, AT_MOST_ONCE) + callsInPlace(catch, AT_MOST_ONCE) + } + return fold(block, catch, recover, ::identity) +} /** * Execute the [Raise] context function resulting in [A] or any _logical error_ of type [Error], @@ -453,7 +420,14 @@ public inline fun recover( @BuilderInference block: Raise.() -> A, @BuilderInference recover: (error: Error) -> A, @BuilderInference catch: (t: T) -> A, -): A = fold(block, { t -> if (t is T) catch(t) else throw t }, recover, ::identity) +): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(recover, AT_MOST_ONCE) + callsInPlace(catch, AT_MOST_ONCE) + } + return fold(block, { t -> if (t is T) catch(t) else throw t }, recover, ::identity) +} /** * Allows safely catching exceptions without capturing [CancellationException], @@ -467,7 +441,7 @@ public inline fun recover( * --> * ```kotlin * fun test() { - * catch({ throw RuntimeException("BOOM") }) { t -> + * catch({ throw RuntimeException("BOOM") }) { _ -> * "fallback" * } shouldBe "fallback" * @@ -487,12 +461,17 @@ public inline fun recover( * This API offers a similar syntax as the top-level [catch] functions like [Either.catch]. */ @RaiseDSL -public inline fun catch(block: () -> A, catch: (throwable: Throwable) -> A): A = - try { +public inline fun catch(block: () -> A, catch: (throwable: Throwable) -> A): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(catch, AT_MOST_ONCE) + } + return try { block() } catch (t: Throwable) { catch(t.nonFatalOrThrow()) } +} /** * Allows safely catching exceptions of type `T` without capturing [CancellationException], @@ -506,7 +485,7 @@ public inline fun catch(block: () -> A, catch: (throwable: Throwable) -> A): * --> * ```kotlin * fun test() { - * catch({ throw RuntimeException("BOOM") }) { t -> + * catch({ throw RuntimeException("BOOM") }) { _ -> * "fallback" * } shouldBe "fallback" * @@ -527,8 +506,13 @@ public inline fun catch(block: () -> A, catch: (throwable: Throwable) -> A): */ @RaiseDSL @JvmName("catchReified") -public inline fun catch(block: () -> A, catch: (t: T) -> A): A = - catch(block) { t: Throwable -> if (t is T) catch(t) else throw t } +public inline fun catch(block: () -> A, catch: (t: T) -> A): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + callsInPlace(catch, AT_MOST_ONCE) + } + return catch(block) { t: Throwable -> if (t is T) catch(t) else throw t } +} /** * Ensures that the [condition] is met; @@ -702,4 +686,9 @@ public inline fun Raise.withError( @JvmName("_merge") public inline fun merge( @BuilderInference block: Raise.() -> A, -): A = recover(block, ::identity) +): A { + contract { + callsInPlace(block, AT_MOST_ONCE) + } + return recover(block, ::identity) +} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt index 6a826232ba8..e5157fe4a4a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/RaiseAccumulate.kt @@ -10,15 +10,13 @@ import arrow.core.EmptyValue.combine import arrow.core.EmptyValue.unbox import arrow.core.NonEmptyList import arrow.core.NonEmptySet -import arrow.core.Validated -import arrow.core.ValidatedDeprMsg import arrow.core.collectionSizeOrDefault -import arrow.core.ValidatedNel import arrow.core.nonEmptyListOf import arrow.core.toNonEmptyListOrNull import arrow.core.toNonEmptySetOrNull import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_MOST_ONCE +import kotlin.contracts.InvocationKind.EXACTLY_ONCE import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmMultifileClass @@ -767,14 +765,11 @@ public open class RaiseAccumulate( is Either.Right -> value } - @Deprecated(ValidatedDeprMsg, ReplaceWith("toEither().bindNel()")) @RaiseDSL - public fun ValidatedNel.bindNel(): A = when (this) { - is Validated.Invalid -> raise.raise(value) - is Validated.Valid -> value + public inline fun withNel(block: Raise>.() -> A): A { + contract { + callsInPlace(block, EXACTLY_ONCE) + } + return block(raise) } - - @RaiseDSL - public inline fun withNel(block: Raise>.() -> A): A = - block(raise) } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/utils.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/utils.kt index 39a5ca9c66d..eaba8a9b02c 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/utils.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/utils.kt @@ -8,4 +8,3 @@ public fun Predicate.mapNullable(): (T?) -> Boolean = { t -> t?.let public const val DeprecatedUnsafeAccess: String = "This function is unsafe and will be removed in future versions of Arrow. Replace or import `arrow.syntax.unsafe.*` if you wish to continue using it in this way" public const val DeprecatedAmbiguity: String = "This function is ambiguous and will be removed in future versions of Arrow" -public const val DeprecatedWiden: String = "This function is no longer required because of Kotlin's built-in variance and will be removed in future versions of Arrow" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Monoid.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Monoid.kt deleted file mode 100644 index 199ebc177b9..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Monoid.kt +++ /dev/null @@ -1,229 +0,0 @@ -package arrow.typeclasses - -import arrow.core.Const -import arrow.core.Either -import arrow.core.Endo -import arrow.core.None -import arrow.core.Option -import arrow.core.Validated -import arrow.core.combine -import arrow.core.compose -import arrow.core.fold -import arrow.core.identity -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.collections.plus as _plus -import kotlin.sequences.plus as _plus - -public const val MonoidDeprecation: String = - "Monoid is being deprecated, use combine (A, A) -> A lambdas or method references with initial values instead." - -@Deprecated(MonoidDeprecation) -public interface Monoid : Semigroup { - /** - * A zero value for this A - */ - public fun empty(): A - - /** - * Combine an [Collection] of [A] values. - */ - @Deprecated("use fold instead", ReplaceWith("fold()")) - public fun Collection.combineAll(): A = - fold() - - /** - * Combine an array of [A] values. - */ - @Deprecated("use fold instead", ReplaceWith("fold(elems)")) - public fun combineAll(elems: List): A = fold(elems) - - /** - * Fold an [Collection] of [A] values. - */ - public fun Collection.fold(): A = - if (isEmpty()) empty() else reduce { a, b -> a.combine(b) } - - /** - * Fold an array of [A] values. - */ - public fun fold(elems: List): A = elems.fold() - - public companion object { - - @JvmStatic - @JvmName("Boolean") - public fun boolean(): Monoid = AndMonoid - - @JvmStatic - @JvmName("Byte") - public fun byte(): Monoid = ByteMonoid - - @JvmStatic - @JvmName("Integer") - public fun int(): Monoid = IntMonoid - - @JvmStatic - @JvmName("Long") - public fun long(): Monoid = LongMonoid - - @JvmStatic - @JvmName("Short") - public fun short(): Monoid = ShortMonoid - - @JvmStatic - public fun list(): Monoid> = ListMonoid as Monoid> - - @JvmStatic - public fun sequence(): Monoid> = SequenceMonoid as Monoid> - - @JvmStatic - public fun string(): Monoid = StringMonoid - - @JvmStatic - public fun either(SGA: Semigroup, MB: Monoid): Monoid> = - EitherMonoid(SGA, MB) - - @Deprecated("For binary compat", level = DeprecationLevel.HIDDEN) - public fun either(MA: Monoid, MB: Monoid): Monoid> = - EitherMonoid(MA, MB) - - @JvmStatic - public fun endo(): Monoid> = - object : Monoid> { - override fun empty(): Endo = Endo(::identity) - override fun Endo.combine(g: Endo): Endo = Endo(f.compose(g.f)) - } - - @JvmStatic - @JvmName("constant") - public fun const(MA: Monoid): Monoid> = - object : Monoid> { - override fun empty(): Const = Const(MA.empty()) - override fun Const.combine(b: Const): Const = this.combine(MA, b) - } - - @JvmStatic - public fun map(SG: Semigroup): Monoid> = - MapMonoid(SG) - - @JvmStatic - public fun option(MA: Semigroup): Monoid> = - OptionMonoid(MA) - - @JvmStatic - public fun validated(SE: Semigroup, MA: Monoid): Monoid> = - ValidatedMonoid(SE, MA) - - @JvmStatic - public fun pair(MA: Monoid, MB: Monoid): Monoid> = - PairMonoid(MA, MB) - - private class ValidatedMonoid( - private val SA: Semigroup, - private val MB: Monoid - ) : Monoid> { - private val empty = Validated.Valid(MB.empty()) - override fun empty(): Validated = empty - override fun Validated.combine(b: Validated): Validated = - combine(SA, MB, b) - } - - private class OptionMonoid( - private val MA: Semigroup - ) : Monoid> { - - override fun Option.combine(b: Option): Option = - combine(MA, b) - - override fun Option.maybeCombine(b: Option?): Option = - b?.let { combine(MA, it) } ?: this - - override fun empty(): Option = None - } - - private class MapMonoid(private val SG: Semigroup) : Monoid> { - override fun empty(): Map = emptyMap() - - override fun Map.combine(b: Map): Map = - combine(SG, b) - } - - private object AndMonoid : Monoid { - override fun Boolean.combine(b: Boolean): Boolean = this && b - override fun empty(): Boolean = true - } - - private object ByteMonoid : Monoid { - override fun empty(): Byte = 0 - override fun Byte.combine(b: Byte): Byte = (this + b).toByte() - } - - private object DoubleMonoid : Monoid { - override fun empty(): Double = .0 - override fun Double.combine(b: Double): Double = this + b - } - - private object IntMonoid : Monoid { - override fun empty(): Int = 0 - override fun Int.combine(b: Int): Int = this + b - } - - private object LongMonoid : Monoid { - override fun empty(): Long = 0L - override fun Long.combine(b: Long): Long = this + b - } - - private object ShortMonoid : Monoid { - override fun empty(): Short = 0 - override fun Short.combine(b: Short): Short = (this + b).toShort() - } - - private object FloatMonoid : Monoid { - override fun empty(): Float = 0f - override fun Float.combine(b: Float): Float = this + b - } - - private object StringMonoid : Monoid { - override fun String.combine(b: String): String = "${this}$b" - override fun empty(): String = "" - } - - private object ListMonoid : Monoid> { - override fun empty(): List = emptyList() - override fun List.combine(b: List): List = this._plus(b) - } - - private object SequenceMonoid : Monoid> { - override fun empty(): Sequence = emptySequence() - override fun Sequence.combine(b: Sequence): Sequence = this._plus(b) - } - - private class EitherMonoid( - private val SGOL: Semigroup, - private val MOR: Monoid - ) : Monoid> { - override fun empty(): Either = Either.Right(MOR.empty()) - - override fun Either.combine(b: Either): Either = - combine(SGOL, MOR, b) - - override fun Collection>.fold(): Either = - fold(either(SGOL, MOR)) - - override fun fold(elems: List>): Either = - elems.fold(either(SGOL, MOR)) - - override fun Either.maybeCombine(b: Either?): Either = - b?.let { combine(SGOL, MOR, it) } ?: this - } - - private class PairMonoid( - private val MA: Monoid, - private val MB: Monoid - ) : Monoid> { - override fun empty(): Pair = Pair(MA.empty(), MB.empty()) - override fun Pair.combine(b: Pair): Pair = combine(MA, MB, b) - } - } -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semigroup.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semigroup.kt deleted file mode 100644 index 8748ee32aca..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semigroup.kt +++ /dev/null @@ -1,238 +0,0 @@ -package arrow.typeclasses - -import arrow.core.Const -import arrow.core.ConstDeprecation -import arrow.core.Either -import arrow.core.Endo -import arrow.core.Ior -import arrow.core.NonEmptyList -import arrow.core.Option -import arrow.core.Validated -import arrow.core.combine -import arrow.core.compose -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic - -public const val SemigroupDeprecation: String = - "Semigroup is being deprecated, use combine (A, A) -> A lambdas or method references instead." - -@Deprecated(SemigroupDeprecation) -public fun interface Semigroup { - /** - * Combine two [A] values. - */ - public fun A.combine(b: A): A - - public fun append(a: A, b: A): A = - a.combine(b) - - public operator fun A.plus(b: A): A = - this.combine(b) - - public fun A.maybeCombine(b: A?): A = - b?.let { combine(it) } ?: this - - public companion object { - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Lis::plus directly instead.", - ReplaceWith("List::plus") - ) - public fun list(): Semigroup> = Monoid.list() - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Sequence::plus directly instead.", - ReplaceWith("Sequence::plus") - ) - public fun sequence(): Semigroup> = Monoid.sequence() - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use String::plus directly instead.", - ReplaceWith("String::plus") - ) - public fun string(): Semigroup = Monoid.string() - - @JvmStatic - @JvmName("Boolean") - @Deprecated( - "$SemigroupDeprecation. Use Boolean::and directly instead.", - ReplaceWith("Boolean::and") - ) - public fun boolean(): Semigroup = Monoid.boolean() - - @JvmStatic - @JvmName("Byte") - @Deprecated( - "$SemigroupDeprecation. Use Int::plus and toByte directly instead.", - ReplaceWith("{ a, b -> (a + b).toByte() }") - ) - public fun byte(): Semigroup = Monoid.byte() - - @JvmStatic - @JvmName("Integer") - @Deprecated( - "$SemigroupDeprecation. Use Int::plus directly instead.", - ReplaceWith("Int::plus") - ) - public fun int(): Semigroup = Monoid.int() - - @JvmStatic - @JvmName("Long") - @Deprecated( - "$SemigroupDeprecation. Use Long::plus directly instead.", - ReplaceWith("Long::plus") - ) - public fun long(): Semigroup = Monoid.long() - - @JvmStatic - @JvmName("Short") - @Deprecated( - "$SemigroupDeprecation. Use Int::plus and toShort directly instead.", - ReplaceWith("{ a, b -> (a + b).toShort() }") - ) - public fun short(): Semigroup = Monoid.short() - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Either::combine directly instead.", - ReplaceWith("{ a: Either, b: Either -> a.combine(b, {a1, a2 -> a1 + a2}, {b1, b2 -> b1 + b2}) }") - ) - public fun either(SA: Semigroup, SB: Semigroup): Semigroup> = - EitherSemigroup(SA, SB) - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Ior::combine directly instead.", - ReplaceWith("{ a: Ior, b: Ior -> a.combine(b, {a1, a2 -> a1 + a2}, {b1, b2 -> b1 + b2}) }") - ) - public fun ior(SA: Semigroup, SB: Semigroup): Semigroup> = - IorSemigroup(SA, SB) - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use arrow.core.compose directly instead.", - ReplaceWith("{ f, g -> f.compose(g.f) }") - ) - public fun endo(): Semigroup> = - Semigroup { g -> Endo(f.compose(g.f)) } - - @JvmStatic - @JvmName("constant") - @Deprecated(ConstDeprecation) - public fun const(SA: Semigroup): Semigroup> = - Semigroup { b -> this.combine(SA, b) } - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Map::combine directly instead.", - ReplaceWith( - "{ a: Map, b: Map -> a.combine(b, SG::combine) }", - "arrow.core.combine" - ) - ) - public fun map(SG: Semigroup): Semigroup> = - MapSemigroup(SG) - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Option::combine directly instead.", - ReplaceWith( - "{ a: Option, b: Option -> a.combine(b, SGA::combine) }", - "arrow.core.combine" - ) - ) - public fun option(SGA: Semigroup): Semigroup> = - OptionSemigroup(SGA) - - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use Validated::combine directly instead.", - ReplaceWith( - "{ a: Validated, b: Validated -> a.combine(b, SE, SA) }", - "arrow.core.combine" - ) - ) - public fun validated(SE: Semigroup, SA: Semigroup): Semigroup> = - ValidatedSemigroup(SE, SA) - - @Suppress("UNCHECKED_CAST") - @JvmStatic - @Deprecated( - "$SemigroupDeprecation. Use NonEmptyPlus::plus directly instead.", - ReplaceWith("NonEmptyList::plus", "arrow.core.plus") - ) - public fun nonEmptyList(): Semigroup> = - NonEmptyListSemigroup as Semigroup> - - @JvmStatic - public fun pair(SA: Semigroup, SB: Semigroup): Semigroup> = - PairSemigroup(SA, SB) - - private open class PairSemigroup( - private val SA: Semigroup, - private val SB: Semigroup - ) : Semigroup> { - override fun Pair.combine(b: Pair): Pair = combine(SA, SB, b) - } - - public object NonEmptyListSemigroup : Semigroup> { - override fun NonEmptyList.combine(b: NonEmptyList): NonEmptyList = - NonEmptyList(this.head, this.tail.plus(b)) - } - - private open class ValidatedSemigroup( - private val SA: Semigroup, - private val SB: Semigroup - ) : Semigroup> { - override fun Validated.combine(b: Validated): Validated = - combine(SA, SB, b) - } - - private class OptionSemigroup( - private val SGA: Semigroup - ) : Semigroup> { - - override fun Option.combine(b: Option): Option = - combine(SGA, b) - - override fun Option.maybeCombine(b: Option?): Option = - b?.let { combine(SGA, it) } ?: this - } - - private class MapSemigroup(private val SG: Semigroup) : Semigroup> { - override fun Map.combine(b: Map): Map = - combine(SG, b) - } - - private open class EitherSemigroup( - private val SGL: Semigroup, - private val SGR: Semigroup - ) : Semigroup> { - - override fun Either.combine(b: Either): Either = - combine(SGL, SGR, b) - - override fun Either.maybeCombine(b: Either?): Either = - b?.let { combine(SGL, SGR, it) } ?: this - } - - private class IorSemigroup( - private val SGA: Semigroup, - private val SGB: Semigroup - ) : Semigroup> { - - override fun Ior.combine(b: Ior): Ior = - combine(SGA, SGB, b) - - override fun Ior.maybeCombine(b: Ior?): Ior = - b?.let { combine(SGA, SGB, it) } ?: this - } - } -} - -@Deprecated(SemigroupDeprecation) -public fun Semigroup.combine(a: A, b: A): A = - a.combine(b) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semiring.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semiring.kt deleted file mode 100644 index 7ff3da0dddf..00000000000 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/typeclasses/Semiring.kt +++ /dev/null @@ -1,194 +0,0 @@ -package arrow.typeclasses - -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic - -public const val FloatInstanceDeprecation: String = - "Float instances for Semigroup/Monoid & Semiring are deprecated. Due to how equality of floating-point numbers work, they're not lawful under equality." - -public const val DoubleInstanceDeprecation: String = - "Double instances for Semigroup/Monoid & Semiring are deprecated. Due to how equality of floating-point numbers work, they're not lawful under equality." - -public const val SemiringDeprecation: String = - "Semiring is being deprecated." - -/** - * The [Semiring] type class for a given type `A` combines both a commutative additive [Monoid] and a multiplicative [Monoid]. - * It requires the multiplicative [Monoid] to distribute over the additive one. The operations of the multiplicative [Monoid] have been renamed to - * [one] and [combineMultiplicate] for easier use. - * - * The [one] function serves exactly like the [empty] function for an additive [Monoid], just adapted for the multiplicative - * version. This forms the following law: - * - * Please note that the empty function has been renamed to [zero] to get a consistent naming style inside the semiring. - * - * Currently, [Semiring] instances are defined for all available number types. - * - * ### Examples - * - * Here a some examples: - * - * ```kotlin - * import arrow.typeclasses.Semiring - * - * fun main(args: Array) { - * val result = - * //sampleStart - * Semiring.int().run { 1.combine(2) } - * //sampleEnd - * println(result) - * } - * ``` - * - * - * ```kotlin - * import arrow.typeclasses.Semiring - * - * fun main(args: Array) { - * val result = - * //sampleStart - * Semiring.int().run { 2.combineMultiplicate(3) } - * //sampleEnd - * println(result) - * } - * ``` - * - * - * The type class `Semiring` also has support for the `+` `*` syntax: - * - * ```kotlin - * import arrow.typeclasses.Semiring - * - * fun main(args: Array) { - * val result = - * //sampleStart - * Semiring.int().run { - * 1 + 2 - * } - * //sampleEnd - * println(result) - * } - * ``` - * - * - * ```kotlin - * import arrow.typeclasses.Semiring - * - * fun main(args: Array) { - * val result = - * //sampleStart - * Semiring.int().run { - * 2 * 3 - * } - * //sampleEnd - * println(result) - * } - * ``` - * - */ -@Deprecated(SemiringDeprecation) -public interface Semiring { - - /** - * A zero value for this A - */ - public fun zero(): A - - /** - * A one value for this A - */ - public fun one(): A - - public fun A.combine(b: A): A - - public operator fun A.plus(b: A): A = - combine(b) - - /** - * Multiplicatively combine two [A] values. - */ - public fun A.combineMultiplicate(b: A): A - - public operator fun A.times(b: A): A = - this.combineMultiplicate(b) - - /** - * Maybe additively combine two [A] values. - */ - public fun A?.maybeCombineAddition(b: A?): A = - if (this == null) zero() - else b?.let { combine(it) } ?: this - - /** - * Maybe multiplicatively combine two [A] values. - */ - public fun A?.maybeCombineMultiplicate(b: A?): A = - if (this == null) one() - else b?.let { combineMultiplicate(it) } ?: this - - public companion object { - @JvmStatic - @JvmName("Short") - public fun short(): Semiring = ShortSemiring - - @JvmStatic - @JvmName("Long") - public fun long(): Semiring = LongSemiring - - @JvmStatic - @JvmName("Integer") - public fun int(): Semiring = IntSemiring - - @JvmStatic - @JvmName("Byte") - public fun byte(): Semiring = ByteSemiring - - private object ByteSemiring : Semiring { - override fun one(): Byte = 1 - override fun zero(): Byte = 0 - - override fun Byte.combine(b: Byte): Byte = (this + b).toByte() - override fun Byte.combineMultiplicate(b: Byte): Byte = (this * b).toByte() - } - - private object DoubleSemiring : Semiring { - override fun one(): Double = 1.0 - override fun zero(): Double = 0.0 - - override fun Double.combine(b: Double): Double = this + b - override fun Double.combineMultiplicate(b: Double): Double = this * b - } - - private object IntSemiring : Semiring { - override fun one(): Int = 1 - override fun zero(): Int = 0 - - override fun Int.combine(b: Int): Int = this + b - override fun Int.combineMultiplicate(b: Int): Int = this * b - } - - private object LongSemiring : Semiring { - override fun one(): Long = 1 - override fun zero(): Long = 0 - - override fun Long.combine(b: Long): Long = this + b - override fun Long.combineMultiplicate(b: Long): Long = this * b - } - - private object ShortSemiring : Semiring { - override fun one(): Short = 1 - override fun zero(): Short = 0 - - override fun Short.combine(b: Short): Short = (this + b).toShort() - override fun Short.combineMultiplicate(b: Short): Short = (this * b).toShort() - } - - private object FloatSemiring : Semiring { - override fun one(): Float = 1f - override fun zero(): Float = 0f - - override fun Float.combine(b: Float): Float = this + b - override fun Float.combineMultiplicate(b: Float): Float = this * b - } - } -} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/BooleanTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/BooleanTest.kt index b53fa2bc8e6..1ee68bcbcb8 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/BooleanTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/BooleanTest.kt @@ -2,12 +2,13 @@ package arrow.core import arrow.core.test.laws.MonoidLaws import arrow.core.test.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean +import kotlin.test.Test -class BooleanTest : StringSpec({ +class BooleanTest{ + @Test fun monoidLaws() = testLaws( MonoidLaws("Boolean", true, { x, y -> x && y }, Arb.boolean()) ) -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CollectionsSyntaxTests.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CollectionsSyntaxTests.kt index 27a6975fc6b..3ce6f5bd96b 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CollectionsSyntaxTests.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CollectionsSyntaxTests.kt @@ -16,21 +16,22 @@ package arrow.core -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class CollectionsSyntaxTests : StringSpec({ - "tail" { +class CollectionsSyntaxTests { + @Test fun tail() = runTest { listOf(1, 2, 3).tail() shouldBe listOf(2, 3) } - "prependTo" { + @Test fun prependTo() = runTest { 1 prependTo listOf(2, 3) shouldBe listOf(1, 2, 3) } - "destructured" { + @Test fun destructured() = runTest { val (head, tail) = listOf(1, 2, 3).let { it.first() to it.tail() } head shouldBe 1 tail shouldBe listOf(2, 3) } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ComparisonKtTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ComparisonKtTest.kt index 4f40b9b0d06..bde7a4b8ba4 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ComparisonKtTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ComparisonKtTest.kt @@ -1,7 +1,6 @@ package arrow.core import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.checkAll import io.kotest.matchers.shouldBe @@ -12,6 +11,8 @@ import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.short import io.kotest.property.arbitrary.string +import kotlinx.coroutines.test.runTest +import kotlin.test.Test data class Person(val age: Int, val name: String) : Comparable { companion object { @@ -27,10 +28,10 @@ data class Person(val age: Int, val name: String) : Comparable { } fun Arb.Companion.person(): Arb = - Arb.bind(Arb.int(), Arb.string(), ::Person) + Arb.bind(Arb.int(0, 100), Arb.string(0 .. 10), ::Person) -class ComparisonKtTest : StringSpec({ - "Arberic - sort2" { +class ComparisonKtTest { + @Test fun arbericSort2() = runTest { checkAll(Arb.person(), Arb.person()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -42,7 +43,7 @@ class ComparisonKtTest : StringSpec({ } } - "Arberic - sort3" { + @Test fun arbericSort3() = runTest { checkAll(Arb.person(), Arb.person(), Arb.person()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -55,8 +56,8 @@ class ComparisonKtTest : StringSpec({ } } - "Arberic - sortAll" { - checkAll(Arb.person(), Arb.list(Arb.person(), 0..50)) { a, lst -> + @Test fun arbericSortAll() = runTest { + checkAll(Arb.person(), Arb.list(Arb.person(), 0..20)) { a, lst -> val aas = lst.toTypedArray() val res = sort(a, *aas) val expected = listOf(a, *aas).sorted() @@ -65,7 +66,7 @@ class ComparisonKtTest : StringSpec({ } } - "Arberic - comparator - sort2" { + @Test fun arbericComparatorSort2() = runTest { checkAll(Arb.person(), Arb.person()) { a, b -> val (first, second) = sort(a, b, Person.comparator) val (aa, bb) = listOf(a, b).sorted() @@ -77,7 +78,7 @@ class ComparisonKtTest : StringSpec({ } } - "Arberic - comparator - sort3" { + @Test fun arbericComparatorSort3() = runTest { checkAll(Arb.person(), Arb.person(), Arb.person()) { a, b, c -> val (first, second, third) = sort(a, b, c, Person.comparator) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -90,7 +91,7 @@ class ComparisonKtTest : StringSpec({ } } - "Byte - sort2" { + @Test fun byteSort2() = runTest { checkAll(Arb.byte(), Arb.byte()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -102,7 +103,7 @@ class ComparisonKtTest : StringSpec({ } } - "Byte - sort3" { + @Test fun byteSort3() = runTest { checkAll(Arb.byte(), Arb.byte(), Arb.byte()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -115,7 +116,7 @@ class ComparisonKtTest : StringSpec({ } } - "Byte - sortAll" { + @Test fun byteSortAll() = runTest { checkAll(Arb.byte(), Arb.byte(), Arb.byte(), Arb.byte()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() @@ -124,7 +125,7 @@ class ComparisonKtTest : StringSpec({ } } - "Short - sort2" { + @Test fun shortSort2() = runTest { checkAll(Arb.short(), Arb.short()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -136,7 +137,7 @@ class ComparisonKtTest : StringSpec({ } } - "Short - sort3" { + @Test fun shortSort3() = runTest { checkAll(Arb.short(), Arb.short(), Arb.short()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -149,7 +150,7 @@ class ComparisonKtTest : StringSpec({ } } - "Short - sortAll" { + @Test fun shortSortAll() = runTest { checkAll(Arb.short(), Arb.short(), Arb.short(), Arb.short()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() @@ -157,8 +158,8 @@ class ComparisonKtTest : StringSpec({ res shouldBe expected } } - - "Int - sort2" { + + @Test fun intSort2() = runTest { checkAll(Arb.int(), Arb.int()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -168,7 +169,7 @@ class ComparisonKtTest : StringSpec({ } } - "Int - sort3" { + @Test fun intSort3() = runTest { checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -181,7 +182,7 @@ class ComparisonKtTest : StringSpec({ } } - "Int - sortAll" { + @Test fun intSortAll() = runTest { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() @@ -190,7 +191,7 @@ class ComparisonKtTest : StringSpec({ } } - "Long - sort2" { + @Test fun longSort2() = runTest { checkAll(Arb.long(), Arb.long()) { a, b -> val (first, second) = sort(a, b) val (aa, bb) = listOf(a, b).sorted() @@ -202,7 +203,7 @@ class ComparisonKtTest : StringSpec({ } } - "Long - sort3" { + @Test fun longSort3() = runTest { checkAll(Arb.long(), Arb.long(), Arb.long()) { a, b, c -> val (first, second, third) = sort(a, b, c) val (aa, bb, cc) = listOf(a, b, c).sorted() @@ -215,7 +216,7 @@ class ComparisonKtTest : StringSpec({ } } - "Long - sortAll" { + @Test fun longSortAll() = runTest { checkAll(Arb.long(), Arb.long(), Arb.long(), Arb.long()) { a, b, c, d -> val res = sort(a, b, c, d) val expected = listOf(a, b, c, d).sorted() @@ -223,4 +224,4 @@ class ComparisonKtTest : StringSpec({ res shouldBe expected } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt index 655a3a8ce54..8e570bcec97 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EitherTest.kt @@ -2,20 +2,12 @@ package arrow.core import arrow.core.Either.Left import arrow.core.Either.Right -import arrow.core.test.any import arrow.core.test.either import arrow.core.test.intSmall import arrow.core.test.laws.MonoidLaws import arrow.core.test.nonEmptyList -import arrow.core.test.suspendFunThatReturnsAnyLeft -import arrow.core.test.suspendFunThatReturnsAnyRight -import arrow.core.test.suspendFunThatReturnsEitherAnyOrAnyOrThrows -import arrow.core.test.suspendFunThatThrows import arrow.core.test.testLaws -import arrow.typeclasses.Monoid import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean @@ -24,594 +16,204 @@ import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.double import io.kotest.property.arbitrary.float import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.nonPositiveInt import io.kotest.property.arbitrary.short import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class EitherTest : StringSpec({ +class EitherTest { val ARB = Arb.either(Arb.string(), Arb.int()) + @Test + fun monoidLaws() = testLaws( MonoidLaws("Either", 0.right(), { x, y -> x.combine(y, String::plus, Int::plus) }, ARB) ) - "isLeft should return true if Left and false if Right" { - checkAll(Arb.int()) { a: Int -> - val x = Left(a) - if (x.isLeft()) x.value shouldBe a - else fail("Left(a).isLeft() cannot be false") - x.isRight() shouldBe false - } - } - - "isRight should return false if Left and true if Right" { - checkAll(Arb.int()) { a: Int -> - val x = Right(a) - if (x.isRight()) x.value shouldBe a - else fail("Right(a).isRight() cannot be false") - x.isLeft() shouldBe false - } - } - - "tap applies effects returning the original value" { - checkAll(Arb.either(Arb.long(), Arb.int())) { either -> - var effect = 0 - val res = either.tap { effect += 1 } - val expected = when (either) { - is Left -> 0 - is Right -> 1 - } - effect shouldBe expected - res shouldBe either - } - } - - "tapLeft applies effects returning the original value" { - checkAll(Arb.either(Arb.long(), Arb.int())) { either -> - var effect = 0 - val res = either.tapLeft { effect += 1 } - val expected = when (either) { - is Left -> 1 - is Right -> 0 - } - effect shouldBe expected - res shouldBe either - } - } - - "fold should apply first op if Left and second op if Right" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.fold({ it + 2 }, { it + 1 }) shouldBe a + 1 - left.fold({ it + 2 }, { it + 1 }) shouldBe b + 2 - } - } - - "foldLeft should return initial if Left and apply op if Right" { - checkAll(Arb.intSmall(), Arb.intSmall(), Arb.intSmall()) { a, b, c -> - Right(a).foldLeft(c, Int::plus) shouldBe c + a - Left(b).foldLeft(c, Int::plus) shouldBe c - } - } - - "foldMap should return the empty of the inner type if Left and apply op if Right" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val left: Either = Left(b) - - Right(a).foldMap(Monoid.int()) { it + 1 } shouldBe a + 1 - left.foldMap(Monoid.int()) { it + 1 } shouldBe Monoid.int().empty() - } - } - - "bifoldLeft should apply first op if Left and apply second op if Right" { - checkAll(Arb.intSmall(), Arb.intSmall(), Arb.intSmall()) { a, b, c -> - Right(a).bifoldLeft(c, Int::plus, Int::times) shouldBe a * c - Left(b).bifoldLeft(c, Int::plus, Int::times) shouldBe b + c - } - } - - "bifoldMap should apply first op if Left and apply second op if Right" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) shouldBe a + 1 - left.bifoldMap(Monoid.int(), { it + 2 }, { it + 1 }) shouldBe b + 2 - } - } - - "fromNullable should lift value as a Right if it is not null" { - checkAll(Arb.int()) { a: Int -> - Either.fromNullable(a) shouldBe Right(a) - } - } - - "fromNullable should lift value as a Left(Unit) if it is null" { - Either.fromNullable(null) shouldBe Left(Unit) - } - - "empty should return a Right of the empty of the inner type" { - Right(Monoid.string().empty()) shouldBe Monoid.either(Monoid.string(), Monoid.string()).empty() - } - - "combine two rights should return a right of the combine of the inners" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - Monoid.string().run { Right(a.combine(b)) } shouldBe Right(a).combine( - Monoid.string(), - Monoid.string(), - Right(b) - ) - } - } - - "combine two lefts should return a left of the combine of the inners" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - Monoid.string().run { Left(a.combine(b)) } shouldBe Left(a).combine(Monoid.string(), Monoid.string(), Left(b)) - } - } - - "combine a right and a left should return left" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - Left(a) shouldBe Left(a).combine(Monoid.string(), Monoid.string(), Right(b)) - Left(a) shouldBe Right(b).combine(Monoid.string(), Monoid.string(), Left(a)) - } - } - - "getOrElse should return value" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - Right(a).getOrElse { b } shouldBe a - Left(a).getOrElse { b } shouldBe b - } - } - - "orNull should return value" { - checkAll(Arb.int()) { a: Int -> - Right(a).orNull() shouldBe a - } - } - - "orNone should return Some(value)" { - checkAll(Arb.int()) { a: Int -> - Right(a).orNone() shouldBe Some(a) - } - } - - "orNone should return None when left" { - checkAll(Arb.string()) { a: String -> - Left(a).orNone() shouldBe None - } - } - - "getOrHandle should return value" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - Right(a).getOrHandle { b } shouldBe a - Left(a).getOrHandle { it + b } shouldBe a + b - } - } - - "filterOrElse should filter values" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val left: Either = Left(a) - - Right(a).filterOrElse({ it > a - 1 }, { b }) shouldBe Right(a) - Right(a).filterOrElse({ it > a + 1 }, { b }) shouldBe Left(b) - left.filterOrElse({ it > a - 1 }, { b }) shouldBe Left(a) - left.filterOrElse({ it > a + 1 }, { b }) shouldBe Left(a) - } - } - - "filterOrOther should filter values" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val left: Either = Left(a) - - Right(a).filterOrOther({ it > a - 1 }, { b + a }) shouldBe Right(a) - Right(a).filterOrOther({ it > a + 1 }, { b + a }) shouldBe Left(b + a) - left.filterOrOther({ it > a - 1 }, { b + a }) shouldBe Left(a) - left.filterOrOther({ it > a + 1 }, { b + a }) shouldBe Left(a) - } - } - - "leftIfNull should return Left if Right value is null of if Either is Left" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - Right(a).leftIfNull { b } shouldBe Right(a) - Right(null).leftIfNull { b } shouldBe Left(b) - Left(a).leftIfNull { b } shouldBe Left(a) - } - } - - "exists should apply predicate to Right only" { - checkAll(Arb.intSmall()) { a -> - val left: Either = Left(a) - - Right(a).exists { it > a - 1 } shouldBe true - !Right(a).exists { it > a + 1 } shouldBe true - !left.exists { it > a - 1 } shouldBe true - !left.exists { it > a + 1 } shouldBe true - } - } - - "rightIfNotNull should return Left if value is null or Right of value when not null" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - null.rightIfNotNull { b } shouldBe Left(b) - a.rightIfNotNull { b } shouldBe Right(a) - } - } - - "rightIfNull should return Left if value is not null or Right of value when null" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - a.rightIfNull { b } shouldBe Left(b) - null.rightIfNull { b } shouldBe Right(null) - } - } - - "swap should interchange values" { - checkAll(Arb.int()) { a: Int -> - Left(a).swap() shouldBe Right(a) - Right(a).swap() shouldBe Left(a) - } - } - - "orNull should convert" { - checkAll(Arb.int()) { a: Int -> - val left: Either = Left(a) - - Right(a).orNull() shouldBe a - left.orNull() shouldBe null - } - } - - "contains should check value" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - require(Right(a).contains(a)) { "Expected ${Right(a)}.contains($a) to be true, but it was false." } - if (a != b) require(!Right(a).contains(b)) { "Expected ${Right(a)}.contains($b) to be false, but it was true." } - else require(Right(a).contains(b)) { "Expected ${Right(a)}.contains($b) to be true, but it was false." } - require(!Left(a).contains(a)) { "Expected ${Left(a)}.contains($a) to be false, but it was true." } - } - } - - "map should alter right instance only" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.map { it + 1 } shouldBe Right(a + 1) - left.map { it + 1 } shouldBe left - } - } - - "mapLeft should alter left instance only" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.mapLeft { it + 1 } shouldBe right - left.mapLeft { it + 1 } shouldBe Left(b + 1) - } - } - - "bimap should alter left or right instance accordingly" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.bimap({ it + 2 }, { it + 1 }) shouldBe Right(a + 1) - left.bimap({ it + 2 }, { it + 1 }) shouldBe Left(b + 2) - } - } - - "replicate should return Right(empty list) when n <= 0" { - checkAll( - Arb.nonPositiveInt(), - Arb.int(0..100) - ) { n: Int, a: Int -> - val expected: Either> = Right(emptyList()) - - Right(a).replicate(n) shouldBe expected - - - Left(a).replicate(n) shouldBe expected - } - } - - "replicate should return Right(list of repeated value size n) when Right and n is positive" { - checkAll( - Arb.int(1..10), - Arb.int() - ) { n: Int, a: Int -> - Right(a).replicate(n) shouldBe Right(List(n) { a }) - Left(a).replicate(n) shouldBe Left(a) - } + @Test + fun leftIsLeftIsRight() = runTest { + checkAll(Arb.int()) { a: Int -> + val x = Left(a) + if (x.isLeft()) x.value shouldBe a + else fail("Left(a).isLeft() cannot be false") + x.isRight() shouldBe false } - - "traverse should return list of Right when Right and singleton list when Left" { - checkAll( - Arb.int(), - Arb.int(), - Arb.int() - ) { a: Int, b: Int, c: Int -> - Right(a).traverse { emptyList() } shouldBe emptyList() - Right(a).traverse { listOf(b, c) } shouldBe listOf(Right(b), Right(c)) - Left(a).traverse { listOf(b, c) } shouldBe listOf(Left(a)) - } - } - - "flatMap should map right instance only" { - checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> - val right: Either = Right(a) - val left: Either = Left(b) - - right.flatMap { Right(it + 1) } shouldBe Right(a + 1) - left.flatMap { Right(it + 1) } shouldBe left - } + } + + @Test + fun rightIsLeftIsRight() = runTest { + checkAll(Arb.int()) { a: Int -> + val x = Right(a) + if (x.isRight()) x.value shouldBe a + else fail("Right(a).isRight() cannot be false") + x.isLeft() shouldBe false } - - "conditionally should create right instance only if test is true" { - checkAll(Arb.boolean(), Arb.int(), Arb.string()) { t: Boolean, i: Int, s: String -> - val expected = if (t) Right(i) else Left(s) - Either.conditionally(t, { s }, { i }) shouldBe expected - } + } + + @Test + fun tapAppliesEffects() = runTest { + checkAll(Arb.either(Arb.long(), Arb.int())) { either -> + var effect = 0 + val res = either.onRight { effect += 1 } + val expected = when (either) { + is Left -> 0 + is Right -> 1 + } + effect shouldBe expected + res shouldBe either } - - "handleErrorWith should handle left instance otherwise return Right" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - Left(a).handleErrorWith { Right(b) } shouldBe Right(b) - Right(a).handleErrorWith { Right(b) } shouldBe Right(a) - Left(a).handleErrorWith { Left(b) } shouldBe Left(b) - } + } + + @Test + fun tapLeftAppliesEffects() = runTest { + checkAll(Arb.either(Arb.long(), Arb.int())) { either -> + var effect = 0 + val res = either.onLeft { effect += 1 } + val expected = when (either) { + is Left -> 1 + is Right -> 0 + } + effect shouldBe expected + res shouldBe either } - - "catch should return Right(result) when f does not throw" { - Either.catch { 1 } shouldBe Right(1) + } + + @Test + fun foldOk() = runTest { + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> + val right: Either = Right(a) + val left: Either = Left(b) + + right.fold({ it + 2 }, { it + 1 }) shouldBe a + 1 + left.fold({ it + 2 }, { it + 1 }) shouldBe b + 2 } - - "catch should return Left(result) when f throws" { - val exception = Exception("Boom!") - Either.catch { throw exception } shouldBe Left(exception) + } + + @Test + fun combineTwoRights() = runTest { + checkAll(Arb.string(), Arb.string()) { a: String, b: String -> + Right(a + b) shouldBe Right(a).combine( + Right(b), + Int::plus, + String::plus + ) } - - "catchAndFlatten should return Right(result) when f does not throw" { - Either.catchAndFlatten { Right(1) } shouldBe Right(1) + } + + @Test + fun combineTwoLefts() = runTest { + checkAll(Arb.string(), Arb.string()) { a: String, b: String -> + Left(a + b) shouldBe Left(a).combine( + Left(b), + String::plus, + Int::plus + ) } - - "catchAndFlatten should return Left(result) when f throws" { - val exception = Exception("Boom!") - Either.catchAndFlatten { throw exception } shouldBe Left(exception) + } + + @Test + fun combineRightLeft() = runTest { + checkAll(Arb.string(), Arb.string()) { a: String, b: String -> + Left(a) shouldBe Left(a).combine(Right(b), String::plus, String::plus) + Left(a) shouldBe Right(b).combine(Left(a), String::plus, String::plus) } - - "resolve should yield a result when deterministic functions are used as handlers" { - checkAll( - Arb.suspendFunThatReturnsEitherAnyOrAnyOrThrows(), - Arb.any() - ) { f: suspend () -> Either, returnObject: Any -> - val result = - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result shouldBe returnObject - } + } + + @Test + fun getOrElseOk() = runTest { + checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> + Right(a).getOrElse { b } shouldBe a + Left(a).getOrElse { b } shouldBe b } - - "resolve should yield a result when an exception is thrown in the success supplied function" { - checkAll( - Arb.suspendFunThatReturnsAnyRight(), - Arb.any() - ) { f: suspend () -> Either, returnObject: Any -> - val result = - Either.resolve( - f = { f() }, - success = { throwException(it) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result shouldBe returnObject - } + } + + @Test + fun getOrNullOk() = runTest { + checkAll(Arb.int()) { a: Int -> + Right(a).getOrNull() shouldBe a } - - "resolve should yield a result when an exception is thrown in the error supplied function" { - checkAll( - Arb.suspendFunThatReturnsAnyLeft(), - Arb.any() - ) { f: suspend () -> Either, returnObject: Any -> - val result = - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { throwException(it) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - result shouldBe returnObject - } + } + + @Test + fun getOrNoneRight() = runTest { + checkAll(Arb.int()) { a: Int -> + Right(a).getOrNone() shouldBe Some(a) } - - "resolve should throw a Throwable when any exception is thrown in the throwable supplied function" { - checkAll( - Arb.suspendFunThatThrows() - ) { f: suspend () -> Either -> - shouldThrow { - Either.resolve( - f = { f() }, - success = { throwException(it) }, - error = { throwException(it) }, - throwable = { throwException(it) }, - unrecoverableState = { handleWithPureFunction(it) } - ) - } - } + } + + @Test + fun getOrNoneLeft() = runTest { + checkAll(Arb.string()) { a: String -> + Left(a).getOrNone() shouldBe None } + } - "combine should combine 2 eithers" { - checkAll(Arb.either(Arb.string(), Arb.int()), Arb.either(Arb.string(), Arb.int())) { e1, e2 -> - val obtained = e1.combine(e2, { l1, l2 -> l1 + l2 }, { r1, r2 -> r1 + r2 }) - val expected = when(e1){ - is Left -> when(e2) { - is Left -> Left(e1.value + e2.value) - is Right -> e1 - } - is Right -> when(e2) { - is Left -> e2 - is Right -> Right(e1.value + e2.value) - } - } - obtained shouldBe expected - } + @Test + fun swapOk() = runTest { + checkAll(Arb.int()) { a: Int -> + Left(a).swap() shouldBe Right(a) + Right(a).swap() shouldBe Left(a) } + } + @Test + fun mapOnlyRight() = runTest { + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> + val right: Either = Right(a) + val left: Either = Left(b) - "combineAll replacement should work " { - checkAll(Arb.list(Arb.either(Arb.string(), Arb.int()))) { list -> - val obtained = list.fold, Either>(0.right()) { x, y -> - Either.zipOrAccumulate( - { a1, a2 -> a1 + a2 }, - x, - y, - { b1, b2 -> b1 + b2 }) - } - val expected = list.combineAll(Monoid.string(), Monoid.int()) - obtained shouldBe expected + right.map { it + 1 } shouldBe Right(a + 1) + left.map { it + 1 } shouldBe left } } + @Test + fun mapLeftOnlyLeft() = runTest { + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> + val right: Either = Right(a) + val left: Either = Left(b) - - "traverse should return list if either is right" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.traverse { listOf(it, 2, 3) } shouldBe listOf(Right(1), Right(2), Right(3)) - left.traverse { listOf(it, 2, 3) } shouldBe listOf(left) - } - - "sequence should be consistent with traverse" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.map { listOf(it) }.sequence() shouldBe either.traverse { listOf(it) } - } - } - - "traverseNullable should return non-nullable if either is right" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.traverseNullable { it } shouldBe Right(1) - right.traverseNullable { null } shouldBe null - left.traverseNullable { it } shouldBe left - } - - "sequence for Nullable should be consistent with traverseNullable" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.map { it }.sequence() shouldBe either.traverseNullable { it } - // wrong! if you map a `Left`, you should get a `Left` back, not null - // either.map { null }.sequence() shouldBe null - } - } - - "traverse for Option should return option if either is right" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.traverse { Some(it) } shouldBe Some(Right(1)) - right.traverse { None } shouldBe None - left.traverse { Some(it) } shouldBe Some(left) - left.traverse { None } shouldBe Some(left) - } - - "sequence for Option should be consistent with traverseOption" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.map { Some(it) }.sequence() shouldBe either.traverse { Some(it) } - } - } - - "traverse for Validated should return validated of either" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.traverse { it.valid() } shouldBe Valid(Right(1)) - left.traverse { it.valid() } shouldBe Valid(Left("foo")) - } - - "sequence for Validated should be consistent with traverseValidated" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.map { it.valid() }.sequence() shouldBe either.traverse { it.valid() } - } - } - - "bitraverse should wrap either in a list" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.bitraverse({ listOf(it, "bar", "baz") }, { listOf(it, 2, 3) }) shouldBe listOf(Right(1), Right(2), Right(3)) - left.bitraverse({ listOf(it, "bar", "baz") }, { listOf(it, 2, 3) }) shouldBe - listOf(Left("foo"), Left("bar"), Left("baz")) - } - - "bisequence should be consistent with bitraverse" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe either.bitraverse( - { listOf(it) }, - { listOf(it) }) - } - } - - "bitraverseNullable should wrap either in a nullable" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.bitraverseNullable({ it }, { it.toString() }) shouldBe Right("1") - left.bitraverseNullable({ it }, { it.toString() }) shouldBe Left("foo") - - right.bitraverseNullable({ it }, { null }) shouldBe null - left.bitraverseNullable({ null }, { it.toString() }) shouldBe null - } - - "bisequenceNullable should be consistent with bitraverseNullable" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.bimap({ it }, { it }).bisequenceNullable() shouldBe - either.bitraverseNullable({ it }, { it }) - } + right.mapLeft { it + 1 } shouldBe right + left.mapLeft { it + 1 } shouldBe Left(b + 1) } - - "bitraverseOption should wrap either in an option" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.bitraverseOption({ Some(it) }, { Some(it.toString()) }) shouldBe Some(Right("1")) - left.bitraverseOption({ Some(it) }, { Some(it.toString()) }) shouldBe Some(Left("foo")) - } - - "bisequenceOption should be consistent with bitraverseOption" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe - either.bitraverseOption({ Some(it) }, { Some(it) }) - } - } - - "bitraverseValidated should return validated of either" { - val right: Either = Right(1) - val left: Either = Left("foo") - - right.bitraverseValidated({ it.invalid() }, { it.valid() }) shouldBe Valid(Right(1)) - left.bitraverseValidated({ it.invalid() }, { it.valid() }) shouldBe Invalid("foo") + } + + @Test + fun flatMapOnlyRight() = runTest { + checkAll(Arb.intSmall(), Arb.intSmall()) { a, b -> + val right: Either = Right(a) + val left: Either = Left(b) + + right.flatMap { Right(it + 1) } shouldBe Right(a + 1) + left.flatMap { Right(it + 1) } shouldBe left } - - "bisequenceValidated should be consistent with bitraverseValidated" { - checkAll(Arb.either(Arb.string(), Arb.int())) { either -> - either.bimap({ it.invalid() }, { it.valid() }).bisequenceValidated() shouldBe - either.bitraverseValidated({ it.invalid() }, { it.valid() }) - } + } + + @Test + fun handleErrorWithOk() = runTest { + checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> + Left(a).recover { Right(b).bind() } shouldBe Right(b) + Right(a).recover { Right(a + 1).bind() } shouldBe Right(a) + Left(a).recover { Left(b).bind() } shouldBe Left(b) } + } + + @Test + fun catchRight() = runTest { + Either.catch { 1 } shouldBe Right(1) + } + + @Test + fun catchLeft() = runTest { + val exception = Exception("Boom!") + Either.catch { throw exception } shouldBe Left(exception) + } - "zipOrAccumulate results in all Right transformed, or all Left combined according to combine" { + @Test + fun zipOrAccumulateList() = runTest { checkAll( Arb.either(Arb.string(), Arb.short()), Arb.either(Arb.string(), Arb.byte()), @@ -638,7 +240,8 @@ class EitherTest : StringSpec({ } } - "zipOrAccumulate without Semigroup results in all Right transformed, or all Left in a NonEmptyList" { + @Test + fun zipOrAccumulateSemigroup() = runTest { checkAll( Arb.either(Arb.string(), Arb.short()), Arb.either(Arb.string(), Arb.byte()), @@ -665,7 +268,8 @@ class EitherTest : StringSpec({ } } - "zipOrAccumulate EitherNel results in all Right transformed, or all Left in a NonEmptyList" { + @Test + fun zipOrAccumulateEitherNel() = runTest { checkAll( Arb.either(Arb.nonEmptyList(Arb.int()), Arb.short()), Arb.either(Arb.nonEmptyList(Arb.int()), Arb.byte()), @@ -693,18 +297,4 @@ class EitherTest : StringSpec({ res shouldBe expected } } -}) - -@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER") -suspend fun handleWithPureFunction(a: Any, b: Any): Either = - b.right() - -@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER") -suspend fun handleWithPureFunction(throwable: Throwable): Either = - Unit.right() - -@Suppress("RedundantSuspendModifier", "UNUSED_PARAMETER") -private suspend fun throwException( - a: A, -): Either = - throw RuntimeException("An Exception is thrown while handling the result of the supplied function.") +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EndoTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EndoTest.kt deleted file mode 100644 index 0bdb1c74424..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EndoTest.kt +++ /dev/null @@ -1,18 +0,0 @@ -package arrow.core - -import arrow.core.test.endo -import arrow.core.test.laws.MonoidLaws -import arrow.core.test.testLaws -import io.kotest.core.spec.style.StringSpec -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int - -class EndoTest : StringSpec({ - - testLaws( - MonoidLaws("Endo", Endo(::identity), { f, g -> Endo(f.f.compose(g.f)) }, Arb.endo(Arb.int())) { a, b -> - a.f(1) == b.f(1) - } - ) - -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EvalTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EvalTest.kt deleted file mode 100644 index c77faef7345..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/EvalTest.kt +++ /dev/null @@ -1,134 +0,0 @@ -package arrow.core - -import arrow.core.test.stackSafeIteration -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe - -internal data class SideEffect(var counter: Int = 0) { - fun increment() { - counter++ - } -} - -private fun recur(limit: Int, sideEffect: SideEffect): (Int) -> Eval { - return { num -> - if (num <= limit) { - sideEffect.increment() - Eval.defer { - recur(limit, sideEffect).invoke(num + 1) - } - } else { - Eval.now(-1) - } - } -} - -class EvalTest : StringSpec({ - - "should map wrapped value" { - val sideEffect = SideEffect() - val mapped = Eval.now(0) - .map { sideEffect.increment(); it + 1 } - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 2 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 3 - } - - "later should lazily evaluate values once" { - val sideEffect = SideEffect() - val mapped = Eval.later { sideEffect.increment(); sideEffect.counter } - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - } - - "later should memoize values" { - val sideEffect = SideEffect() - val mapped = Eval.later { sideEffect.increment(); sideEffect.counter }.memoize() - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - } - - "always should lazily evaluate values repeatedly" { - val sideEffect = SideEffect() - val mapped = Eval.always { sideEffect.increment(); sideEffect.counter } - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 2 - sideEffect.counter shouldBe 2 - mapped.value() shouldBe 3 - sideEffect.counter shouldBe 3 - } - - "always should memoize values" { - val sideEffect = SideEffect() - val mapped = Eval.always { sideEffect.increment(); sideEffect.counter }.memoize() - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - } - - "defer should lazily evaluate other Evals" { - val sideEffect = SideEffect() - val mapped = Eval.defer { sideEffect.increment(); Eval.later { sideEffect.increment(); sideEffect.counter } } - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 2 - sideEffect.counter shouldBe 2 - mapped.value() shouldBe 4 - sideEffect.counter shouldBe 4 - mapped.value() shouldBe 6 - sideEffect.counter shouldBe 6 - } - - "defer should memoize Eval#later" { - val sideEffect = SideEffect() - val mapped = Eval.defer { sideEffect.increment(); Eval.later { sideEffect.increment(); sideEffect.counter } }.memoize() - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 2 - sideEffect.counter shouldBe 2 - mapped.value() shouldBe 2 - sideEffect.counter shouldBe 2 - mapped.value() shouldBe 2 - sideEffect.counter shouldBe 2 - } - - "defer should memoize Eval#now" { - val sideEffect = SideEffect() - val mapped = Eval.defer { sideEffect.increment(); Eval.now(sideEffect.counter) }.memoize() - sideEffect.counter shouldBe 0 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - mapped.value() shouldBe 1 - sideEffect.counter shouldBe 1 - } - - "flatMap should complete without blowing up the stack" { - val limit = stackSafeIteration() - val sideEffect = SideEffect() - val flatMapped = Eval.now(0).flatMap(recur(limit, sideEffect)) - sideEffect.counter shouldBe 0 - flatMapped.value() shouldBe -1 - sideEffect.counter shouldBe limit + 1 - } - -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt deleted file mode 100644 index 204cb0f7863..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt +++ /dev/null @@ -1,158 +0,0 @@ -package arrow.core - -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe - -class FunctionSyntaxTest : StringSpec({ - - val sum = { i1: Int, i2: Int -> i1 + i2 } - val add5 = { i: Int -> i + 5 } - val multiplyBy2 = { i: Int -> i * 2 } - - "it should compose function correctly (andThen)" { - val potato = "potato" - val ninja = "ninja" - val get = { potato } - val map = { word: String -> ninja + word } - (get andThen map)() - (ninja + potato) shouldBe (get andThen map)() - } - - "testAndThen" { - val add5andMultiplyBy2 = add5 andThen multiplyBy2 - add5andMultiplyBy2(2) shouldBe 14 - } - - "testAndThen2" { - val sumAndMultiplyBy2 = sum andThen multiplyBy2 - sumAndMultiplyBy2(5, 2) shouldBe 14 - } - - "testCompose" { - val multiplyBy2andAdd5 = add5 compose multiplyBy2 - multiplyBy2andAdd5(2) shouldBe 9 - } - - "testCurrying" { - val sum2ints = { x: Int, y: Int -> x + y } - val curried = sum2ints.curried() - curried(2)(4) shouldBe 6 - val addFive = curried(5) - addFive(7) shouldBe 12 - } - - "testUncurrying" { - val sum2ints: (Int, Int) -> Int = { x, y -> x + y } - val curried: (Int) -> (Int) -> Int = sum2ints.curried() - curried(2)(4) shouldBe 6 - // same type as sum2ints, - curried.uncurried()(2, 4) shouldBe 6 - sum2ints(2, 4) shouldBe 6 - } - - "testCurryingEffect" { - val sum2ints: suspend (Int, Int) -> Int = { x: Int, y: Int -> x + y } - val curried: (Int) -> suspend (Int) -> Int = sum2ints.curried() - curried(2)(4) shouldBe 6 - val addFive: suspend (Int) -> Int = curried(5) - addFive(7) shouldBe 12 - } - - "testUncurryingEffect" { - val sum2ints: suspend (Int, Int) -> Int = { x, y -> x + y } - val curried: (Int) -> suspend (Int) -> Int = sum2ints.curried() - curried(2)(4) shouldBe 6 - // same type as sum2ints, - curried.uncurried()(2, 4) shouldBe 6 - sum2ints(2, 4) shouldBe 6 - } - - "memoize" { - var counterA = 0 - var counterB = 0 - - val a = { _: Int -> counterA++ } - val b = { _: Int -> counterB++ }.memoize() - - repeat(5) { a(1) } - repeat(5) { b(1) } - - counterA shouldBe 5 - counterB shouldBe 1 // calling several times a memoized function with the same parameter is computed just once - } - - "memoizeEmpty" { - var counterA = 0 - var counterB = 0 - - val a = { counterA++ } - val b = { counterB++ }.memoize() - - repeat(5) { a() } - repeat(5) { b() } - - counterA shouldBe 5 - counterB shouldBe 1 // calling several times a memoized function with the same parameter is computed just once - } - - "partially" { - val sum5ints = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } - val sum4intsTo10 = sum5ints.partially5(10) - val sum3intsTo15 = sum4intsTo10.partially4(5) - val sum2intsTo17 = sum3intsTo15.partially3(2) - sum2intsTo17(1, 2) shouldBe 20 - - val prefixAndPostfix = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } - - val helloX = prefixAndPostfix.partially1("Hello, ").partially2("!") - helloX("Arrow") shouldBe "Hello, Arrow!" - } - - "suspend partially" { - val sum5ints: suspend (Int, Int, Int, Int, Int) -> Int = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } - val sum4intsTo10 = sum5ints.partially5(10) - val sum3intsTo15 = sum4intsTo10.partially4(5) - val sum2intsTo17 = sum3intsTo15.partially3(2) - sum2intsTo17(1, 2) shouldBe 20 - - val prefixAndPostfix: suspend (String, String, String) -> String = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } - - val helloX = prefixAndPostfix.partially1("Hello, ").partially2("!") - helloX("Arrow") shouldBe "Hello, Arrow!" - } - - "partials" { - val sum5ints = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } - val sum4intsTo10: (Int, Int, Int, Int) -> Int = sum5ints.partially5(10) - val sum3intsTo15: (Int, Int, Int) -> Int = sum4intsTo10.partially4(5) - val sum2intsTo17: (Int, Int) -> Int = sum3intsTo15.partially3(2) - sum2intsTo17(1, 2) shouldBe 20 - val prefixAndPostfix = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } - val helloX: (String) -> String = prefixAndPostfix.partially1("Hello, ").partially2("!") - helloX("Arrow") shouldBe "Hello, Arrow!" - } - - "suspend partials" { - val sum5ints: suspend (Int, Int, Int, Int, Int) -> Int = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } - val sum4intsTo10: suspend (Int, Int, Int, Int) -> Int = sum5ints.partially5(10) - val sum3intsTo15: suspend (Int, Int, Int) -> Int = sum4intsTo10.partially4(5) - val sum2intsTo17: suspend (Int, Int) -> Int = sum3intsTo15.partially3(2) - sum2intsTo17(1, 2) shouldBe 20 - val prefixAndPostfix: suspend (String, String, String) -> String = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } - val helloX: suspend (String) -> String = prefixAndPostfix.partially1("Hello, ").partially2("!") - helloX("Arrow") shouldBe "Hello, Arrow!" - } - - "bind" { - var i = 0 - fun inc(a: Int) { - i += a - } - - val binded = ::inc.partially1(5) - i shouldBe 0 - binded() - i shouldBe 5 - } - -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IorTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IorTest.kt index fdf797dea7a..502dbe63c2c 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IorTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IorTest.kt @@ -3,99 +3,28 @@ package arrow.core import arrow.core.test.ior import arrow.core.test.laws.SemigroupLaws import arrow.core.test.testLaws -import arrow.typeclasses.Semigroup -import io.kotest.core.spec.style.StringSpec import io.kotest.data.forAll import io.kotest.data.row import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf import io.kotest.property.Arb import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class IorTest : StringSpec({ +class IorTest { val ARB = Arb.ior(Arb.string(), Arb.int()) - testLaws( + @Test fun semigroupLaws() = testLaws( SemigroupLaws("Ior", { a, b -> a.combine(b, String::plus, Int::plus) }, ARB) ) - val nullableLongSemigroup = object : Semigroup { - override fun Long?.combine(b: Long?): Long? = - Nullable.zip(this, b) { a, bb -> a + bb } - } - - "zip identity" { - checkAll(Arb.ior(Arb.long().orNull(), Arb.int().orNull())) { ior -> - val res = ior.zip(nullableLongSemigroup, Ior.Right(Unit)) { a, _ -> a } - res shouldBe ior - } - } - - "zip is derived from flatMap" { - checkAll( - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()), - Arb.ior(Arb.long().orNull(), Arb.int().orNull()) - ) { a, b, c, d, e, f, g, h, i, j -> - val res = a.zip( - nullableLongSemigroup, - b, c, d, e, f, g, h, i, j - ) { a, b, c, d, e, f, g, h, i, j -> - Nullable.zip( - a, - b, - c, - d, - e, - f, - g, - h, - i, - j - ) { a, b, c, d, e, f, g, h, i, j -> a + b + c + d + e + f + g + h + i + j } - } - - val expected = listOf(a, b, c, d, e, f, g, h, i, j) - .fold, Ior>(Ior.Right(0)) { acc, ior -> - val mid = acc.flatMap(nullableLongSemigroup) { a -> ior.map { b -> Nullable.zip(a, b) { a, b -> a + b } } } - mid - } - - res shouldBe expected - } - } - - "zip should combine left values in correct order" { - Ior.Both("fail1", -1).zip( - Semigroup.string(), - Ior.Left("fail2"), - Ior.Right(-1) - ) { _, _, _ -> "success!" } shouldBe Ior.Left("fail1fail2") - } - - "bimap() should allow modify both value" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - Ior.Right(b).bimap({ "5" }, { a * 2 }) shouldBe Ior.Right(a * 2) - Ior.Left(a).bimap({ a * 3 }, { "5" }) shouldBe Ior.Left(a * 3) - Ior.Both(a, b).bimap({ 2 }, { "power of $it" }) shouldBe Ior.Both(2, "power of $b") - } - } - - "map() should just right side of an Ior" { + @Test fun mapRightOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Left(a).map { l: String -> l.length } shouldBe Ior.Left(a) Ior.Right(b).map { it.length } shouldBe Ior.Right(b.length) @@ -103,7 +32,7 @@ class IorTest : StringSpec({ } } - "mapLeft() should modify only left value" { + @Test fun mapLeftOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Right(b).mapLeft { a * 2 } shouldBe Ior.Right(b) Ior.Left(a).mapLeft { b } shouldBe Ior.Left(b) @@ -111,20 +40,20 @@ class IorTest : StringSpec({ } } - "swap() should interchange value" { + @Test fun swapBoth() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Both(a, b).swap() shouldBe Ior.Both(b, a) } } - "swap() should interchange entity" { + @Test fun swapLeftRight() = runTest { checkAll(Arb.int()) { a: Int -> Ior.Left(a).swap() shouldBe Ior.Right(a) Ior.Right(a).swap() shouldBe Ior.Left(a) } } - "unwrap() should return the isomorphic either" { + @Test fun unwrapOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Left(a).unwrap() shouldBe Either.Left(Either.Left(a)) Ior.Right(b).unwrap() shouldBe Either.Left(Either.Right(b)) @@ -132,15 +61,7 @@ class IorTest : StringSpec({ } } - "padNull() should return the correct Pair of nullables" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - Ior.Left(a).padNull() shouldBe Pair(a, null) - Ior.Right(b).padNull() shouldBe Pair(null, b) - Ior.Both(a, b).padNull() shouldBe Pair(a, b) - } - } - - "toEither() should convert values into a valid Either" { + @Test fun toEitherOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Left(a).toEither() shouldBe Either.Left(a) Ior.Right(b).toEither() shouldBe Either.Right(b) @@ -148,15 +69,7 @@ class IorTest : StringSpec({ } } - "orNull() should convert right values into a nullable" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - Ior.Left(a).orNull() shouldBe null - Ior.Right(b).orNull() shouldBe b - Ior.Both(a, b).orNull() shouldBe b - } - } - - "getOrNull() should convert right values into a nullable, or return null if left" { + @Test fun getOrNullOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Left(a).getOrNull() shouldBe null Ior.Right(b).getOrNull() shouldBe b @@ -165,7 +78,7 @@ class IorTest : StringSpec({ } - "leftOrNull() should convert left values into a nullable" { + @Test fun leftOrNullOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.Left(a).leftOrNull() shouldBe a Ior.Right(b).leftOrNull() shouldBe null @@ -173,15 +86,7 @@ class IorTest : StringSpec({ } } - "toValidated() should convert values into a valid Validated" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - Ior.Left(a).toValidated() shouldBe Invalid(a) - Ior.Right(b).toValidated() shouldBe Valid(b) - Ior.Both(a, b).toValidated() shouldBe Valid(b) - } - } - - "fromNullables() should build a correct Ior" { + @Test fun fromNullablesOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.fromNullables(a, null) shouldBe Ior.Left(a) Ior.fromNullables(a, b) shouldBe Ior.Both(a, b) @@ -190,49 +95,19 @@ class IorTest : StringSpec({ } } - "leftNel() should build a correct Ior" { + @Test fun leftNelOk() = runTest { checkAll(Arb.int()) { a: Int -> Ior.leftNel(a) shouldBe Ior.Left(nonEmptyListOf(a)) } } - "bothNel() should build a correct Ior" { + @Test fun bothNelOk() = runTest { checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> Ior.bothNel(a, b) shouldBe Ior.Both(nonEmptyListOf(a), b) } } - "lift(f) should apply the input function to an Ior correctly" { - checkAll(Arb.string()) { a: String -> - val f = Ior.lift { s: String -> "Hello $s" } - f(Ior.Right(a)) shouldBe Ior.Right("Hello $a") - } - } - - "lift(fa, fb) should apply the input functions to an Ior correctly" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val fa = { s1: String -> "Hello $s1" } - val fb = { s2: String -> s2.length } - val f = Ior.lift(fa, fb) - f(Ior.Right(b)) shouldBe Ior.Right(b.length) - f(Ior.Left(a)) shouldBe Ior.Left("Hello $a") - f(Ior.Both(a, b)) shouldBe Ior.Both("Hello $a", b.length) - } - } - - "foldLeft should fold an Ior correctly" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val left = Ior.Left(a) - val right = Ior.Right(b) - val both = Ior.Both(a, b) - val f = { c: Int, b: String -> c + b.length } - left.foldLeft(0, f) shouldBe 0 - right.foldLeft(0, f) shouldBe b.length - both.foldLeft(0, f) shouldBe b.length - } - } - - "getOrElse() should return value" { + @Test fun getOrElseOk() = runTest { checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> Ior.Right(a).getOrElse { b } shouldBe a Ior.Left(a).getOrElse { b } shouldBe b @@ -240,13 +115,13 @@ class IorTest : StringSpec({ } } - "Ior.monad.flatMap should combine left values" { + @Test fun flatMapCombinesLeft() = runTest { val ior1 = Ior.Both(3, "Hello, world!") val iorResult = ior1.flatMap(Int::plus) { Ior.Left(7) } iorResult shouldBe Ior.Left(10) } - "Ior.monad.flatMap should combine Both values" { + @Test fun flatMapCombinesBoth() = runTest { val ior1 = Ior.Both(3, "Hello, world!") val iorResult1 = ior1.flatMap(Int::plus) { Ior.Both(7, "Again!") } iorResult1 shouldBe Ior.Both(10, "Again!") @@ -255,7 +130,7 @@ class IorTest : StringSpec({ iorResult2 shouldBe Ior.Both(3, "Again!") } - "combine cases for Semigroup" { + @Test fun combineSemigroup() = runTest { forAll( row("Hello, ".leftIor(), Ior.Left("Arrow!"), Ior.Left("Hello, Arrow!")), row(Ior.Left("Hello"), Ior.Right(2020), Ior.Both("Hello", 2020)), @@ -271,150 +146,15 @@ class IorTest : StringSpec({ } } - "traverse should wrap ior in a list" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.traverse { listOf(it) } shouldBe listOf(Ior.Left(a)) - iorR.traverse { listOf(it) } shouldBe listOf(Ior.Right(b)) - iorBoth.traverse { listOf(it) } shouldBe listOf(Ior.Both(a, b)) - } - } - - "sequence should be consistent with traverse" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.map { listOf(it) }.sequence() shouldBe ior.traverse { listOf(it) } - } - } - - "traverseNullable should wrap ior in a nullable" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.traverseNullable { it } shouldBe Ior.Left(a) - iorR.traverseNullable { it } shouldBe Ior.Right(b) - iorBoth.traverseNullable { it } shouldBe Ior.Both(a, b) - - iorL.traverseNullable { null } shouldBe Ior.Left(a) - iorR.traverseNullable { null } shouldBe null - iorBoth.traverseNullable { null } shouldBe null - } - } - - "sequence for Nullable should be consistent with traverseNullable" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.map { it }.sequence() shouldBe ior.traverseNullable { it } - ior.map { null }.sequence() shouldBe ior.traverseNullable { null } - } - } - - "traverseOption should wrap ior in an Option" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.traverse { Some(it) } shouldBe Some(Ior.Left(a)) - iorR.traverse { Some(it) } shouldBe Some(Ior.Right(b)) - iorBoth.traverse { Some(it) } shouldBe Some(Ior.Both(a, b)) - } - } - - "sequenceOption should be consistent with traverseOption" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.map { Some(it) }.sequence() shouldBe ior.traverse { Some(it) } - } - } - - "traverseEither should wrap ior in an Option" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.traverse { it.right() } shouldBe Either.Right(Ior.Left(a)) - iorR.traverse { it.right() } shouldBe Either.Right(Ior.Right(b)) - iorBoth.traverse { it.right() } shouldBe Either.Right(Ior.Both(a, b)) - } - } - - "sequenceEither should be consistent with traverseEither" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.map { it.right() }.sequence() shouldBe ior.traverse { it.right() } - } - } - - "bitraverse should wrap ior in a list" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) shouldBe listOf(Ior.Left(a), Ior.Left(2), Ior.Left(3)) - iorR.bitraverse({ listOf(it, 2, 3) }, { listOf(it) }) shouldBe listOf(Ior.Right(b)) - iorBoth.bitraverse({ listOf(it, 2, 3) }, { listOf(it, 4, 5) }) shouldBe - listOf(Ior.Both(a, b), Ior.Both(2, 4), Ior.Both(3, 5)) - } - } - - "bisequence should be consistent with bitraverse" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe - ior.bitraverse({ listOf(it) }, { listOf(it) }) - } - } - - "bitraverseOption should wrap ior in an Option" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.bitraverseOption({ None }, { Some(it) }) shouldBe None - iorR.bitraverseOption({ None }, { Some(it) }) shouldBe Some(Ior.Right(b)) - iorBoth.bitraverseOption({ None }, { Some(it) }) shouldBe None - } - } - - "bisequenceOption should be consistent with bitraverseOption" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.bimap({ None }, { Some(it) }).bisequenceOption() shouldBe - ior.bitraverseOption({ None }, { Some(it) }) - } - } - - "bitraverseEither should wrap ior in an Either" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val iorL: Ior = a.leftIor() - val iorR: Ior = b.rightIor() - val iorBoth: Ior = (a to b).bothIor() - - iorL.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Left(a) - iorR.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Right(Ior.Right(b)) - iorBoth.bitraverseEither({ it.left() }, { it.right() }) shouldBe Either.Left(a) - } - } - - "bisequenceEither should be consistent with bitraverseEither" { - checkAll(Arb.ior(Arb.int(), Arb.string())) { ior -> - ior.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe - ior.bitraverseEither({ it.left() }, { it.right() }) - } - } - - "isLeft() should return true with Left and false otherwise" { - checkAll(Arb.int(), Arb.string()) { a, b -> + @Test fun isLeftOk() = runTest { + checkAll(Arb.int(), Arb.string()){ a, b -> Ior.Left(a).isLeft() shouldBe true Ior.Right(b).isLeft() shouldBe false Ior.Both(a, b).isLeft() shouldBe false } } - "isRight() should return true with Right and false otherwise" { + @Test fun isRightOk() = runTest { checkAll(Arb.int(), Arb.string()) { a, b -> Ior.Left(a).isRight() shouldBe false Ior.Right(b).isRight() shouldBe true @@ -422,7 +162,7 @@ class IorTest : StringSpec({ } } - "isBoth() should return true with Both and false otherwise" { + @Test fun isBothOk() = runTest { checkAll(Arb.int(), Arb.string()) { a, b -> Ior.Left(a).isBoth() shouldBe false Ior.Right(b).isBoth() shouldBe false @@ -430,7 +170,7 @@ class IorTest : StringSpec({ } } - "isLeft(predicate) should return true with Left, if satisfies the predicate, and false otherwise" { + @Test fun isLeftPredicateOk() = runTest { checkAll(Arb.int(), Arb.string()) { a, b -> val predicate = { i: Int -> i % 2 == 0 } @@ -442,7 +182,7 @@ class IorTest : StringSpec({ } } - "isRight(predicate) should return true with Right, if satisfies the predicate, and false otherwise" { + @Test fun isRightPredicateOk() = runTest { checkAll(Arb.int(), Arb.string()) { a, b -> val predicate = { s: String -> s.length % 2 == 0 } @@ -454,7 +194,7 @@ class IorTest : StringSpec({ } } - "isBoth(predicate) should return true with Both, if satisfies the predicate, and false otherwise" { + @Test fun isBothPredicateOk() = runTest { checkAll(Arb.int(), Arb.string()) { a, b -> val leftPredicate = { i: Int -> i % 2 == 0 } val rightPredicate = { s: String -> s.length % 2 == 0 } @@ -466,14 +206,7 @@ class IorTest : StringSpec({ } } - "widen should retype Right" { - checkAll(Arb.int(), Arb.string()) { a, b -> - val ior = Ior.Both(a, b) - ior.widen().shouldBeInstanceOf>() - } - } - - "compareTo should compare 2 Ior" { + @Test fun compareToOk() = runTest { val left1 = Ior.Left(1) val left2 = Ior.Left(2) val right1 = Ior.Right(1) @@ -496,4 +229,4 @@ class IorTest : StringSpec({ both11.compareTo(left1) shouldBe 1 both11.compareTo(right1) shouldBe 1 } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt index 06880e53fa7..5f449328f2f 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/IterableTest.kt @@ -3,12 +3,8 @@ package arrow.core import arrow.core.test.either -import arrow.core.test.functionAToB import arrow.core.test.ior import arrow.core.test.option -import arrow.typeclasses.Semigroup -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.collections.shouldContainExactly import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.property.Arb @@ -16,17 +12,18 @@ import io.kotest.matchers.shouldBe import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest import kotlin.math.max import kotlin.math.min +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class IterableTest : StringSpec({ - - "flattenOrAccumulate(combine)" { - checkAll(Arb.list(Arb.either(Arb.string(), Arb.int()))) { list -> +class IterableTest { + @Test fun flattenOrAccumulateCombine() = runTest(timeout = 30.seconds) { + checkAll(Arb.list(Arb.either(Arb.string(maxSize = 10), Arb.int()), range = 0 .. 20)) { list -> val expected = if (list.any { it.isLeft() }) list.filterIsInstance>() .fold("") { acc, either -> "$acc${either.value}" }.left() @@ -36,8 +33,8 @@ class IterableTest : StringSpec({ } } - "flattenOrAccumulate" { - checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()))) { list -> + @Test fun flattenOrAccumulateOk() = runTest { + checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()), range = 0 .. 20)) { list -> val expected = if (list.any { it.isLeft() }) list.filterIsInstance>() .map { it.value }.toNonEmptyListOrNull().shouldNotBeNull().left() @@ -47,241 +44,35 @@ class IterableTest : StringSpec({ } } - "mapAccumulating stack-safe, and runs in original order" { - val acc = mutableListOf() - val res = (0..20_000).mapOrAccumulate(String::plus) { - acc.add(it) - it - } - res shouldBe acc.right() - res shouldBe (0..20_000).toList().right() - } - - "mapAccumulating accumulates" { - checkAll(Arb.list(Arb.int())) { ints -> - val res = ints.mapOrAccumulate { i -> - if (i % 2 == 0) i else raise(i) - } - - val expected: Either, List> = ints.filterNot { it % 2 == 0 } - .toNonEmptyListOrNull()?.left() ?: ints.filter { it % 2 == 0 }.right() - - res shouldBe expected - } - } - - "mapAccumulating with String::plus" { - listOf(1, 2, 3).mapOrAccumulate(String::plus) { i -> - raise("fail") - } shouldBe Either.Left("failfailfail") - } - - "traverse Either stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).traverse { a -> - acc.add(a) - Either.Right(a) - } - res shouldBe Either.Right(acc) - res shouldBe Either.Right((0..20_000).toList()) - } - - "traverse Either short-circuit" { - checkAll(Arb.list(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - if (it % 2 == 0) { - acc.add(it) - Either.Right(it) - } else Either.Left(it) - } - acc shouldBe ints.takeWhile { it % 2 == 0 } - when (evens) { - is Either.Right -> evens.value shouldBe ints - is Either.Left -> evens.value shouldBe ints.first { it % 2 != 0 } - } - } - } - - "sequenceEither should be consistent with traverse Either" { - checkAll(Arb.list(Arb.int())) { ints -> - ints.map { it.right() }.sequence() shouldBe ints.traverse { it.right() } - } - } - - "traverse Result stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).traverse { a -> - acc.add(a) - Result.success(a) - } - res shouldBe Result.success(acc) - res shouldBe Result.success((0..20_000).toList()) - } - - "traverse Result short-circuit" { - checkAll(Arb.list(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - if (it % 2 == 0) { - acc.add(it) - Result.success(it) - } else Result.failure(RuntimeException()) - } - acc shouldBe ints.takeWhile { it % 2 == 0 } - evens.fold( - { it shouldBe ints }, - { } - ) - } - } - - "sequence Result should be consistent with traverse Result" { - checkAll(Arb.list(Arb.int())) { ints -> - ints.map { Result.success(it) }.sequence() shouldBe ints.traverse { Result.success(it) } - } - } - - "traverse Option is stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).traverse { a: Int -> - acc.add(a) - Some(a) - } - res shouldBe Some(acc) - res shouldBe Some((0..20_000).toList()) - } - - "traverse Option short-circuits" { - checkAll(Arb.list(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - (it % 2 == 0).maybe { - acc.add(it) - it - } - } - acc shouldBe ints.takeWhile { it % 2 == 0 } - evens.fold({ Unit }) { it shouldBe ints } - } - } - - "sequence Option yields some when all entries in the list are some" { - checkAll(Arb.list(Arb.int())) { ints -> - val evens = ints.map { (it % 2 == 0).maybe { it } }.sequence() - evens.fold({ Unit }) { it shouldBe ints } - } - } - - "sequence Option should be consistent with traverse Option" { - checkAll(Arb.list(Arb.int())) { ints -> - ints.map { Some(it) }.sequence() shouldBe ints.traverse { Some(it) } - } - } - - "traverse Nullable is stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).traverse { a: Int -> - acc.add(a) - a - } - res.shouldNotBeNull() shouldBe acc - res.shouldNotBeNull() shouldBe (0..20_000).toList() - } - - "traverse Nullable short-circuits" { - checkAll(Arb.list(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - if (it % 2 == 0) { - acc.add(it) - it - } else { - null - } - } - - val expected = ints.takeWhile { it % 2 == 0 } - acc shouldBe expected - - if (ints.any { it % 2 != 0 }) { - evens.shouldBeNull() - } else { - evens.shouldNotBeNull() shouldContainExactly expected - } - } - } - - "sequence Nullable yields some when all entries in the list are not null" { - checkAll(Arb.list(Arb.int())) { ints -> - val evens = ints.map { if (it % 2 == 0) it else null }.sequence() - - if (ints.any { it % 2 != 0 }) { - evens.shouldBeNull() - } else { - evens.shouldNotBeNull() shouldContainExactly ints.takeWhile { it % 2 == 0 } - } - } - } - - "sequence Nullable should be consistent with travers Nullable" { - checkAll(Arb.list(Arb.int())) { ints -> - ints.map { it as Int? }.sequence() shouldBe ints.traverse { it as Int? } - } - } - - "traverse Validated stack-safe" { - // also verifies result order and execution order (l to r) + @Test fun mapOrAccumulateOrder() = runTest { val acc = mutableListOf() - val res = (0..20_000).traverse(Semigroup.string()) { + val res = (0..20_000).mapOrAccumulate(String::plus) { acc.add(it) - Validated.Valid(it) + it } - res shouldBe Validated.Valid(acc) - res shouldBe Validated.Valid((0..20_000).toList()) + res shouldBe acc.right() + res shouldBe (0..20_000).toList().right() } - "traverse Validated acumulates" { - checkAll(Arb.list(Arb.int())) { ints -> - val res: ValidatedNel> = - ints.map { i -> if (i % 2 == 0) Valid(i) else Invalid(nonEmptyListOf(i)) } - .sequence() + @Test fun mapOrAccumulateAccumulates() = runTest { + checkAll(Arb.list(Arb.int(), range = 0 .. 20)) { ints -> + val res= + ints.mapOrAccumulate { i -> if (i % 2 == 0) i else raise(i) } - val expected: ValidatedNel> = ints.filterNot { it % 2 == 0 } - .toNonEmptyListOrNull()?.invalid() ?: Valid(ints.filter { it % 2 == 0 }) + val expected: Either, List> = ints.filterNot { it % 2 == 0 } + .toNonEmptyListOrNull()?.left() ?: ints.filter { it % 2 == 0 }.right() res shouldBe expected } } - "sequence Validated should be consistent with traverse Validated" { - checkAll(Arb.list(Arb.int())) { ints -> - ints.map { it.valid() }.sequence(Semigroup.string()) shouldBe - ints.traverse(Semigroup.string()) { it.valid() } - } - } - - "sequence Either traverse Nullable interoperate - and proof map + sequence equality with traverse" { - checkAll( - Arb.list(Arb.int()), - Arb.functionAToB?>(Arb.either(Arb.int(), Arb.int()).orNull()) - ) { ints, f -> - - val res: Either>? = - ints.traverse(f)?.sequence() - - val expected: Either>? = - ints.map(f).sequence()?.sequence() - - res shouldBe expected - } + @Test fun mapOrAccumulateString() = runTest { + listOf(1, 2, 3).mapOrAccumulate(String::plus) { i -> + raise("fail") + } shouldBe Either.Left("failfailfail") } - "zip3" { + @Test fun zip3Ok() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b, c -> val result = a.zip(b, c, ::Triple) val expected = a.zip(b, ::Pair).zip(c) { (a, b), c -> Triple(a, b, c) } @@ -289,7 +80,7 @@ class IterableTest : StringSpec({ } } - "zip4" { + @Test fun zip4Ok() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b, c, d -> val result = a.zip(b, c, d, ::Tuple4) val expected = a.zip(b, ::Pair) @@ -300,7 +91,7 @@ class IterableTest : StringSpec({ } } - "zip5" { + @Test fun zip5Ok() = runTest { checkAll( Arb.list(Arb.int()), Arb.list(Arb.int()), @@ -318,7 +109,7 @@ class IterableTest : StringSpec({ } } - "zip6" { + @Test fun zip6Ok() = runTest { checkAll( Arb.list(Arb.int()), Arb.list(Arb.int()), @@ -338,7 +129,7 @@ class IterableTest : StringSpec({ } } - "zip7" { + @Test fun zip7Ok() = runTest { checkAll( Arb.list(Arb.int()), Arb.list(Arb.int()), @@ -360,7 +151,7 @@ class IterableTest : StringSpec({ } } - "zip8" { + @Test fun zip8Ok() = runTest { checkAll( Arb.list(Arb.int()), Arb.list(Arb.int()), @@ -384,7 +175,7 @@ class IterableTest : StringSpec({ } } - "zip9" { + @Test fun zip9Ok() = runTest { checkAll( Arb.list(Arb.int()), Arb.list(Arb.int()), @@ -410,57 +201,29 @@ class IterableTest : StringSpec({ } } - "zip10" { - checkAll( - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()), - Arb.list(Arb.int()) - ) { a, b, c, d, e, f, g, h, i, j -> - val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) - val expected = a.zip(b, ::Pair) - .zip(c) { (a, b), c -> Triple(a, b, c) } - .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } - .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } - .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } - .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } - .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } - .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } - .zip(j) { (a, b, c, d, e, f, g, h, i), j -> Tuple10(a, b, c, d, e, f, g, h, i, j) } - - result shouldBe expected - } - } - - "can align lists with different lengths" { + @Test fun alignDifferentLength() = runTest { checkAll(Arb.list(Arb.boolean()), Arb.list(Arb.boolean())) { a, b -> a.align(b).size shouldBe max(a.size, b.size) } checkAll(Arb.list(Arb.boolean()), Arb.list(Arb.boolean())) { a, b -> a.align(b).take(min(a.size, b.size)).forEach { - it.isBoth shouldBe true + it.isBoth() shouldBe true } } checkAll(Arb.list(Arb.boolean()), Arb.list(Arb.boolean())) { a, b -> a.align(b).drop(min(a.size, b.size)).forEach { if (a.size < b.size) { - it.isRight shouldBe true + it.isRight() shouldBe true } else { - it.isLeft shouldBe true + it.isLeft() shouldBe true } } } } - "leftPadZip (with map)" { + @Test fun leftPadZipMap() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -471,7 +234,7 @@ class IterableTest : StringSpec({ } } - "leftPadZip (without map)" { + @Test fun leftPadZipNoMap() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -482,7 +245,7 @@ class IterableTest : StringSpec({ } } - "rightPadZip (without map)" { + @Test fun rightPadZipNoMap() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -494,7 +257,7 @@ class IterableTest : StringSpec({ } } - "rightPadZip (with map)" { + @Test fun rightPadZipMap() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -506,7 +269,7 @@ class IterableTest : StringSpec({ } } - "padZip" { + @Test fun padZipOk() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -514,7 +277,7 @@ class IterableTest : StringSpec({ } } - "padZipWithNull" { + @Test fun padZipNull() = runTest { checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> val left = a.map { it } + List(max(0, b.count() - a.count())) { null } val right = b.map { it } + List(max(0, a.count() - b.count())) { null } @@ -523,19 +286,19 @@ class IterableTest : StringSpec({ } } - "filterOption" { + @Test fun filterOptionOk() = runTest { checkAll(Arb.list(Arb.option(Arb.int()))) { listOfOption -> - listOfOption.filterOption() shouldBe listOfOption.mapNotNull { it.orNull() } + listOfOption.filterOption() shouldBe listOfOption.mapNotNull { it.getOrNull() } } } - "flattenOption" { + @Test fun flattenOptionOk() = runTest { checkAll(Arb.list(Arb.option(Arb.int()))) { listOfOption -> - listOfOption.flattenOption() shouldBe listOfOption.mapNotNull { it.orNull() } + listOfOption.flattenOption() shouldBe listOfOption.mapNotNull { it.getOrNull() } } } - "separateEither" { + @Test fun separateEitherOk() = runTest { checkAll(Arb.list(Arb.int())) { ints -> val list = ints.separateEither { if (it % 2 == 0) it.left() @@ -545,17 +308,7 @@ class IterableTest : StringSpec({ } } - "separateValidated" { - checkAll(Arb.list(Arb.int())) { ints -> - val list = ints.map { - if (it % 2 == 0) it.invalid() - else it.valid() - } - list.separateValidated() shouldBe ints.partition { it % 2 == 0 } - } - } - - "unzip is the inverse of zip" { + @Test fun unzipInverseOfZip() = runTest { checkAll(Arb.list(Arb.int())) { xs -> val zipped = xs.zip(xs) @@ -566,38 +319,46 @@ class IterableTest : StringSpec({ } } - "unzip(fn)" { + @Test fun unzipOk() = runTest { checkAll(Arb.list(Arb.pair(Arb.int(), Arb.int()))) { xs -> xs.unzip { it } shouldBe xs.unzip() } } - "unalign is the inverse of align" { + @Test fun unalignInverseOfAlign() = runTest { + fun Pair, List>.fix(): Pair, List> = + first.mapNotNull { it } to second.mapNotNull { it } + checkAll(Arb.list(Arb.int()), Arb.list(Arb.int())) { a, b -> - a.align(b).unalign() shouldBe (a to b) + a.align(b).unalign().fix() shouldBe (a to b) } } - "align is the inverse of unalign" { + @Test fun alignInverseOfUnalign() = runTest { + fun Ior.fix(): Ior = + fold({ Ior.Left(it!!) }, { Ior.Right(it!!) }, { a, b -> + when { + a == null -> Ior.Right(b!!) + b == null -> Ior.Left(a) + else -> Ior.Both(a, b) + } + }) + checkAll(Arb.list(Arb.ior(Arb.int(), Arb.int()))) { xs -> val (a, b) = xs.unalign() - a.align(b) shouldBe xs + a.align(b) { + it.fix() + } shouldBe xs } } - "unalign(fn)" { + @Test fun unalignOk() = runTest { checkAll(Arb.list(Arb.ior(Arb.int(), Arb.int()))) { xs -> xs.unalign { it } shouldBe xs.unalign() } } - "salign" { - checkAll(Arb.list(Arb.int())) { xs -> - xs.salign(Semigroup.int(), xs) shouldBe xs.map { it + it } - } - } - - "reduceOrNull is compatible with reduce from stdlib" { + @Test fun reduceOrNullCompatibleWithReduce() = runTest { checkAll(Arb.list(Arb.int())) { xs -> val rs = xs.reduceOrNull({ it }) { a, b -> @@ -614,7 +375,7 @@ class IterableTest : StringSpec({ } } - "reduceRightNull is compatible with reduce from stdlib" { + @Test fun reduceRightNullCompatibleWithReduce() = runTest { checkAll(Arb.list(Arb.int())) { xs -> val rs = xs.reduceRightNull({ it }) { a, b -> @@ -630,4 +391,4 @@ class IterableTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/KotestConfig.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/KotestConfig.kt deleted file mode 100644 index ce7f493fad2..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/KotestConfig.kt +++ /dev/null @@ -1,12 +0,0 @@ -package arrow.core - -import io.kotest.core.config.AbstractProjectConfig -import io.kotest.property.PropertyTesting -import kotlin.time.Duration -import kotlin.time.Duration.Companion.seconds - -class KotestConfig : AbstractProjectConfig() { - override suspend fun beforeProject() { - PropertyTesting.defaultIterationCount = 250 - } -} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ListKTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ListKTest.kt index a3ef444a513..08ed5566c53 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ListKTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ListKTest.kt @@ -2,18 +2,20 @@ package arrow.core import arrow.core.test.laws.MonoidLaws import arrow.core.test.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class ListKTest : StringSpec({ +class ListKTest { + @Test fun monoidLaws() = testLaws(MonoidLaws("List", emptyList(), List::plus, Arb.list(Arb.int()))) - "mapNotNull() should map list and filter out null values" { + @Test fun mapNotNullOk() = runTest { checkAll(Arb.list(Arb.int())) { listk -> listk.mapNotNull { when (it % 2 == 0) { @@ -24,4 +26,4 @@ class ListKTest : StringSpec({ } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MapKTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MapKTest.kt index 95ac777206f..e6ba1a9d7e1 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MapKTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MapKTest.kt @@ -9,12 +9,7 @@ import arrow.core.test.map2 import arrow.core.test.map3 import arrow.core.test.option import arrow.core.test.testLaws -import arrow.typeclasses.Semigroup -import io.kotest.core.spec.style.StringSpec import io.kotest.inspectors.forAll -import io.kotest.inspectors.forAllValues -import io.kotest.matchers.booleans.shouldBeTrue -import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.collections.shouldContainAll import io.kotest.matchers.maps.shouldBeEmpty import io.kotest.matchers.maps.shouldContain @@ -27,13 +22,15 @@ import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.pair import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class MapKTest : StringSpec({ +class MapKTest { + @Test fun monoidLaws() = testLaws( MonoidLaws( "Map", @@ -43,98 +40,7 @@ class MapKTest : StringSpec({ ) ) - "traverseEither is stacksafe" { - val acc = mutableListOf() - val res = (0..20_000).associateWith { it }.traverse { v -> - acc.add(v) - Either.Right(v) - } - res shouldBe acc.associateWith { it }.right() - res shouldBe (0..20_000).associateWith { it }.right() - } - - "traverseEither short-circuit" { - checkAll(Arb.map(Arb.int(), Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - if (it % 2 == 0) { - acc.add(it) - Either.Right(it) - } else Either.Left(it) - } - acc shouldBe ints.values.takeWhile { it % 2 == 0 } - when (evens) { - is Either.Right -> evens.value shouldBe ints - is Either.Left -> evens.value shouldBe ints.values.first { it % 2 != 0 } - } - } - } - - "traverseOption is stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).associateWith { it }.traverse { a -> - acc.add(a) - Some(a) - } - res shouldBe Some(acc.associateWith { it }) - res shouldBe Some((0..20_000).associateWith { it }) - } - - "traverseOption short-circuits" { - checkAll(Arb.map(Arb.int(), Arb.int())) { ints -> - var shortCircuited = 0 - val result = ints.traverse { - if (it % 2 == 0) { - Some(it) - } else { - shortCircuited++ - None - } - } - shortCircuited.shouldBeIn(0, 1) - - if (shortCircuited == 0) { - result.isSome().shouldBeTrue() - } else if (shortCircuited == 1) { - result.isNone().shouldBeTrue() - } - } - } - - "sequenceOption yields some when all entries in the list are some" { - checkAll(Arb.list(Arb.int())) { ints -> - val evens = ints.map { (it % 2 == 0).maybe { it } }.sequence() - evens.fold({ Unit }) { it shouldBe ints } - } - } - - "traverseValidated is stacksafe" { - val acc = mutableListOf() - val res = (0..20_000).associateWith { it }.traverse(Semigroup.string()) { v -> - acc.add(v) - Validated.Valid(v) - } - res shouldBe acc.associateWith { it }.valid() - res shouldBe (0..20_000).associateWith { it }.valid() - } - - "traverseValidated acummulates" { - checkAll(Arb.map(Arb.int(), Arb.int())) { ints -> - val res: ValidatedNel> = - ints.traverse(Semigroup.nonEmptyList()) { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } - - val expected: ValidatedNel> = - Option.fromNullable(ints.values.filterNot { it % 2 == 0 }.toNonEmptyListOrNull()) - .fold( - { ints.entries.filter { (_, v) -> v % 2 == 0 }.associate { (k, v) -> k to v }.validNel() }, - { it.invalid() }) - - res shouldBe expected - } - } - - "can align maps" { + @Test fun alignMaps() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -156,7 +62,7 @@ class MapKTest : StringSpec({ } } - "zip is idempotent" { + @Test fun zipIsIdempotent() = runTest { checkAll( Arb.map(Arb.int(), Arb.intSmall())) { a -> @@ -164,7 +70,7 @@ class MapKTest : StringSpec({ } } - "align is idempotent" { + @Test fun alignIsIdempotent() = runTest { checkAll( Arb.map(Arb.int(), Arb.intSmall())) { a -> @@ -172,7 +78,7 @@ class MapKTest : StringSpec({ } } - "zip is commutative" { + @Test fun zipIsCommutative() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -181,7 +87,7 @@ class MapKTest : StringSpec({ } } - "align is commutative" { + @Test fun alignIsCommutative() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -190,7 +96,7 @@ class MapKTest : StringSpec({ } } - "zip is associative" { + @Test fun zipIsAssociative() = runTest { checkAll( Arb.map3(Arb.int(), Arb.int(), Arb.int(), Arb.int()) ) { (a, b, c) -> @@ -202,7 +108,7 @@ class MapKTest : StringSpec({ } } - "align is associative" { + @Test fun alignIsAssociative() = runTest { checkAll( Arb.map3(Arb.int(), Arb.int(), Arb.int(), Arb.int()) ) { (a, b, c) -> @@ -226,7 +132,7 @@ class MapKTest : StringSpec({ } } - "zip with" { + @Test fun zipWith() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()), Arb.functionABCToD(Arb.int()) @@ -235,7 +141,7 @@ class MapKTest : StringSpec({ } } - "align with" { + @Test fun alignWith() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()), Arb.functionAToB>, Int>(Arb.int()) @@ -244,7 +150,7 @@ class MapKTest : StringSpec({ } } - "zip functoriality" { + @Test fun zipFunctor() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()), Arb.functionAToB(Arb.int()), @@ -261,7 +167,7 @@ class MapKTest : StringSpec({ } } - "align functoriality" { + @Test fun alignFunctor() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()), Arb.functionAToB(Arb.int()), @@ -269,14 +175,14 @@ class MapKTest : StringSpec({ ) { (a,b),f,g -> - val l = a.mapValues{ f(it.value)}.align(b.mapValues{g(it.value)}) - val r = a.align(b).mapValues { it.value.bimap(f,g)} + val l = a.mapValues{ f(it.value) }.align(b.mapValues{ g(it.value) }) + val r = a.align(b).mapValues { it.value.map(g).mapLeft(f) } l shouldBe r } } - "alignedness" { + @Test fun alignedness() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -302,7 +208,7 @@ class MapKTest : StringSpec({ } } - "zippyness1" { + @Test fun zippyness1() = runTest { checkAll( Arb.map(Arb.int(), Arb.int())) { xs -> @@ -310,23 +216,23 @@ class MapKTest : StringSpec({ } } - "zippyness2" { + @Test fun zipyness2() = runTest { checkAll( - Arb.map(Arb.int(), Arb.int())) { + Arb.map(Arb.int(), Arb.int(), maxSize = 30)) { xs -> xs.zip(xs).mapValues { it.value.second } shouldBe xs } } - "zippyness3" { + @Test fun zipyness3() = runTest { checkAll( - Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int()))) { + Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int()), maxSize = 30)) { xs -> xs.mapValues { it.value.first }.zip(xs.mapValues { it.value.second }) shouldBe xs } } - "distributivity1" { + @Test fun distributivity1() = runTest { checkAll( Arb.map3(Arb.int(), Arb.int(), Arb.int(), Arb.int()) ) {(x,y,z) -> @@ -355,7 +261,7 @@ class MapKTest : StringSpec({ } } - "distributivity2" { + @Test fun distributivity2() = runTest { checkAll( Arb.map3(Arb.int(), Arb.int(), Arb.int(), Arb.int()) ) {(x,y,z) -> @@ -374,7 +280,7 @@ class MapKTest : StringSpec({ } } - "distributivity3" { + @Test fun distributivity3() = runTest { checkAll( Arb.map3(Arb.int(), Arb.int(), Arb.int(), Arb.int()) ) {(x,y,z) -> @@ -393,9 +299,9 @@ class MapKTest : StringSpec({ } } - "unzip is the inverse of zip" { + @Test fun unzipInverseOfZip() = runTest { checkAll( - Arb.map(Arb.int(), Arb.int()) + Arb.map(Arb.int(), Arb.int(), maxSize = 30) ) { xs -> val ls = xs.zip(xs).unzip() val rs = xs to xs @@ -404,34 +310,34 @@ class MapKTest : StringSpec({ } } - "zip is the inverse of unzip" { + @Test fun zipInverseOfUnzip() = runTest { checkAll( - Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int())) + Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int()), maxSize = 30) ) { xs -> val (a,b) = xs.unzip() a.zip(b) shouldBe xs } } - "unzip with" { + @Test fun unzipWith() = runTest { checkAll( - Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int())) + Arb.map(Arb.int(), Arb.pair(Arb.int(), Arb.int()), maxSize = 30) ) { xs -> xs.unzip { it.value.first to it.value.second } shouldBe xs.unzip() } } - "unalign with" { + @Test fun unalignWith() = runTest { checkAll( - Arb.map(Arb.int(), Arb.ior(Arb.int(), Arb.int())) + Arb.map(Arb.int(), Arb.ior(Arb.int(), Arb.int()), maxSize = 30) ) { xs -> xs.unalign { it.value } shouldBe xs.unalign() } } - "getOrNone" { + @Test fun getOrNoneOk() = runTest { checkAll( - Arb.map(Arb.int(0 .. 1000), Arb.int()) + Arb.map(Arb.int(0 .. 1000), Arb.int(), maxSize = 30) ) { xs -> val (found, notFound) = (0 .. 1000).partition { xs.containsKey(it) } @@ -448,7 +354,7 @@ class MapKTest : StringSpec({ } } - "unalign is the inverse of align" { + @Test fun unalignInverseOfAlign() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -456,9 +362,9 @@ class MapKTest : StringSpec({ } } - "align is the inverse of unalign" { + @Test fun alignInverseOfUnalign() = runTest { checkAll( - Arb.map(Arb.int(), Arb.ior(Arb.int(), Arb.int())) + Arb.map(Arb.int(), Arb.ior(Arb.int(), Arb.int()), maxSize = 30) ) { xs -> val (a,b) = xs.unalign() @@ -466,7 +372,7 @@ class MapKTest : StringSpec({ } } - "padZip" { + @Test fun padZipOk() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -486,7 +392,7 @@ class MapKTest : StringSpec({ } } - "padZip with" { + @Test fun padZipWith() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()), Arb.functionABCToD(Arb.int()) @@ -495,30 +401,19 @@ class MapKTest : StringSpec({ } } - "salign" { + @Test fun salignOk() = runTest { checkAll( Arb.map2(Arb.int(), Arb.intSmall(), Arb.intSmall()) ) { (a, b) -> - a.salign(Semigroup.int(), b) shouldBe a.align(b) {it.value.fold(::identity, ::identity) { a, b -> a + b } } - } - } - - "void" { - checkAll( - Arb.map(Arb.intSmall(), Arb.intSmall()) - ) { a -> - val result = a.void() - - result.keys shouldBe a.keys - result.forAllValues { it shouldBe Unit } + a.salign(b, Int::plus) shouldBe a.align(b) {it.value.fold(::identity, ::identity) { a, b -> a + b } } } } - "filterMap" { + @Test fun mapNotNullOk() = runTest { checkAll( - Arb.map(Arb.int(), Arb.boolean()) + Arb.map(Arb.int(), Arb.boolean(), maxSize = 30) ) { xs -> - val rs = xs.filterMap { if(it) true else null } + val rs = xs.mapNotNull { (_, pred) -> if(pred) true else null } xs.forAll { if (it.value) @@ -529,9 +424,9 @@ class MapKTest : StringSpec({ } } - "filterOption" { + @Test fun filterOptionOk() = runTest { checkAll( - Arb.map(Arb.int(), Arb.option(Arb.int())) + Arb.map(Arb.int(), Arb.option(Arb.int()), maxSize = 30) ) { xs -> val rs = xs.filterOption() @@ -545,9 +440,9 @@ class MapKTest : StringSpec({ } } - "filterInstance" { + @Test fun filterInstanceOk() = runTest { checkAll( - Arb.map(Arb.int(), Arb.choice(Arb.int(), Arb.int())) + Arb.map(Arb.int(), Arb.choice(Arb.int(), Arb.int()), maxSize = 30) ) { xs -> val a = xs.filterIsInstance() val b = xs.filterIsInstance() @@ -556,19 +451,19 @@ class MapKTest : StringSpec({ } } - "filterInstance: identity" { - checkAll(Arb.map(Arb.int(), Arb.int())) { xs -> + @Test fun filterInstanceIdentity() = runTest { + checkAll(Arb.map(Arb.int(), Arb.int(), maxSize = 30)) { xs -> xs.filterIsInstance() shouldBe xs } } - "filterInstance: identity with null" { - checkAll(Arb.map(Arb.int(), Arb.int().orNull())) { xs -> + @Test fun filterInstanceIdentityNull() = runTest { + checkAll(Arb.map(Arb.int(), Arb.int().orNull(), maxSize = 30)) { xs -> xs.filterIsInstance() shouldBe xs } } - "zip2" { + @Test fun zip2Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -581,7 +476,7 @@ class MapKTest : StringSpec({ } } - "zip2 with nullables" { + @Test fun zip2Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -594,7 +489,7 @@ class MapKTest : StringSpec({ } } - "zip3" { + @Test fun zip3Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -608,7 +503,7 @@ class MapKTest : StringSpec({ } } - "zip3 with nullables" { + @Test fun zip3Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -621,7 +516,7 @@ class MapKTest : StringSpec({ } } - "zip4" { + @Test fun zip4Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -635,7 +530,7 @@ class MapKTest : StringSpec({ } } - "zip4 with nullables" { + @Test fun zip4Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -648,7 +543,7 @@ class MapKTest : StringSpec({ } } - "zip5" { + @Test fun zip5Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -662,7 +557,7 @@ class MapKTest : StringSpec({ } } - "zip5 with nullables" { + @Test fun zip5Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -675,7 +570,7 @@ class MapKTest : StringSpec({ } } - "zip6" { + @Test fun zip6Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -689,7 +584,7 @@ class MapKTest : StringSpec({ } } - "zip6 with nullables" { + @Test fun zip6Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -702,7 +597,7 @@ class MapKTest : StringSpec({ } } - "zip7" { + @Test fun zip7Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -716,7 +611,7 @@ class MapKTest : StringSpec({ } } - "zip7 with nullables" { + @Test fun zip7Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -729,7 +624,7 @@ class MapKTest : StringSpec({ } } - "zip8" { + @Test fun zip8Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -744,7 +639,7 @@ class MapKTest : StringSpec({ } } - "zip8 with nullables" { + @Test fun zip8Null() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -757,7 +652,7 @@ class MapKTest : StringSpec({ } } - "zip9" { + @Test fun zip9Ok() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -783,85 +678,7 @@ class MapKTest : StringSpec({ } } - "zip9 with nullables" { - checkAll( - Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) - ) { (mapA, mapB) -> - val result = mapA.zip(mapB, mapB, mapB, mapB, mapB, mapB, mapB, mapB) { _, aa, bb, cc, dd, ee, ff, gg, hh, ii -> - Tuple9( - aa, - bb, - cc, - dd, - ee, - ff, - gg, - hh, - ii - ) - } - val expected = mapA.filter { (k, _) -> mapB.containsKey(k) } - .map { (k, v) -> Pair(k, Tuple9(v, mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k])) } - .toMap() - - result shouldBe expected - } - } - - "zip10" { - checkAll( - Arb.map2(Arb.int(), Arb.int(), Arb.int()) - ) { (a, b) -> - val result = a.zip(b, b, b, b, b, b, b, b, b) { _, aa, bb, cc, dd, ee, ff, gg, hh, ii, jj -> - Tuple10( - aa, - bb, - cc, - dd, - ee, - ff, - gg, - hh, - ii, - jj - ) - } - - val expected = a.filter { (k, _) -> b.containsKey(k) } - .map { (k, v) -> Pair(k, Tuple10(v, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!, b[k]!!)) } - .toMap() - - result shouldBe expected - } - } - - "zip10 with nullables" { - checkAll( - Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) - ) { (mapA, mapB) -> - val result = mapA.zip(mapB, mapB, mapB, mapB, mapB, mapB, mapB, mapB, mapB) { _, aa, bb, cc, dd, ee, ff, gg, hh, ii, jj -> - Tuple10( - aa, - bb, - cc, - dd, - ee, - ff, - gg, - hh, - ii, - jj - ) - } - val expected = mapA.filter { (k, _) -> mapB.containsKey(k) } - .map { (k, v) -> Pair(k, Tuple10(v, mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k], mapB[k])) } - .toMap() - - result shouldBe expected - } - } - - "flatMap" { + @Test fun flatMapOk() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int()) ) { (a, b) -> @@ -873,7 +690,7 @@ class MapKTest : StringSpec({ } } - "mapOrAccumulate of empty should be empty" { + @Test fun mapOrAccumulateEmpty() = runTest { val result: Either, Map> = emptyMap().mapOrAccumulate { it.value.toString() } @@ -882,9 +699,9 @@ class MapKTest : StringSpec({ .value.shouldBeEmpty() } - "mapOrAccumulate can map" { + @Test fun mapOrAccumulateMaps() = runTest { checkAll( - Arb.map(Arb.int(), Arb.int()) + Arb.map(Arb.int(), Arb.int(), maxSize = 30) ) { xs -> val result: Either, Map> = xs.mapOrAccumulate { @@ -897,9 +714,9 @@ class MapKTest : StringSpec({ } } - "mapOrAccumulate accumulates errors" { + @Test fun mapOrAccumulateAccumulates() = runTest { checkAll( - Arb.map(Arb.int(), Arb.int(), minSize = 1) + Arb.map(Arb.int(), Arb.int(), minSize = 1, maxSize = 30) ) { xs -> xs.mapOrAccumulate { raise(it.value) @@ -908,7 +725,7 @@ class MapKTest : StringSpec({ } } - "flatMap with nullables" { + @Test fun flatMapNull() = runTest { checkAll( Arb.map2(Arb.int(), Arb.int(), Arb.int().orNull()) ) { (mapA, mapB) -> @@ -919,4 +736,4 @@ class MapKTest : StringSpec({ result shouldBe expected } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt index 2b7ef66ec8e..29023d96cab 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt @@ -1,12 +1,8 @@ package arrow.core -import arrow.core.test.laws.SemigroupLaws import arrow.core.test.nonEmptyList import arrow.core.test.stackSafeIteration -import arrow.core.test.testLaws -import arrow.typeclasses.Semigroup import io.kotest.assertions.withClue -import io.kotest.core.spec.style.StringSpec import io.kotest.inspectors.shouldForAll import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.nulls.shouldBeNull @@ -15,494 +11,395 @@ import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.* import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest import kotlin.math.max import kotlin.math.min +import kotlin.test.Test -class NonEmptyListTest : StringSpec({ +class NonEmptyListTest { - testLaws(SemigroupLaws("NonEmptyList", NonEmptyList::plus, Arb.nonEmptyList(Arb.int()))) - - "iterable.toNonEmptyListOrNull should round trip" { - checkAll(Arb.nonEmptyList(Arb.int())) { nonEmptyList -> - nonEmptyList.all.toNonEmptyListOrNull().shouldNotBeNull() shouldBe nonEmptyList - } - } - - "iterable.toNonEmptyListOrNull should return null for an empty iterable" { - listOf().toNonEmptyListOrNull().shouldBeNull() + @Test + fun nonEmptyList() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { nel1, nel2, nel3 -> + (nel1 + nel2) + nel3 shouldBe nel1 + (nel2 + nel3) } + } - "iterable.toNonEmptyListOrNull should work correctly when the iterable starts with or contains null" { - checkAll(Arb.nonEmptyList(Arb.int().orNull())) { nonEmptyList -> - nonEmptyList.all.toNonEmptyListOrNull().shouldNotBeNull() shouldBe nonEmptyList - } + @Test + fun iterableToNonEmptyListOrNullShouldRoundTrip() = runTest { + checkAll(Arb.nonEmptyList(Arb.int())) { nonEmptyList -> + nonEmptyList.all.toNonEmptyListOrNull().shouldNotBeNull() shouldBe nonEmptyList } + } - "iterable.toNonEmptyListOrNone should round trip" { - checkAll(Arb.nonEmptyList(Arb.int())) { nonEmptyList -> - nonEmptyList.all.toNonEmptyListOrNone() shouldBe nonEmptyList.some() - } + @Test + fun iterableToNonEmptyListOrNoneShouldRoundTrip() = runTest { + checkAll(Arb.nonEmptyList(Arb.int())) { nonEmptyList -> + nonEmptyList.all.toNonEmptyListOrNone() shouldBe nonEmptyList.some() } + } - "flatten" { - checkAll(Arb.nonEmptyList(Arb.int())) { nel -> - nonEmptyListOf(nel).flatten() shouldBe nel - } - } + @Test + fun iterableToNonEmptyListOrNullShouldReturnNullForAnEmptyIterable() = runTest { + listOf().toNonEmptyListOrNull().shouldBeNull() + } - "traverse for Either stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..stackSafeIteration()).toNonEmptyListOrNull()?.traverse { a -> - acc.add(a) - Either.Right(a) + @Test + fun iterableToNonEmptyListOrNullShouldWorkCorrectlyWhenTheIterableStartsWithOrContainsNull() = runTest { + checkAll(Arb.list(Arb.int())) { list -> + checkAll(iterations = 5, Arb.int(min = 0, max = list.size)) { ix -> + val mutableList: MutableList = list.toMutableList() + mutableList.add(ix, null) + mutableList.toNonEmptyListOrNull().shouldNotBeNull() shouldBe mutableList } - res shouldBe Either.Right(acc.toNonEmptyListOrNull()) - res shouldBe Either.Right((0..stackSafeIteration()).toNonEmptyListOrNull()) } + } - "traverse for Either short-circuit" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { - if (it % 2 == 0) { - acc.add(it) - Either.Right(it) - } else Either.Left(it) - } - acc shouldBe ints.takeWhile { it % 2 == 0 } - when (evens) { - is Either.Right -> evens.value shouldBe ints - is Either.Left -> evens.value shouldBe ints.first { it % 2 != 0 } - } - } - } - - "sequence for Either should be consistent with traverseEither" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - fun onlyEven(i: Int) = if (i % 2 == 0) Either.Right(i) else Either.Left(i) - ints.map { onlyEven(it) }.sequence() shouldBe ints.traverse { onlyEven(it) } - } - } + @Test + fun canAlignListsWithDifferentLengths() = runTest { + checkAll(Arb.nonEmptyList(Arb.boolean()), Arb.nonEmptyList(Arb.boolean())) { a, b -> + val result = a.align(b) - "traverse for Option is stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..stackSafeIteration()).toNonEmptyListOrNull()?.traverse { a -> - acc.add(a) - Some(a) + result.size shouldBe max(a.size, b.size) + result.take(min(a.size, b.size)).shouldForAll { + it.isBoth() shouldBe true } - res shouldBe Some(acc.toNonEmptyListOrNull()) - res shouldBe Some((0..stackSafeIteration()).toNonEmptyListOrNull()) - } - - "traverse for Option short-circuits" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - val acc = mutableListOf() - val evens = ints.traverse { a -> - if ((a % 2 == 0)) { - acc.add(a) - Some(a) - } else { - None - } + result.drop(min(a.size, b.size)).shouldForAll { + if (a.size < b.size) { + it.isRight() shouldBe true + } else { + it.isLeft() shouldBe true } - acc shouldBe ints.takeWhile { it % 2 == 0 } - evens.fold({ Unit }) { it shouldBe ints } } } + } - "sequence for Option yields some when all entries in the list are some" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - val evens = ints.map { a -> - if ((a % 2 == 0)) { - Some(a) - } else { - None - } - }.sequence() - evens.fold({ Unit }) { it shouldBe ints } + @Test + fun mapOrAccumulateIsStackSafeAndRunsInOriginalOrder() = runTest { + val acc = mutableListOf() + val res = (0..stackSafeIteration()) + .toNonEmptyListOrNull()!! + .mapOrAccumulate(String::plus) { + acc.add(it) + it } - } + res shouldBe Either.Right(acc) + res shouldBe Either.Right((0..stackSafeIteration()).toList()) + } - "sequence for Option should be consistent with traverseOption" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - ints.map { a-> - if ((a % 2 == 0)) { - Some(a) - } else { - None - } - }.sequence() shouldBe - ints.traverse { a-> - if ((a % 2 == 0)) { - Some(a) - } else { - None - } - } + @Test + fun mapOrAccumulateAccumulatesErrors() = runTest { + checkAll(Arb.nonEmptyList(Arb.int(), range = 0 .. 20)) { nel -> + val res = nel.mapOrAccumulate { i -> + if (i % 2 == 0) i else raise(i) } - } - - "traverse for Validated is stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..stackSafeIteration()) - .toNonEmptyListOrNull()?.traverse(Semigroup.string()) { - acc.add(it) - Validated.Valid(it) - } - res shouldBe Validated.Valid(acc) - res shouldBe Validated.Valid((0..stackSafeIteration()).toList()) - } - - "traverse for Validated accumulates" { - checkAll(Arb.nonEmptyList(Arb.int())) { ints -> - val res: ValidatedNel> = - ints.traverse(Semigroup.nonEmptyList()) { i: Int -> if (i % 2 == 0) i.validNel() else i.invalidNel() } - val expected: ValidatedNel> = - ints.filterNot { it % 2 == 0 }.toNonEmptyListOrNull()?.invalid() ?: ints.filter { it % 2 == 0 }.toNonEmptyListOrNull()!!.valid() + val expected = nel.filterNot { it % 2 == 0 } + .toNonEmptyListOrNull()?.left() ?: nel.filter { it % 2 == 0 }.right() - res shouldBe expected - } + res shouldBe expected } + } - "can align lists with different lengths" { - checkAll(Arb.nonEmptyList(Arb.boolean()), Arb.nonEmptyList(Arb.boolean())) { a, b -> - val result = a.align(b) + @Test + fun mapOrAccumulateAccumulatesErrorsWithCombineFunction() = runTest { + checkAll(Arb.nonEmptyList(Arb.negativeInt(), range = 0 .. 20)) { nel -> + val res = nel.mapOrAccumulate(String::plus) { i -> + if (i > 0) i else raise("Negative") + } + + res shouldBe nel.map { "Negative" }.joinToString("").left() + } + } - result.size shouldBe max(a.size, b.size) - result.take(min(a.size, b.size)).shouldForAll { - it.isBoth() shouldBe true - } - result.drop(min(a.size, b.size)).shouldForAll { - if (a.size < b.size) { - it.isRight() shouldBe true - } else { - it.isLeft() shouldBe true - } - } - } - } - - "mapOrAccumulate is stack-safe, and runs in original order" { - val acc = mutableListOf() - val res = (0..stackSafeIteration()) - .toNonEmptyListOrNull()!! - .mapOrAccumulate(String::plus) { - acc.add(it) - it - } - res shouldBe Either.Right(acc) - res shouldBe Either.Right((0..stackSafeIteration()).toList()) - } - - "mapOrAccumulate accumulates errors" { - checkAll(Arb.nonEmptyList(Arb.int())) { nel -> - val res = nel.mapOrAccumulate { i -> - if (i % 2 == 0) i else raise(i) - } - - val expected = nel.filterNot { it % 2 == 0 } - .toNonEmptyListOrNull()?.left() ?: nel.filter { it % 2 == 0 }.right() - - res shouldBe expected - } - } - - "mapOrAccumulate accumulates errors with combine function" { - checkAll(Arb.nonEmptyList(Arb.negativeInt())) { nel -> - val res = nel.mapOrAccumulate(String::plus) { i -> - if (i > 0) i else raise("Negative") - } - - res shouldBe nel.map { "Negative" }.joinToString("").left() - } - } - - "padZip" { - checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> - val result = a.padZip(b) - val left = a + List(max(0, b.size - a.size)) { null } - val right = b + List(max(0, a.size - b.size)) { null } - - result shouldBe left.zip(right) - } - } - - "padZip with transformation" { - checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> - val result = a.padZip(b, { it * 2 }, { it * 3 }, { x, y -> x + y }) - - val minSize = min(a.size, b.size) - result.size shouldBe max(a.size, b.size) - result.take(minSize) shouldBe a.take(minSize).zip(b.take(minSize)) { x, y -> x + y } - - if (a.size > b.size) - result.drop(minSize) shouldBe a.drop(minSize).map { it * 2 } - else - result.drop(minSize) shouldBe b.drop(minSize).map { it * 3 } - } - } - - "unzip is the inverse of zip" { - checkAll(Arb.nonEmptyList(Arb.int())) { nel -> - val zipped = nel.zip(nel) - val left = zipped.map { it.first } - val right = zipped.map { it.second } - - left shouldBe nel - right shouldBe nel - } - } - - "unzip with split function" { - checkAll(Arb.nonEmptyList(Arb.pair(Arb.int(), Arb.int()))) { nel -> - val unzipped = nel.unzip(::identity) - - unzipped.first shouldBe nel.map { it.first } - unzipped.second shouldBe nel.map { it.second } - } - } - - "zip2" { - checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> - val result = a.zip(b) - val expected = a.all.zip(b.all).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip3" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c -> - val result = a.zip(b, c, ::Triple) - val expected = a.all.zip(b.all, c.all, ::Triple).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip4" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d -> - val result = a.zip(b, c, d, ::Tuple4) - val expected = a.all.zip(b.all, c.all, d.all, ::Tuple4).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip5" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e -> - val result = a.zip(b, c, d, e, ::Tuple5) - val expected = a.all.zip(b.all, c.all, d.all, e.all, ::Tuple5).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip6" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e, f -> - val result = a.zip(b, c, d, e, f, ::Tuple6) - val expected = - a.all.zip(b.all, c.all, d.all, e.all, f.all, ::Tuple6).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip7" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e, f, g -> - val result = a.zip(b, c, d, e, f, g, ::Tuple7) - val expected = - a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, ::Tuple7).toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip8" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e, f, g, h -> - val result = a.zip(b, c, d, e, f, g, h, ::Tuple8) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, ::Tuple8) - .toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip9" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e, f, g, h, i -> - val result = a.zip(b, c, d, e, f, g, h, i, ::Tuple9) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, ::Tuple9) - .toNonEmptyListOrNull() - result shouldBe expected - } - } - - "zip10" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()), - Arb.nonEmptyList(Arb.int()) - ) { a, b, c, d, e, f, g, h, i, j -> - val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) - val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, j.all, ::Tuple10) - .toNonEmptyListOrNull() - result shouldBe expected - } - } - - "max element" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.max() - val expected = a.maxOrNull() - result shouldBe expected - } - } - - "maxBy element" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.maxBy(::identity) - val expected = a.maxByOrNull(::identity) - result shouldBe expected - } - } - - "min element" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.min() - val expected = a.minOrNull() - result shouldBe expected - } - } - - "minBy element" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.minBy(::identity) - val expected = a.minByOrNull(::identity) - result shouldBe expected - } - } - - "NonEmptyList equals List" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - withClue("$a should be equal to ${a.all}") { - // `shouldBe` doesn't use the `equals` methods on `Iterable` - (a == a.all).shouldBeTrue() - } - } - } - - "lastOrNull" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.lastOrNull() - val expected = a.last() - result shouldBe expected - } - } - - "extract" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.extract() - val expected = a.head - result shouldBe expected - } - } - - "plus" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.int() - ) { a, b -> - val result = a + b - val expected = a.all + b - result shouldBe expected - } - } - - "coflatMap should retain the same length as the original list" { - checkAll( - Arb.nonEmptyList(Arb.int()) - ) { a -> - val result = a.coflatMap { it.all } - val expected = a.all - result.size shouldBe expected.size - } - } - - "foldLeft should sum up correctly for addition" { - checkAll( - Arb.nonEmptyList(Arb.int()), - Arb.int() - ) { list, initial -> - val result = list.foldLeft(initial) { acc, i -> acc + i } - val expected = initial + list.all.sum() - result shouldBe expected - } - } -}) + @Test + fun padZip() = runTest { + checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> + val result = a.padZip(b) + val left = a + List(max(0, b.size - a.size)) { null } + val right = b + List(max(0, a.size - b.size)) { null } + + result shouldBe left.zip(right) + } + } + + @Test + fun padZipWithTransformation() = runTest { + checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> + val result = a.padZip(b, { it * 2 }, { it * 3 }, { x, y -> x + y }) + + val minSize = min(a.size, b.size) + result.size shouldBe max(a.size, b.size) + result.take(minSize) shouldBe a.take(minSize).zip(b.take(minSize)) { x, y -> x + y } + + if (a.size > b.size) + result.drop(minSize) shouldBe a.drop(minSize).map { it * 2 } + else + result.drop(minSize) shouldBe b.drop(minSize).map { it * 3 } + } + } + + @Test + fun unzipIsTheInverseOfZip() = runTest { + checkAll(Arb.nonEmptyList(Arb.int())) { nel -> + val zipped = nel.zip(nel) + val left = zipped.map { it.first } + val right = zipped.map { it.second } + + left shouldBe nel + right shouldBe nel + } + } + + @Test + fun unzipWithSplitFunction() = runTest { + checkAll(Arb.nonEmptyList(Arb.pair(Arb.int(), Arb.int()))) { nel -> + val unzipped = nel.unzip(::identity) + + unzipped.first shouldBe nel.map { it.first } + unzipped.second shouldBe nel.map { it.second } + } + } + + @Test + fun zip2() = runTest { + checkAll(Arb.nonEmptyList(Arb.int()), Arb.nonEmptyList(Arb.int())) { a, b -> + val result = a.zip(b) + val expected = a.all.zip(b.all).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip3() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c -> + val result = a.zip(b, c, ::Triple) + val expected = a.all.zip(b.all, c.all, ::Triple).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip4() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d -> + val result = a.zip(b, c, d, ::Tuple4) + val expected = a.all.zip(b.all, c.all, d.all, ::Tuple4).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip5() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d, e -> + val result = a.zip(b, c, d, e, ::Tuple5) + val expected = a.all.zip(b.all, c.all, d.all, e.all, ::Tuple5).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip6() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d, e, f -> + val result = a.zip(b, c, d, e, f, ::Tuple6) + val expected = + a.all.zip(b.all, c.all, d.all, e.all, f.all, ::Tuple6).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip7() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d, e, f, g -> + val result = a.zip(b, c, d, e, f, g, ::Tuple7) + val expected = + a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, ::Tuple7).toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip8() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d, e, f, g, h -> + val result = a.zip(b, c, d, e, f, g, h, ::Tuple8) + val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, ::Tuple8) + .toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun zip9() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()), + Arb.nonEmptyList(Arb.int()) + ) { a, b, c, d, e, f, g, h, i -> + val result = a.zip(b, c, d, e, f, g, h, i, ::Tuple9) + val expected = a.all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, ::Tuple9) + .toNonEmptyListOrNull() + result shouldBe expected + } + } + + @Test + fun maxElement() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.max() + val expected = a.maxOrNull() + result shouldBe expected + } + } + + @Test + fun maxByElement() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.maxBy(::identity) + val expected = a.maxByOrNull(::identity) + result shouldBe expected + } + } + + @Test + fun minElement() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.min() + val expected = a.minOrNull() + result shouldBe expected + } + } + + @Test + fun minByElement() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.minBy(::identity) + val expected = a.minByOrNull(::identity) + result shouldBe expected + } + } + + @Test + fun nonEmptyListEqualsList() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + withClue("$a should be equal to ${a.all}") { + // `shouldBe` doesn't use the `equals` methods on `Iterable` + (a == a.all).shouldBeTrue() + } + } + } + + @Test + fun lastOrNull() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.lastOrNull() + val expected = a.last() + result shouldBe expected + } + } + + @Test + fun extract() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.extract() + val expected = a.head + result shouldBe expected + } + } + + @Test + fun plus() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.int() + ) { a, b -> + val result = a + b + val expected = a.all + b + result shouldBe expected + } + } + + @Test + fun coflatMapKeepsLength() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()) + ) { a -> + val result = a.coflatMap { it.all } + val expected = a.all + result.size shouldBe expected.size + } + } + + @Test + fun foldLeftAddition() = runTest { + checkAll( + Arb.nonEmptyList(Arb.int()), + Arb.int() + ) { list, initial -> + val result = list.foldLeft(initial) { acc, i -> acc + i } + val expected = initial + list.all.sum() + result shouldBe expected + } + } +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt index df83f8a5221..8d04c5990a1 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt @@ -2,7 +2,6 @@ package arrow.core import arrow.core.test.nonEmptySet import io.kotest.assertions.withClue -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.booleans.shouldBeTrue import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.nulls.shouldNotBeNull @@ -12,46 +11,48 @@ import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.next import io.kotest.property.arbitrary.orNull import io.kotest.property.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class NonEmptySetTest : StringSpec({ +class NonEmptySetTest { - "iterable.toNonEmptySetOrNull should round trip" { + @Test fun iterableToNonEmptySetOrNullShouldRoundTrip() = runTest { checkAll(Arb.nonEmptySet(Arb.int())) { nonEmptySet -> nonEmptySet.toNonEmptySetOrNull().shouldNotBeNull() shouldBe nonEmptySet } } - "iterable.toNonEmptySetOrNull should return null for an empty iterable" { + @Test fun iterableToNonEmptySetOrNullShouldReturnNullForEmptyIterable() = runTest { listOf().toNonEmptySetOrNull().shouldBeNull() } - "iterable.toNonEmptySetOrNull should work correctly when the iterable starts with or contains null" { + @Test fun iterableToNonEmptySetOrNullShouldReturnWorkWhenContainingNull() = runTest { checkAll(Arb.nonEmptySet(Arb.int().orNull())) { nonEmptySet -> nonEmptySet.toNonEmptySetOrNull().shouldNotBeNull() shouldBe nonEmptySet } } - "iterable.toNonEmptySetOrNone should round trip" { + @Test fun iterableToNonEmptySetOrNoneShouldRoundTrip() = runTest { checkAll(Arb.nonEmptySet(Arb.int())) { nonEmptySet -> nonEmptySet.toNonEmptySetOrNone() shouldBe nonEmptySet.some() } } - "emptyList.toNonEmptySetOrNull should be null" { + @Test fun emptyListToNonEmptySetOrNullShouldBeNull() = runTest { listOf().toNonEmptySetOrNull() shouldBe null } - "emptyList.toNonEmptySetOrNone should be none" { + @Test fun emptyListToNonEmptySetOrNoneShouldBeNone() = runTest { listOf().toNonEmptySetOrNone() shouldBe none() } - "adding an element already present doesn't change the set" { + @Test fun addingAnElementAlreadyPresentDoesNotChangeTheSet() = runTest { val element = Arb.int().next() val initialSet: NonEmptySet = nonEmptySetOf(element) + Arb.nonEmptySet(Arb.int()).next() initialSet.plus(element) shouldBe initialSet } - "NonEmptySet equals Set" { + @Test fun nonEmptySetEqualsSet() = runTest { checkAll( Arb.nonEmptySet(Arb.int()) ) { nes -> @@ -63,7 +64,7 @@ class NonEmptySetTest : StringSpec({ } } - "NonEmptySet equals NonEmptySet" { + @Test fun nonEmptySetEqualsNonEmptySet() = runTest { checkAll( Arb.nonEmptySet(Arb.int()) ) { nes -> @@ -74,5 +75,5 @@ class NonEmptySetTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonFatalTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonFatalTest.kt index 541e500ecc8..054574958ac 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonFatalTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonFatalTest.kt @@ -1,9 +1,9 @@ package arrow.core -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlin.test.Test -class NonFatalTest : StringSpec({ +class NonFatalTest { val nonFatals: List = listOf( RuntimeException(), @@ -12,14 +12,16 @@ class NonFatalTest : StringSpec({ NotImplementedError() ) - "Test nonfatals using #invoke()" { + @Test + fun usingInvoke() { nonFatals.forEach { NonFatal(it) shouldBe true } } - "Test nonfatals using Throwable#nonFatalOrThrow" { + + @Test fun usingNotFatalOrThrow() { nonFatals.forEach { it.nonFatalOrThrow() shouldBe it } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NullableTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NullableTest.kt deleted file mode 100644 index 3d3a61eda76..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NullableTest.kt +++ /dev/null @@ -1,198 +0,0 @@ -@file:Suppress("NAME_SHADOWING") - -package arrow.core - -import arrow.core.test.intSmall -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldBeNull -import io.kotest.property.Arb -import io.kotest.matchers.shouldBe -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.orNull -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll - -class NullableTest : StringSpec({ - "map1 short circuits if any arg is null" { - Nullable.zip(null) { Unit }.shouldBeNull() - } - - "map1 performs action when arg is not null" { - checkAll(Arb.intSmall()) { a -> - Nullable.zip(a) { it + 1 } shouldBe a + 1 - } - } - - "map2 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05) - ) { a: String?, b: String? -> - if (a == null || b == null) Nullable.zip(a, b) { _, _ -> Unit } shouldBe null - else Nullable.zip(a, b) { a, b -> a + b } shouldBe a + b - } - } - - "map3 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05) - ) { a: String?, b: String?, c: String? -> - if (a == null || b == null || c == null) Nullable.zip(a, b, c) { a, b, c -> a + b + c } shouldBe null - else Nullable.zip(a, b, c) { a, b, c -> a + b + c } shouldBe a + b + c - } - } - - "map4 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - ) { a: String?, b: String?, c: String?, d: String? -> - if (a == null || b == null || c == null || d == null) Nullable.zip( - a, - b, - c, - d - ) { a, b, c, d -> a + b + c + d } shouldBe null - else Nullable.zip(a, b, c, d) { a, b, c, d -> a + b + c + d } shouldBe a + b + c + d - } - } - - "map5 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - ) { a: String?, b: String?, c: String?, d: String?, e: String? -> - if (a == null || b == null || c == null || d == null || e == null) Nullable.zip( - a, - b, - c, - d, - e - ) { _, _, _, _, _ -> Unit } shouldBe null - else Nullable.zip(a, b, c, d, e) { a, b, c, d, e -> a + b + c + d + e } shouldBe a + b + c + d + e - } - } - - "map6 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - ) { a: String?, b: String?, c: String?, d: String?, e: String?, f: String? -> - if (a == null || b == null || c == null || d == null || e == null || f == null) Nullable.zip( - a, - b, - c, - d, - e, - f - ) { _, _, _, _, _, _ -> Unit } shouldBe null - else Nullable.zip(a, b, c, d, e, f) { a, b, c, d, e, f -> a + b + c + d + e + f } shouldBe a + b + c + d + e + f - } - } - - "map7 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - ) { a: String?, b: String?, c: String?, d: String?, e: String?, f: String?, g: String? -> - if (a == null || b == null || c == null || d == null || e == null || f == null || g == null) Nullable.zip( - a, - b, - c, - d, - e, - f, - g - ) { _, _, _, _, _, _, _ -> Unit } shouldBe null - else Nullable.zip( - a, - b, - c, - d, - e, - f, - g - ) { a, b, c, d, e, f, g -> a + b + c + d + e + f + g } shouldBe a + b + c + d + e + f + g - } - } - - "map8 only performs action when all arguments are not null" { - checkAll( - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - Arb.string().orNull(0.05), - ) { a: String?, b: String?, c: String?, d: String?, e: String?, f: String?, g: String?, h: String? -> - if (a == null || b == null || c == null || d == null || e == null || f == null || g == null || h == null) Nullable.zip( - a, - b, - c, - d, - e, - f, - g, - h - ) { _, _, _, _, _, _, _, _ -> Unit } shouldBe null - else Nullable.zip( - a, - b, - c, - d, - e, - f, - g, - h - ) { a, b, c, d, e, f, g, h -> a + b + c + d + e + f + g + h } shouldBe a + b + c + d + e + f + g + h - } - } - - "map9 only performs action when all arguments are not null" { - checkAll( - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05), - Arb.int().orNull(0.05) - ) { a: Int?, b: Int?, c: Int?, d: Int?, e: Int?, f: Int?, g: Int?, h: Int?, i: Int? -> - if (a == null || b == null || c == null || d == null || e == null || f == null || g == null || h == null || i == null) { - Nullable.zip(a, b, c, d, e, f, g, h, i) { _, _, _, _, _, _, _, _, _ -> Unit } shouldBe null - } else { - Nullable.zip( - a, - b, - c, - d, - e, - f, - g, - h, - i - ) { a, b, c, d, e, f, g, h, i -> a + b + c + d + e + f + g + h + i } shouldBe a + b + c + d + e + f + g + h + i - } - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/OptionTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/OptionTest.kt index cd1406c80a8..16e7e3f4fc3 100755 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/OptionTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/OptionTest.kt @@ -1,11 +1,9 @@ package arrow.core -import arrow.core.continuations.ensureNotNull -import arrow.core.continuations.option +import arrow.core.raise.option import arrow.core.test.laws.MonoidLaws import arrow.core.test.option import arrow.core.test.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe import io.kotest.property.Arb @@ -15,498 +13,338 @@ import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class OptionTest : StringSpec({ +class OptionTest { val some: Option = Some("kotlin") val none: Option = None - testLaws( - MonoidLaws("Option", None, { x, y -> x.combine(y, Int::plus) }, Arb.option(Arb.int())) - ) + @Test fun testMonoidLaws() = testLaws( + MonoidLaws("Option", None, { x, y -> x.combine(y, Int::plus) }, Arb.option(Arb.int())) + ) - "ensure null in option computation" { - checkAll(Arb.boolean(), Arb.int()) { predicate, i -> - option { - ensure(predicate) - i - } shouldBe if (predicate) Some(i) else None - } - } - - "ensureNotNull in option computation" { - fun square(i: Int): Int = i * i - checkAll(Arb.int().orNull()) { i: Int? -> - option { - ensureNotNull(i) - square(i) // Smart-cast by contract - } shouldBe i.toOption().map(::square) - } - } - - "short circuit null" { + @Test fun ensureNullInOptionComputation() = runTest { + checkAll(Arb.boolean(), Arb.int()) { predicate, i -> option { - val number: Int = "s".length - ensureNotNull(number.takeIf { it > 1 }) - throw IllegalStateException("This should not be executed") - } shouldBe None - } - - "tap applies effects returning the original value" { - checkAll(Arb.option(Arb.long())) { option -> - var effect = 0 - val res = option.tap { effect += 1 } - val expected = when (option) { - is Some -> 1 - is None -> 0 - } - effect shouldBe expected - res shouldBe option - } - } - - "tapNone applies effects returning the original value" { - checkAll(Arb.option(Arb.long())) { option -> - var effect = 0 - val res = option.tapNone { effect += 1 } - val expected = when (option) { - is Some -> 0 - is None -> 1 - } - effect shouldBe expected - res shouldBe option - } - } - - "fromNullable should work for both null and non-null values of nullable types" { - checkAll(Arb.int().orNull()) { a: Int? -> - // This seems to be generating only non-null values, so it is complemented by the next test - val o: Option = Option.fromNullable(a) - if (a == null) o shouldBe None else o shouldBe Some(a) - } - } - - "fromNullable should return none for null values of nullable types" { - val a: Int? = null - Option.fromNullable(a) shouldBe None - } - - "getOrElse" { - some.getOrElse { "java" } shouldBe "kotlin" - none.getOrElse { "java" } shouldBe "java" - } - - "orNull" { - some.orNull() shouldNotBe null - none.orNull() shouldBe null - } - - "map" { - some.map(String::uppercase) shouldBe Some("KOTLIN") - none.map(String::uppercase) shouldBe None - } - - "zip" { - checkAll(Arb.int()) { a: Int -> - val op: Option = a.some() - some.zip(op) { a, b -> a + b } shouldBe Some("kotlin$a") - none.zip(op) { a, b -> a + b } shouldBe None - some.zip(op) shouldBe Some(Pair("kotlin", a)) - } - } - - "mapNotNull" { - some.mapNotNull { it.toIntOrNull() } shouldBe None - some.mapNotNull { it.uppercase() } shouldBe Some("KOTLIN") - } - - "fold" { - some.fold({ 0 }) { it.length } shouldBe 6 - none.fold({ 0 }) { it.length } shouldBe 0 - } - - "flatMap" { - some.flatMap { Some(it.uppercase()) } shouldBe Some("KOTLIN") - none.flatMap { Some(it.uppercase()) } shouldBe None - } - - "align" { - some align some shouldBe Some(Ior.Both("kotlin", "kotlin")) - some align none shouldBe Some(Ior.Left("kotlin")) - none align some shouldBe Some(Ior.Right("kotlin")) - none align none shouldBe None - - some.align(some) { "$it" } shouldBe Some("Ior.Both(kotlin, kotlin)") - some.align(none) { "$it" } shouldBe Some("Ior.Left(kotlin)") - none.align(some) { "$it" } shouldBe Some("Ior.Right(kotlin)") - none.align(none) { "$it" } shouldBe None - - val nullable = null.some() - some align nullable shouldBe Some(Ior.Both("kotlin", null)) - nullable align some shouldBe Some(Ior.Both(null, "kotlin")) - nullable align nullable shouldBe Some(Ior.Both(null, null)) - - some.align(nullable) { "$it" } shouldBe Some("Ior.Both(kotlin, null)") - nullable.align(some) { "$it" } shouldBe Some("Ior.Both(null, kotlin)") - nullable.align(nullable) { "$it" } shouldBe Some("Ior.Both(null, null)") - } - - "filter" { - some.filter { it == "java" } shouldBe None - none.filter { it == "java" } shouldBe None - some.filter { it.startsWith('k') } shouldBe Some("kotlin") - } - - "filterNot" { - some.filterNot { it == "java" } shouldBe Some("kotlin") - none.filterNot { it == "java" } shouldBe None - some.filterNot { it.startsWith('k') } shouldBe None - } - - "filterIsInstance" { - val someAny: Option = some - someAny.filterIsInstance() shouldBe Some("kotlin") - someAny.filterIsInstance() shouldBe None - - val someNullableAny: Option = null.some() - someNullableAny.filterIsInstance() shouldBe Some(null) - someNullableAny.filterIsInstance() shouldBe None - - val noneAny: Option = none - noneAny.filterIsInstance() shouldBe None - noneAny.filterIsInstance() shouldBe None - } - - "exists" { - some.exists { it.startsWith('k') } shouldBe true - some.exists { it.startsWith('j') } shouldBe false - none.exists { it.startsWith('k') } shouldBe false - } - - "all" { - some.all { it.startsWith('k') } shouldBe true - some.all { it.startsWith('j') } shouldBe false - none.all { it.startsWith('k') } shouldBe true - } - - "orElse" { - some.orElse { Some("java") } shouldBe Some("kotlin") - none.orElse { Some("java") } shouldBe Some("java") - } - - "toList" { - some.toList() shouldBe listOf("kotlin") - none.toList() shouldBe listOf() - } - - "Iterable.firstOrNone" { - val iterable = iterableOf(1, 2, 3, 4, 5, 6) - iterable.firstOrNone() shouldBe Some(1) - iterable.firstOrNone { it > 2 } shouldBe Some(3) - iterable.firstOrNone { it > 7 } shouldBe None - - val emptyIterable = iterableOf() - emptyIterable.firstOrNone() shouldBe None - - val nullableIterable1 = iterableOf(null, 2, 3, 4, 5, 6) - nullableIterable1.firstOrNone() shouldBe Some(null) - - val nullableIterable2 = iterableOf(1, 2, 3, null, 5, null) - nullableIterable2.firstOrNone { it == null } shouldBe Some(null) - } - - "Collection.firstOrNone" { - val list = listOf(1, 2, 3, 4, 5, 6) - list.firstOrNone() shouldBe Some(1) - - val emptyList = emptyList() - emptyList.firstOrNone() shouldBe None - - val nullableList = listOf(null, 2, 3, 4, 5, 6) - nullableList.firstOrNone() shouldBe Some(null) - } - - "Iterable.singleOrNone" { - val iterable = iterableOf(1, 2, 3, 4, 5, 6) - iterable.singleOrNone() shouldBe None - iterable.singleOrNone { it > 2 } shouldBe None - - val singleIterable = iterableOf(3) - singleIterable.singleOrNone() shouldBe Some(3) - singleIterable.singleOrNone { it == 3 } shouldBe Some(3) - - val nullableSingleIterable1 = iterableOf(null) - nullableSingleIterable1.singleOrNone() shouldBe Some(null) - - val nullableSingleIterable2 = iterableOf(1, 2, 3, null, 5, 6) - nullableSingleIterable2.singleOrNone { it == null } shouldBe Some(null) - - val nullableSingleIterable3 = iterableOf(1, 2, 3, null, 5, null) - nullableSingleIterable3.singleOrNone { it == null } shouldBe None - } - - "Collection.singleOrNone" { - val list = listOf(1, 2, 3, 4, 5, 6) - list.singleOrNone() shouldBe None - - val singleList = listOf(3) - singleList.singleOrNone() shouldBe Some(3) - - val nullableSingleList = listOf(null) - nullableSingleList.singleOrNone() shouldBe Some(null) - } - - "Iterable.lastOrNone" { - val iterable = iterableOf(1, 2, 3, 4, 5, 6) - iterable.lastOrNone() shouldBe Some(6) - iterable.lastOrNone { it < 4 } shouldBe Some(3) - iterable.lastOrNone { it > 7 } shouldBe None - - val emptyIterable = iterableOf() - emptyIterable.lastOrNone() shouldBe None - - val nullableIterable1 = iterableOf(1, 2, 3, 4, 5, null) - nullableIterable1.lastOrNone() shouldBe Some(null) - - val nullableIterable2 = iterableOf(null, 2, 3, null, 5, 6) - nullableIterable2.lastOrNone { it == null } shouldBe Some(null) - } - - "Collection.lastOrNone" { - val list = listOf(1, 2, 3, 4, 5, 6) - list.lastOrNone() shouldBe Some(6) - - val emptyList = emptyList() - emptyList.lastOrNone() shouldBe None - - val nullableList = listOf(1, 2, 3, 4, 5, null) - nullableList.lastOrNone() shouldBe Some(null) - } - - "Iterable.elementAtOrNone" { - val iterable = iterableOf(1, 2, 3, 4, 5, 6) - iterable.elementAtOrNone(index = 3 - 1) shouldBe Some(3) - iterable.elementAtOrNone(index = -1) shouldBe None - iterable.elementAtOrNone(index = 100) shouldBe None - - val nullableIterable = iterableOf(1, 2, null, 4, 5, 6) - nullableIterable.elementAtOrNone(index = 3 - 1) shouldBe Some(null) - } - - "Collection.elementAtOrNone" { - val list = listOf(1, 2, 3, 4, 5, 6) - list.elementAtOrNone(index = 3 - 1) shouldBe Some(3) - list.elementAtOrNone(index = -1) shouldBe None - list.elementAtOrNone(index = 100) shouldBe None - - val nullableList = listOf(1, 2, null, 4, 5, 6) - nullableList.elementAtOrNone(index = 3 - 1) shouldBe Some(null) - } - - "and" { - val x = Some(2) - val y = Some("Foo") - x and y shouldBe Some("Foo") - x and None shouldBe None - None and x shouldBe None - None and None shouldBe None - } - - "or" { - val x = Some(2) - val y = Some(100) - x or y shouldBe Some(2) - x or None shouldBe Some(2) - None or x shouldBe Some(2) - None or None shouldBe None - } - - "toLeftOption" { - 1.leftIor().leftOrNull() shouldBe 1 - 2.rightIor().leftOrNull() shouldBe null - (1 to 2).bothIor().leftOrNull() shouldBe 1 - } - - "pairLeft" { - val some: Option = Some(2) - val none: Option = None - some.pairLeft("key") shouldBe Some("key" to 2) - none.pairLeft("key") shouldBe None - } - - "pairRight" { - val some: Option = Some(2) - val none: Option = None - some.pairRight("right") shouldBe Some(2 to "right") - none.pairRight("right") shouldBe None - } - - "Option>.toMap()" { - val some: Option> = Some("key" to "value") - val none: Option> = None - some.toMap() shouldBe mapOf("key" to "value") - none.toMap() shouldBe emptyMap() - } - - "traverse should yield list of option" { - val some: Option = Some("value") - val none: Option = None - some.traverse { listOf(it) } shouldBe listOf(Some("value")) - none.traverse { listOf(it) } shouldBe listOf(None) - } - - "sequence should be consistent with traverse" { - checkAll(Arb.option(Arb.int())) { option -> - option.map { listOf(it) }.sequence() shouldBe option.traverse { listOf(it) } - } - } - - "traverseEither should yield either of option" { - val some: Option = Some("value") - val none: Option = None - some.traverse { it.right() } shouldBe some.right() - none.traverse { it.right() } shouldBe none.right() - } - - "sequenceEither should be consistent with traverseEither" { - checkAll(Arb.option(Arb.int())) { option -> - option.map { it.right() }.sequence() shouldBe option.traverse{ it.right() } - } - } - - "traverseValidated should yield validated of option" { - val some: Option = Some("value") - val none: Option = None - some.traverse { it.valid() } shouldBe some.valid() - none.traverse { it.valid() } shouldBe none.valid() - } - - "sequenceValidated should be consistent with traverseValidated" { - checkAll(Arb.option(Arb.int())) { option -> - option.map { it.valid() }.sequence() shouldBe option.traverse { it.valid() } - } - } - - "catch should return Some(result) when f does not throw" { - val recover: (Throwable) -> Option = { _ -> None} - Option.catch(recover) { 1 } shouldBe Some(1) + ensure(predicate) + i + } shouldBe if (predicate) Some(i) else None } + } - "catch with default recover should return Some(result) when f does not throw" { - Option.catch { 1 } shouldBe Some(1) - } - - "catch should return Some(recoverValue) when f throws" { - val exception = Exception("Boom!") - val recoverValue = 10 - val recover: (Throwable) -> Option = { _ -> Some(recoverValue) } - Option.catch(recover) { throw exception } shouldBe Some(recoverValue) - } - - "catch should return None when f throws" { - val exception = Exception("Boom!") - Option.catch { throw exception } shouldBe None - } - - "invoke operator should return Some" { - checkAll(Arb.int()) { a: Int -> - Option(a) shouldBe Some(a) - } - } - - "lift" { - val f: (Int) -> String = { a -> a.toString() } - val lifted = Option.lift(f) - checkAll(Arb.int()) { a: Int -> - lifted(Some(a)) shouldBe Some(a.toString()) - } - } - - "isNone should return true if None and false if Some" { - none.isNone() shouldBe true - none.isSome() shouldBe false - } - - "isSome should return true if Some and false if None" { - some.isSome() shouldBe true - some.isNone() shouldBe false - } - - "getOrNull" { - none.getOrNull() shouldBe null - some.getOrNull() shouldBe "kotlin" - } - - "isSome with predicate" { - some.isSome { it.startsWith('k') } shouldBe true - some.isSome { it.startsWith('j') } shouldBe false - none.isSome { it.startsWith('k') } shouldBe false - } - - "flatten" { - checkAll(Arb.int()) { a: Int -> - Some(Some(a)).flatten() shouldBe Some(a) - Some(None).flatten() shouldBe None - } - } - - "unzip Some values" { - checkAll(Arb.int(), Arb.string()) { a: Int, b: String -> - val op: Option> = Pair(a, b).toOption() - op.unzip() shouldBe Pair(Option(a), Option(b)) - } - } - - "unzip None values" { - val op: Option> = None - op.unzip() shouldBe Pair(None, None) - } - - "unzip with function" { - val f: (Int) -> Pair = { c -> Pair(c.toString(), c.toLong()) } - checkAll(Arb.int()) { c: Int -> - Option(c).unzip(f) shouldBe Pair(Option(c.toString()), Option(c.toLong())) + @Test fun ensureNotNullInOptionComputation() = runTest { + fun square(i: Int): Int = i * i + checkAll(Arb.int().orNull()) { i: Int? -> + option { + ensureNotNull(i) + square(i) // Smart-cast by contract + } shouldBe i.toOption().map(::square) + } + } + + @Test fun shortCircuitNull() = runTest { + option { + val number: Int = "s".length + ensureNotNull(number.takeIf { it > 1 }) + throw IllegalStateException("This should not be executed") + } shouldBe None + } + + @Test fun tapAppliesEffectsReturningTheOriginalValue() = runTest { + checkAll(Arb.option(Arb.long())) { option -> + var effect = 0 + val res = option.onSome { effect += 1 } + val expected = when (option) { + is Some -> 1 + is None -> 0 } - } - - "widen" { - checkAll(Arb.string()) { a: String -> - val widen: Option = Option(a).widen() - widen.map { it.length } shouldBe Some(a.length) + effect shouldBe expected + res shouldBe option + } + } + + @Test fun tapNoneAppliesEffectsReturningTheOriginalValue() = runTest { + checkAll(Arb.option(Arb.long())) { option -> + var effect = 0 + val res = option.onNone { effect += 1 } + val expected = when (option) { + is Some -> 0 + is None -> 1 } - } - - "compareTo with Some values" { - checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> - val opA = Option(a) - val opB = Option(b) - (opA > opB) shouldBe (a > b) - (opA >= opB) shouldBe (a >= b) - (opA < opB) shouldBe (a < b) - (opA <= opB) shouldBe (a <= b) - (opA == opB) shouldBe (a == b) - (opA != opB) shouldBe (a != b) - } - } - - "compareTo with None values" { - val opA = Option(1) - val opB = None - (opA > opB) shouldBe true - (opA >= opB) shouldBe true - (opA < opB) shouldBe false - (opA <= opB) shouldBe false - (opA == opB) shouldBe false - (opA != opB) shouldBe true - - (none > some) shouldBe false - (none >= some) shouldBe false - (none < some) shouldBe true - (none <= some) shouldBe true - (none == some) shouldBe false - (none != some) shouldBe true - } -}) + effect shouldBe expected + res shouldBe option + } + } + + @Test fun fromNullableShouldWorkForBothNullAndNonNullValuesOfNullableTypes() = runTest { + checkAll(Arb.int().orNull()) { a: Int? -> + // This seems to be generating only non-null values, so it is complemented by the next test + val o: Option = Option.fromNullable(a) + if (a == null) o shouldBe None else o shouldBe Some(a) + } + } + + @Test fun fromNullableShouldReturnNoneForNullValuesOfNullableTypes() = runTest { + val a: Int? = null + Option.fromNullable(a) shouldBe None + } + + @Test fun getOrElse() = runTest { + some.getOrElse { "java" } shouldBe "kotlin" + none.getOrElse { "java" } shouldBe "java" + } + + @Test fun getOrNull() = runTest { + some.getOrNull() shouldNotBe null + none.getOrNull() shouldBe null + } + + @Test fun map() = runTest { + some.map(String::uppercase) shouldBe Some("KOTLIN") + none.map(String::uppercase) shouldBe None + } + + @Test fun fold() = runTest { + some.fold({ 0 }) { it.length } shouldBe 6 + none.fold({ 0 }) { it.length } shouldBe 0 + } + + @Test fun flatMap() = runTest { + some.flatMap { Some(it.uppercase()) } shouldBe Some("KOTLIN") + none.flatMap { Some(it.uppercase()) } shouldBe None + } + + @Test fun filter() = runTest { + some.filter { it == "java" } shouldBe None + none.filter { it == "java" } shouldBe None + some.filter { it.startsWith('k') } shouldBe Some("kotlin") + } + + @Test fun filterNot() = runTest { + some.filterNot { it == "java" } shouldBe Some("kotlin") + none.filterNot { it == "java" } shouldBe None + some.filterNot { it.startsWith('k') } shouldBe None + } + + @Test fun filterIsInstance() = runTest { + val someAny: Option = some + someAny.filterIsInstance() shouldBe Some("kotlin") + someAny.filterIsInstance() shouldBe None + + val someNullableAny: Option = null.some() + someNullableAny.filterIsInstance() shouldBe Some(null) + someNullableAny.filterIsInstance() shouldBe None + + val noneAny: Option = none + noneAny.filterIsInstance() shouldBe None + noneAny.filterIsInstance() shouldBe None + } + + @Test fun toList() = runTest { + some.toList() shouldBe listOf("kotlin") + none.toList() shouldBe listOf() + } + + @Test fun iterableFirstOrNone() = runTest { + val iterable = iterableOf(1, 2, 3, 4, 5, 6) + iterable.firstOrNone() shouldBe Some(1) + iterable.firstOrNone { it > 2 } shouldBe Some(3) + iterable.firstOrNone { it > 7 } shouldBe None + + val emptyIterable = iterableOf() + emptyIterable.firstOrNone() shouldBe None + + val nullableIterable1 = iterableOf(null, 2, 3, 4, 5, 6) + nullableIterable1.firstOrNone() shouldBe Some(null) + + val nullableIterable2 = iterableOf(1, 2, 3, null, 5, null) + nullableIterable2.firstOrNone { it == null } shouldBe Some(null) + } + + @Test fun collectionFirstOrNone() = runTest { + val list = listOf(1, 2, 3, 4, 5, 6) + list.firstOrNone() shouldBe Some(1) + + val emptyList = emptyList() + emptyList.firstOrNone() shouldBe None + + val nullableList = listOf(null, 2, 3, 4, 5, 6) + nullableList.firstOrNone() shouldBe Some(null) + } + + @Test fun iterableSingleOrNone() = runTest { + val iterable = iterableOf(1, 2, 3, 4, 5, 6) + iterable.singleOrNone() shouldBe None + iterable.singleOrNone { it > 2 } shouldBe None + + val singleIterable = iterableOf(3) + singleIterable.singleOrNone() shouldBe Some(3) + singleIterable.singleOrNone { it == 3 } shouldBe Some(3) + + val nullableSingleIterable1 = iterableOf(null) + nullableSingleIterable1.singleOrNone() shouldBe Some(null) + + val nullableSingleIterable2 = iterableOf(1, 2, 3, null, 5, 6) + nullableSingleIterable2.singleOrNone { it == null } shouldBe Some(null) + + val nullableSingleIterable3 = iterableOf(1, 2, 3, null, 5, null) + nullableSingleIterable3.singleOrNone { it == null } shouldBe None + } + + @Test fun collectionSingleOrNone() = runTest { + val list = listOf(1, 2, 3, 4, 5, 6) + list.singleOrNone() shouldBe None + + val singleList = listOf(3) + singleList.singleOrNone() shouldBe Some(3) + + val nullableSingleList = listOf(null) + nullableSingleList.singleOrNone() shouldBe Some(null) + } + + @Test fun iterableLastOrNone() = runTest { + val iterable = iterableOf(1, 2, 3, 4, 5, 6) + iterable.lastOrNone() shouldBe Some(6) + iterable.lastOrNone { it < 4 } shouldBe Some(3) + iterable.lastOrNone { it > 7 } shouldBe None + + val emptyIterable = iterableOf() + emptyIterable.lastOrNone() shouldBe None + + val nullableIterable1 = iterableOf(1, 2, 3, 4, 5, null) + nullableIterable1.lastOrNone() shouldBe Some(null) + + val nullableIterable2 = iterableOf(null, 2, 3, null, 5, 6) + nullableIterable2.lastOrNone { it == null } shouldBe Some(null) + } + + @Test fun collectionLastOrNone() = runTest { + val list = listOf(1, 2, 3, 4, 5, 6) + list.lastOrNone() shouldBe Some(6) + + val emptyList = emptyList() + emptyList.lastOrNone() shouldBe None + + val nullableList = listOf(1, 2, 3, 4, 5, null) + nullableList.lastOrNone() shouldBe Some(null) + } + + @Test fun iterableElementAtOrNone() = runTest { + val iterable = iterableOf(1, 2, 3, 4, 5, 6) + iterable.elementAtOrNone(index = 3 - 1) shouldBe Some(3) + iterable.elementAtOrNone(index = -1) shouldBe None + iterable.elementAtOrNone(index = 100) shouldBe None + + val nullableIterable = iterableOf(1, 2, null, 4, 5, 6) + nullableIterable.elementAtOrNone(index = 3 - 1) shouldBe Some(null) + } + + @Test fun collectionElementAtOrNone() = runTest { + val list = listOf(1, 2, 3, 4, 5, 6) + list.elementAtOrNone(index = 3 - 1) shouldBe Some(3) + list.elementAtOrNone(index = -1) shouldBe None + list.elementAtOrNone(index = 100) shouldBe None + + val nullableList = listOf(1, 2, null, 4, 5, 6) + nullableList.elementAtOrNone(index = 3 - 1) shouldBe Some(null) + } + + @Test fun toLeftOption() = runTest { + 1.leftIor().leftOrNull() shouldBe 1 + 2.rightIor().leftOrNull() shouldBe null + (1 to 2).bothIor().leftOrNull() shouldBe 1 + } + + @Test fun optionPairToMap() = runTest { + val some: Option> = Some("key" to "value") + val none: Option> = None + some.toMap() shouldBe mapOf("key" to "value") + none.toMap() shouldBe emptyMap() + } + + @Test fun catchShouldReturnSomeResultWhenFDoesNotThrow() = runTest { + val recover: (Throwable) -> Option = { _ -> None} + Option.catch(recover) { 1 } shouldBe Some(1) + } + + @Test fun catchWithDefaultRecoverShouldReturnSomeResultWhenFDoesNotThrow() = runTest { + Option.catch { 1 } shouldBe Some(1) + } + + @Test fun catchShouldReturnSomeRecoverValueWhenFThrows() = runTest { + val exception = Exception("Boom!") + val recoverValue = 10 + val recover: (Throwable) -> Option = { _ -> Some(recoverValue) } + Option.catch(recover) { throw exception } shouldBe Some(recoverValue) + } + + @Test fun catchShouldReturnNoneWhenFThrows() = runTest { + val exception = Exception("Boom!") + Option.catch { throw exception } shouldBe None + } + + @Test fun invokeOperatorShouldReturnSome() = runTest { + checkAll(Arb.int()) { a: Int -> + Option(a) shouldBe Some(a) + } + } + + @Test fun isNoneShouldReturnTrueIfNoneAndFalseIfSome() = runTest { + none.isNone() shouldBe true + none.isSome() shouldBe false + } + + @Test fun isSomeShouldReturnTrueIfSomeAndFalseIfNone() = runTest { + some.isSome() shouldBe true + some.isNone() shouldBe false + } + + @Test fun isSomeWithPredicate() = runTest { + some.isSome { it.startsWith('k') } shouldBe true + some.isSome { it.startsWith('j') } shouldBe false + none.isSome { it.startsWith('k') } shouldBe false + } + + @Test fun flatten() = runTest { + checkAll(Arb.int()) { a: Int -> + Some(Some(a)).flatten() shouldBe Some(a) + Some(None).flatten() shouldBe None + } + } + + @Test fun compareToWithSomeValues() = runTest { + checkAll(Arb.int(), Arb.int()) { a: Int, b: Int -> + val opA = Option(a) + val opB = Option(b) + (opA > opB) shouldBe (a > b) + (opA >= opB) shouldBe (a >= b) + (opA < opB) shouldBe (a < b) + (opA <= opB) shouldBe (a <= b) + (opA == opB) shouldBe (a == b) + (opA != opB) shouldBe (a != b) + } + } + + @Test fun compareToWithNoneValues() = runTest { + val opA = Option(1) + val opB = None + (opA > opB) shouldBe true + (opA >= opB) shouldBe true + (opA < opB) shouldBe false + (opA <= opB) shouldBe false + (opA == opB) shouldBe false + (opA != opB) shouldBe true + + (none > some) shouldBe false + (none >= some) shouldBe false + (none < some) shouldBe true + (none <= some) shouldBe true + (none == some) shouldBe false + (none != some) shouldBe true + } +} // Utils diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ResultTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ResultTest.kt deleted file mode 100644 index a824b3b4d60..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ResultTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package arrow.core - -import arrow.core.raise.result -import arrow.core.test.result -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.checkAll - -class ResultTest : StringSpec({ - - "null zip null" { - val x = Result.success(null) - x.zip(x) { y, z -> - (y?.plus(z ?: -2)) ?: -1 - } shouldBe Result.success(-1) - } - -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt index f6ff9ec73aa..ec58ddef409 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/SequenceKTest.kt @@ -7,78 +7,24 @@ import arrow.core.test.option import arrow.core.test.sequence import arrow.core.test.testLaws import arrow.core.test.unit -import arrow.typeclasses.Semigroup -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.sequences.shouldBeEmpty import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.positiveInt import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest import kotlin.math.max import kotlin.math.min +import kotlin.test.Test -class SequenceKTest : StringSpec({ +class SequenceKTest { + @Test fun monoidLaws() = testLaws(MonoidLaws("Sequence", emptySequence(), { a, b -> sequenceOf(a, b).flatten()} , Arb.sequence(Arb.int())) { s1, s2 -> s1.toList() == s2.toList() }) - "traverse for Either stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = generateSequence(0) { it + 1 }.traverse { a -> - if (a > 20_000) { - Either.Left(Unit) - } else { - acc.add(a) - Either.Right(a) - } - } - acc shouldBe (0..20_000).toList() - res shouldBe Either.Left(Unit) - } - - "traverse for Option stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = generateSequence(0) { it + 1 }.traverse { a -> - if ((a <= 20_000)) { - acc.add(a) - Some(a) - } else { - None - } - } - acc shouldBe (0..20_000).toList() - res shouldBe None - } - - "mapOrAccumlate for Either stack-safe" { - // also verifies result order and execution order (l to r) - val acc = mutableListOf() - val res = (0..20_000).asSequence().mapOrAccumulate(String::plus) { - acc.add(it) - Either.Right(it).bind() - }.map { it.toList() } - res shouldBe Either.Right(acc) - res shouldBe Either.Right((0..20_000).toList()) - } - - "traverse for Validated acummulates" { - checkAll(Arb.sequence(Arb.int())) { ints -> - val res: ValidatedNel> = ints.map { i -> if (i % 2 == 0) i.validNel() else i.invalidNel() } - .sequence(Semigroup.nonEmptyList()) - - val expected: ValidatedNel> = - ints.filterNot { it % 2 == 0 }.toList() - .toNonEmptyListOrNull()?.invalid() ?: ints.filter { it % 2 == 0 }.validNel() - - res.map { it.toList() } shouldBe expected.map { it.toList() } - } - } - - "zip3" { + @Test fun zip3Ok() = runTest { checkAll(Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), Arb.sequence(Arb.int())) { a, b, c -> val result = a.zip(b, c, ::Triple) val expected = a.zip(b, ::Pair).zip(c) { (a, b), c -> Triple(a, b, c) } @@ -86,7 +32,7 @@ class SequenceKTest : StringSpec({ } } - "zip4" { + @Test fun zip4Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -102,7 +48,7 @@ class SequenceKTest : StringSpec({ } } - "zip5" { + @Test fun zip5Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -120,7 +66,7 @@ class SequenceKTest : StringSpec({ } } - "zip6" { + @Test fun zip6Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -140,7 +86,7 @@ class SequenceKTest : StringSpec({ } } - "zip7" { + @Test fun zip7Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -162,7 +108,7 @@ class SequenceKTest : StringSpec({ } } - "zip8" { + @Test fun zip8Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -186,7 +132,7 @@ class SequenceKTest : StringSpec({ } } - "zip9" { + @Test fun zip9Ok() = runTest { checkAll( Arb.sequence(Arb.int()), Arb.sequence(Arb.int()), @@ -212,35 +158,7 @@ class SequenceKTest : StringSpec({ } } - "zip10" { - checkAll( - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()), - Arb.sequence(Arb.int()) - ) { a, b, c, d, e, f, g, h, i, j -> - val result = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) - val expected = a.zip(b, ::Pair) - .zip(c) { (a, b), c -> Triple(a, b, c) } - .zip(d) { (a, b, c), d -> Tuple4(a, b, c, d) } - .zip(e) { (a, b, c, d), e -> Tuple5(a, b, c, d, e) } - .zip(f) { (a, b, c, d, e), f -> Tuple6(a, b, c, d, e, f) } - .zip(g) { (a, b, c, d, e, f), g -> Tuple7(a, b, c, d, e, f, g) } - .zip(h) { (a, b, c, d, e, f, g), h -> Tuple8(a, b, c, d, e, f, g, h) } - .zip(i) { (a, b, c, d, e, f, g, h), i -> Tuple9(a, b, c, d, e, f, g, h, i) } - .zip(j) { (a, b, c, d, e, f, g, h, i), j -> Tuple10(a, b, c, d, e, f, g, h, i, j) } - - result.toList() shouldBe expected.toList() - } - } - - "crosswalk the sequence to a List function" { + @Test fun crosswalkOk() = runTest { checkAll(Arb.list(Arb.int())){ list -> val obtained = list.asSequence().crosswalk { listOf(it) } val expected = if (list.isEmpty()) emptyList() @@ -249,13 +167,13 @@ class SequenceKTest : StringSpec({ } } - "can align sequences - 1" { + @Test fun align1() = runTest { checkAll(Arb.sequence(Arb.unit()), Arb.sequence(Arb.unit())) { a, b -> a.align(b).toList().size shouldBe max(a.toList().size, b.toList().size) } } - "can align sequences - 2" { + @Test fun align2() = runTest { checkAll(Arb.sequence(Arb.unit()), Arb.sequence(Arb.unit())) { a, b -> a.align(b).take(min(a.toList().size, b.toList().size)).forEach { it.isBoth() shouldBe true @@ -263,7 +181,7 @@ class SequenceKTest : StringSpec({ } } - "can align sequences - 3" { + @Test fun align3() = runTest { checkAll(Arb.sequence(Arb.unit()), Arb.sequence(Arb.unit())) { a, b -> val ls = a.toList() val rs = b.toList() @@ -274,12 +192,12 @@ class SequenceKTest : StringSpec({ } } - "align empty sequences" { + @Test fun alignEmpty() = runTest { val a = emptyList().asSequence() a.align(a).shouldBeEmpty() } - "align infinite sequences" { + @Test fun alignInfinite() = runTest { val seq1 = generateSequence("A") { it } val seq2 = generateSequence(0) { it + 1 } @@ -291,7 +209,7 @@ class SequenceKTest : StringSpec({ } } - "mapNotNull" { + @Test fun mapNotNullOk() = runTest { checkAll(Arb.sequence(Arb.int())) { a -> val result = a.mapNotNull { when (it % 2 == 0) { @@ -313,13 +231,13 @@ class SequenceKTest : StringSpec({ } } - "filterOption should filter None" { + @Test fun filterOptionOk() = runTest { checkAll(Arb.list(Arb.option(Arb.int()))) { ints -> ints.asSequence().filterOption().toList() shouldBe ints.filterOption() } } - "separateEither" { + @Test fun separateEitherOk() = runTest { checkAll(Arb.sequence(Arb.int())) { ints -> val sequence = ints.map { if (it % 2 == 0) it.left() @@ -332,16 +250,4 @@ class SequenceKTest : StringSpec({ } } - "separateValidated" { - checkAll(Arb.sequence(Arb.int())) { ints -> - val sequence = ints.map { - if (it % 2 == 0) it.invalid() - else it.valid() - } - - val (invalids, valids) = sequence.separateValidated() - - invalids.toList() to valids.toList() shouldBe ints.partition { it % 2 == 0 } - } - } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/TupleTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/TupleTest.kt index b1d4c6e7346..ac135664d37 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/TupleTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/TupleTest.kt @@ -1,21 +1,20 @@ package arrow.core -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.double import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class TupleTest : StringSpec({ +class TupleTest { - "shortToString" { + @Test fun shortToString() = runTest { checkAll( Arb.int(), Arb.int(), @@ -36,7 +35,7 @@ class TupleTest : StringSpec({ } } - "plus" { + @Test fun plus() = runTest { checkAll( Arb.int(), Arb.int(), @@ -58,7 +57,7 @@ class TupleTest : StringSpec({ } } - "compareTo(equals)" { + @Test fun compareToEquals() = runTest { checkAll( Arb.int(), Arb.string(), @@ -81,7 +80,7 @@ class TupleTest : StringSpec({ } } - "compareTo(not equals)" { + @Test fun compareToNotEquals() = runTest { checkAll( Arb.intOpenEnded(), Arb.intOpenEnded(), @@ -104,7 +103,7 @@ class TupleTest : StringSpec({ } } - "compareTo(deep not equals)" { + @Test fun compareToDeepNotEquals() = runTest { checkAll( Arb.intOpenEnded(), Arb.intOpenEnded(), @@ -161,87 +160,6 @@ class TupleTest : StringSpec({ Tuple9(a, b, c, d, e, f, g, h, i).compareTo(Tuple9(a, b, c, d, e, f, g, h, i + 1)) shouldBe -1 } } - - "toStringN" { - checkAll( - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int(), - Arb.int() - ) { a, b, c, d, e, f, g, h, i, j -> - Tuple10(a, b, c, d, e, f, g, h, i, j).toString() shouldBe "($a, $b, $c, $d, $e, $f, $g, $h, $i, $j)" - } - } - - "plusN" { - checkAll( - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 2..2), - ) { (a, b, c, d), (e, f, g, h), (i, j, k, l), (m, n, o, p), (q, r, s, t), (u, v) -> - Tuple9(a, b, c, d, e, f, g, h, i) + j shouldBe Tuple10(a, b, c, d, e, f, g, h, i, j) - Tuple10(a, b, c, d, e, f, g, h, i, j) + k shouldBe Tuple11(a, b, c, d, e, f, g, h, i, j, k) - Tuple11(a, b, c, d, e, f, g, h, i, j, k) + l shouldBe Tuple12(a, b, c, d, e, f, g, h, i, j, k, l) - Tuple12(a, b, c, d, e, f, g, h, i, j, k, l) + m shouldBe Tuple13(a, b, c, d, e, f, g, h, i, j, k, l, m) - Tuple13(a, b, c, d, e, f, g, h, i, j, k, l, m) + n shouldBe Tuple14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) - Tuple14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) + o shouldBe Tuple15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) - Tuple15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) + p shouldBe Tuple16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) - Tuple16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) + q shouldBe Tuple17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) - Tuple17(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) + r shouldBe Tuple18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) - Tuple18(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) + s shouldBe Tuple19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) - Tuple19(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) + t shouldBe Tuple20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) - Tuple20(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t) + u shouldBe Tuple21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) - Tuple21(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u) + v shouldBe Tuple22(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v) - } - } - - "compareToN(equals)" { - checkAll( - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 4..4), - Arb.list(Arb.int(), 2..2), - ) { (a, b, c, d), (e, f, g, h), (i, j) -> - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f, g, h, i, j)) shouldBe 0 - } - } - - "compareToN(not equals)" { - checkAll( - Arb.list(Arb.intOpenEnded(), 4..4), - Arb.list(Arb.intOpenEnded(), 4..4), - Arb.list(Arb.intOpenEnded(), 2..2), - ) { (a, b, c, d), (e, f, g, h), (i, j) -> - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a + 1, b, c, d, e, f, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a - 1, b, c, d, e, f, g, h, i, j)) shouldBe 1 - } - } - - "compareToN(deep not equals)" { - checkAll( - Arb.list(Arb.intOpenEnded(), 4..4), - Arb.list(Arb.intOpenEnded(), 4..4), - Arb.list(Arb.intOpenEnded(), 2..2), - ) { (a, b, c, d), (e, f, g, h), (i, j) -> - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b + 1, c, d, e, f, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c + 1, d, e, f, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d + 1, e, f, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e + 1, f, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f + 1, g, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f, g + 1, h, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f, g, h + 1, i, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f, g, h, i + 1, j)) shouldBe -1 - Tuple10(a, b, c, d, e, f, g, h, i, j).compareTo(Tuple10(a, b, c, d, e, f, g, h, i, j + 1)) shouldBe -1 - } - } -}) +} private fun Arb.Companion.intOpenEnded() = Arb.int(Int.MIN_VALUE + 1, Int.MAX_VALUE - 1) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ValidatedTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ValidatedTest.kt deleted file mode 100644 index b20b190b5b1..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/ValidatedTest.kt +++ /dev/null @@ -1,516 +0,0 @@ -package arrow.core - -import arrow.core.Either.Left -import arrow.core.Either.Right -import arrow.core.test.validated -import arrow.typeclasses.Monoid -import arrow.typeclasses.Semigroup -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldBeNull -import io.kotest.property.Arb -import io.kotest.matchers.shouldBe -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.long -import io.kotest.property.arbitrary.orNull -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll - -@Suppress("RedundantSuspendModifier") -class ValidatedTest : StringSpec({ - "fold should call function on Invalid" { - val exception = Exception("My Exception") - val result: Validated = Invalid(exception) - result.fold( - { e -> e.message + " Checked" }, - { fail("Some should not be called") } - ) shouldBe "My Exception Checked" - } - - "fold should call function on Valid" { - val value = "Some value" - val result: Validated = Valid(value) - result.fold( - { fail("None should not be called") }, - { a -> "$a processed" } - ) shouldBe "$value processed" - } - - "leftMap should modify error" { - Valid(10).mapLeft { fail("None should not be called") } shouldBe Valid(10) - Invalid(13).mapLeft { i -> "$i is Coming soon!" } shouldBe Invalid("13 is Coming soon!") - } - - "exist should return false if is Invalid" { - Invalid(13).exist { fail("None should not be called") } shouldBe false - } - - "exist should return the value of predicate if is Valid" { - Valid(13).exist { v -> v > 10 } shouldBe true - Valid(13).exist { v -> v < 10 } shouldBe false - } - - "swap should return Valid(e) if is Invalid and Invalid(v) otherwise" { - Valid(13).swap() shouldBe Invalid(13) - Invalid(13).swap() shouldBe Valid(13) - } - - "getOrElse should return value if is Valid or default otherwise" { - Valid(13).getOrElse { fail("None should not be called") } shouldBe 13 - Invalid(13).getOrElse { "defaultValue" } shouldBe "defaultValue" - } - - "orNull should return value if is Valid or null otherwise" { - Valid(13).orNull() shouldBe 13 - val invalid: Validated = Invalid(13) - invalid.orNull() shouldBe null - } - - "orNone should return value if is Valid or None otherwise" { - Valid(13).orNone() shouldBe Some(13) - val invalid: Validated = Invalid(13) - invalid.orNone() shouldBe None - } - - "valueOr should return value if is Valid or the the result of f otherwise" { - Valid(13).valueOr { fail("None should not be called") } shouldBe 13 - Invalid(13).valueOr { e -> "$e is the defaultValue" } shouldBe "13 is the defaultValue" - } - - "orElse should return Valid(value) if is Valid or the result of default otherwise" { - Valid(13).orElse { fail("None should not be called") } shouldBe Valid(13) - Invalid(13).orElse { Valid("defaultValue") } shouldBe Valid("defaultValue") - Invalid(13).orElse { Invalid("defaultValue") } shouldBe Invalid("defaultValue") - } - - "foldLeft should return b when is Invalid" { - Invalid(13).foldLeft("Coming soon!") { _, _ -> fail("None should not be called") } shouldBe "Coming soon!" - } - - "foldLeft should return f processed when is Valid" { - Valid(10).foldLeft("Tennant") { b, a -> "$a is $b" } shouldBe "10 is Tennant" - } - - "toEither should return Either.Right(value) if is Valid or Either.Left(error) otherwise" { - Valid(10).toEither() shouldBe Right(10) - Invalid(13).toEither() shouldBe Left(13) - } - - "toIor should return Ior.Right(value) if is Valid or Ior.Left(error) otherwise" { - Valid(10).toIor() shouldBe Ior.Right(10) - Invalid(13).toIor() shouldBe Ior.Left(13) - } - - "toOption should return Some(value) if is Valid or None otherwise" { - Valid(10).toOption() shouldBe Some(10) - Invalid(13).toOption() shouldBe None - } - - "toList should return listOf(value) if is Valid or empty list otherwise" { - Valid(10).toList() shouldBe listOf(10) - Invalid(13).toList() shouldBe listOf() - } - - "toValidatedNel should return Valid(value) if is Valid or Invalid, A>(error) otherwise" { - Valid(10).toValidatedNel() shouldBe Valid(10) - Invalid(13).toValidatedNel() shouldBe Invalid(NonEmptyList(13, listOf())) - } - - "findValid should return the first Valid value or combine or Invalid values otherwise" { - Valid(10).findValid(Semigroup.int()) { fail("None should not be called") } shouldBe Valid(10) - Invalid(10).findValid(Semigroup.int()) { Valid(5) } shouldBe Valid(5) - Invalid(10).findValid(Semigroup.int()) { Invalid(5) } shouldBe Invalid(15) - } - - val nullableLongSemigroup = object : Monoid { - override fun empty(): Long? = 0 - override fun Long?.combine(b: Long?): Long? = - Nullable.zip(this@combine, b) { a, bb -> a + bb } - } - - "zip identity" { - checkAll(Arb.validated(Arb.long().orNull(), Arb.int().orNull())) { validated -> - val res = validated.zip(nullableLongSemigroup, Valid(Unit)) { a, _ -> a } - res shouldBe validated - } - } - - "tap applies effects returning the original value" { - checkAll(Arb.validated(Arb.long(), Arb.int())) { validated -> - var effect = 0 - val res = validated.tap { effect += 1 } - val expected = when (validated) { - is Validated.Valid -> 1 - is Validated.Invalid -> 0 - } - effect shouldBe expected - res shouldBe validated - } - } - - "tapInvalid applies effects returning the original value" { - checkAll(Arb.validated(Arb.long(), Arb.int())) { validated -> - var effect = 0 - val res = validated.tapInvalid { effect += 1 } - val expected = when (validated) { - is Validated.Valid -> 0 - is Validated.Invalid -> 1 - } - effect shouldBe expected - res shouldBe validated - } - } - - "zip is derived from flatMap" { - checkAll( - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()), - Arb.validated(Arb.long().orNull(), Arb.int().orNull()) - ) { a, b, c, d, e, f, g, h, i, j -> - val res = a.zip( - nullableLongSemigroup, - b, c, d, e, f, g, h, i, j - ) { a, b, c, d, e, f, g, h, i, j -> - Nullable.zip( - a, - b, - c, - d, - e, - f, - g, - h, - i, - j - ) { a, b, c, d, e, f, g, h, i, j -> a + b + c + d + e + f + g + h + i + j } - } - - val all = listOf(a, b, c, d, e, f, g, h, i, j) - val isValid = all.all { it.isValid } - val expected: Validated = - if (isValid) Valid(all.fold, Int?>(0) { acc, validated -> - Nullable.zip( - acc, - validated.orNull() - ) { a, b -> a + b } - }) - else Invalid( - all.filterIsInstance>().map { it.value }.fold(nullableLongSemigroup) - ) - - res shouldBe expected - } - } - - "zip should return Valid(f(a)) if both are Valid" { - Valid(10).zip(Semigroup.int(), Valid { a: Int -> a + 5 }) { a, ff -> ff(a) } shouldBe Valid(15) - } - - "zip should return first Invalid found if is unique or combine both otherwise" { - Invalid(10).zip(Semigroup.int(), Valid { a: Int -> a + 5 }) { a, ff -> ff(a) } shouldBe Invalid(10) - Valid(10).zip Int, Int>(Semigroup.int(), Invalid(5)) { a, ff -> ff(a) } shouldBe Invalid(5) - Invalid(10).zip Int, Int>(Semigroup.int(), Invalid(5)) { a, ff -> ff(a) } shouldBe Invalid(15) - } - - data class MyException(val msg: String) : Exception() - - "fromEither should return Valid if is Either.Right or Failure otherwise" { - Validated.fromEither(Right(10)) shouldBe Valid(10) - Validated.fromEither(Left(10)) shouldBe Invalid(10) - } - - "fromOption should return Valid if is Some or Invalid otherwise" { - Validated.fromOption(Some(10)) { fail("should not be called") } shouldBe Valid(10) - Validated.fromOption(None) { 5 } shouldBe Invalid(5) - } - - "fromNullable should return Valid if is not-null or Invalid otherwise" { - Validated.fromNullable(10) { fail("should not be called") } shouldBe Valid(10) - Validated.fromNullable(null) { 5 } shouldBe Invalid(5) - } - - "invalidNel should return a Invalid>" { - Validated.invalidNel(10) shouldBe Invalid(NonEmptyList(10, listOf())) - } - - "withEither should return Valid(result) if f return Right" { - Valid(10).withEither { it.map { n -> n + 5 } } shouldBe Valid(15) - Invalid(10).withEither { Right(5) } shouldBe Valid(5) - } - - "withEither should return Invalid(result) if f return Left" { - Valid(10).withEither { Left(5) } shouldBe Invalid(5) - Invalid(10).withEither(::identity) shouldBe Invalid(10) - } - - "catch should return Valid(result) when f does not throw" { - suspend fun loadFromNetwork(): Int = 1 - Validated.catch { loadFromNetwork() } shouldBe Valid(1) - } - - "catch should return Invalid(result) when f throws" { - val exception = MyException("Boom!") - suspend fun loadFromNetwork(): Int = throw exception - Validated.catch { loadFromNetwork() } shouldBe Invalid(exception) - } - - "catchNel should return Valid(result) when f does not throw" { - suspend fun loadFromNetwork(): Int = 1 - Validated.catchNel { loadFromNetwork() } shouldBe Valid(1) - } - - "catchNel should return Invalid(Nel(result)) when f throws" { - val exception = MyException("Boom!") - suspend fun loadFromNetwork(): Int = throw exception - Validated.catchNel { loadFromNetwork() } shouldBe Invalid(nonEmptyListOf(exception)) - } - - "Cartesian builder should build products over homogeneous Validated" { - Valid("11th").zip( - Semigroup.string(), - Valid("Doctor"), - Valid("Who") - ) { a, b, c -> "$a $b $c" } shouldBe Valid("11th Doctor Who") - } - - "Cartesian builder should build products over heterogeneous Validated" { - Valid(13).zip( - Semigroup.string(), - Valid("Doctor"), - Valid(false) - ) { a, b, c -> "${a}th $b is $c" } shouldBe Valid("13th Doctor is false") - } - - "Cartesian builder should build products over Invalid Validated" { - Invalid("fail1").zip( - Semigroup.string(), - Invalid("fail2"), - Valid("Who") - ) { _, _, _ -> "success!" } shouldBe Invalid("fail1fail2") - } - - "Cartesian builder for nel doesn't need semigroup parameter" { - "fail1".invalidNel().zip( - "fail2".invalidNel() - ) { _, _ -> "success!" } shouldBe Invalid(nonEmptyListOf("fail1", "fail2")) - } - - "CombineK should combine Valid Validated" { - val valid = Valid("Who") - - valid.combineK(Semigroup.string(), valid) shouldBe (Valid("Who")) - } - - "CombineK should combine Valid and Invalid Validated" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.combineK(Semigroup.string(), invalid) shouldBe (Valid("Who")) - } - - "CombineK should combine Invalid Validated" { - val invalid = Invalid("Nope") - - invalid.combineK(Semigroup.string(), invalid) shouldBe (Invalid("NopeNope")) - } - - "Combine should combine Valid Validated" { - val valid: Validated = Valid("Who") - - valid.combine(Monoid.string(), Monoid.string(), valid) shouldBe (Valid("WhoWho")) - } - - "Combine should combine Valid and Invalid Validated" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.combine(Monoid.string(), Monoid.string(), invalid) shouldBe (Invalid("Nope")) - } - - "Combine should combine Invalid Validated" { - val invalid: Validated = Invalid("Nope") - - invalid.combine(Monoid.string(), Monoid.string(), invalid) shouldBe (Invalid("NopeNope")) - } - - "traverse should yield list when validated is valid" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.traverse { listOf(it) } shouldBe listOf(Valid("Who")) - invalid.traverse { listOf(it) } shouldBe emptyList() - } - - "sequence should yield consistent result with traverse" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid = Valid(a) - val invalid = Invalid(b) - - valid.traverse { listOf(it) } shouldBe valid.map { listOf(it) }.sequence() - invalid.traverse { listOf(it) } shouldBe invalid.map { listOf(it) }.sequence() - } - } - - "traverse for Option should yield option when validated is valid" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.traverse { Some(it) } shouldBe Some(Valid("Who")) - invalid.traverse { Some(it) } shouldBe None - } - - "sequence for Option should yield consistent result with traverseOption" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid = Valid(a) - val invalid = Invalid(b) - - valid.traverse { Some(it) } shouldBe valid.map { Some(it) }.sequence() - invalid.traverse { Some(it) } shouldBe invalid.map { Some(it) }.sequence() - } - } - - "traverseNullable should yield non-null object when validated is valid" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.traverseNullable { it } shouldBe Valid("Who") - valid.traverseNullable { null }.shouldBeNull() - invalid.traverseNullable { it }.shouldBeNull() - } - - "sequence for Nullable should yield consistent result with traverseNullable" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid = Valid(a) - val invalid = Invalid(b) - - valid.traverseNullable { it } shouldBe valid.map { it }.sequence() - valid.traverseNullable { null } shouldBe valid.map { null }.sequence() - invalid.traverseNullable { it } shouldBe invalid.map { it }.sequence() - } - } - - "traverse for Either should wrap validated in either" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.traverse { it.right() } shouldBe Valid("Who").right() - invalid.traverse { it.right() } shouldBe Invalid("Nope").right() - } - - "sequence for Either should yield consistent result with traverseEither" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid = Valid(a) - val invalid = Invalid(b) - - valid.traverse { Right(it) } shouldBe valid.map { Right(it) }.sequence() - invalid.traverse { Right(it) } shouldBe invalid.map { Right(it) }.sequence() - } - } - - "bitraverse should wrap valid or invalid in a list" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.bitraverse({ listOf(it) }, { listOf(it) }) shouldBe listOf(Valid("Who")) - invalid.bitraverse({ listOf(it) }, { listOf(it) }) shouldBe listOf(Invalid("Nope")) - } - - "bisequence should yield consistent result with bitraverse" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid: Validated = Valid(a) - val invalid: Validated = Invalid(b) - - valid.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe valid.bitraverse( - { listOf(it) }, - { listOf(it) }) - invalid.bimap({ listOf(it) }, { listOf(it) }).bisequence() shouldBe invalid.bitraverse( - { listOf(it) }, - { listOf(it) }) - } - } - - "bitraverseOption should wrap valid or invalid in an option" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.bitraverseOption({ Some(it) }, { Some(it) }) shouldBe Some(Valid("Who")) - invalid.bitraverseOption({ Some(it) }, { Some(it) }) shouldBe Some(Invalid("Nope")) - } - - "bisequenceOption should yield consistent result with bitraverseOption" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid: Validated = Valid(a) - val invalid: Validated = Invalid(b) - - valid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe - valid.bitraverseOption({ Some(it) }, { Some(it) }) - invalid.bimap({ Some(it) }, { Some(it) }).bisequenceOption() shouldBe - invalid.bitraverseOption({ Some(it) }, { Some(it) }) - } - } - - "bisequenceNullable should yield consistent result with bitraverseNullable" { - checkAll(Arb.string().orNull(), Arb.string().orNull()) { a: String?, b: String? -> - val valid: Validated = Valid(a) - val invalid: Validated = Invalid(b) - - valid.bimap({ it }, { it }).bisequenceNullable() shouldBe - valid.bitraverseNullable({ it }, { it }) - invalid.bimap({ it }, { it }).bisequenceNullable() shouldBe - invalid.bitraverseNullable({ it }, { it }) - } - } - - "bitraverseNullable should wrap valid or invalid in a nullable" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.bitraverseNullable({ it }, { it }) shouldBe Valid("Who") - invalid.bitraverseNullable({ it }, { it }) shouldBe Invalid("Nope") - } - - "bitraverseEither should wrap valid or invalid in an either" { - val valid = Valid("Who") - val invalid = Invalid("Nope") - - valid.bitraverseEither({ it.left() }, { it.right() }) shouldBe Valid("Who").right() - invalid.bitraverseEither({ it.left() }, { it.right() }) shouldBe "Nope".left() - } - - "bisequenceEither should yield consistent result with bitraverseEither" { - checkAll(Arb.string(), Arb.string()) { a: String, b: String -> - val valid: Validated = Valid(a) - val invalid: Validated = Invalid(b) - - valid.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe - valid.bitraverseEither({ it.left() }, { it.right() }) - invalid.bimap({ it.left() }, { it.right() }).bisequenceEither() shouldBe - invalid.bitraverseEither({ it.left() }, { it.right() }) - } - } - - "andThen should return Valid(result) if f return Valid" { - checkAll(Arb.int(), Arb.int()) { x, y -> - Valid(x).andThen { Valid(it + y) } shouldBe Valid(x + y) - } - } - - "andThen should only run f on valid instances " { - checkAll(Arb.int(), Arb.int()) { x, y -> - Invalid(x).andThen { Valid(y) } shouldBe Invalid(x) - } - } - - "andThen should return Invalid(result) if f return Invalid " { - checkAll(Arb.int(), Arb.int()) { x, y -> - Valid(x).andThen { Invalid(it + y) } shouldBe Invalid(x + y) - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/NullableTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/NullableTest.kt deleted file mode 100644 index d47281f9c0f..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/NullableTest.kt +++ /dev/null @@ -1,97 +0,0 @@ -package arrow.core.computations - -import arrow.core.Some -import io.kotest.core.spec.style.StringSpec -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.checkAll - -class NullableTest : StringSpec({ - "simple case" { - nullable { - "s".length.bind() - } shouldBe 1 - } - "multiple types" { - nullable { - val number = "s".length - val string = number.toString().bind() - string - } shouldBe "1" - } - "binding option in nullable" { - nullable { - val number = Some("s".length) - val string = number.map(Int::toString).bind() - string - } shouldBe "1" - } - "short circuit" { - nullable { - val number: Int = "s".length - (number.takeIf { it > 1 }?.toString()).bind() - throw IllegalStateException("This should not be executed") - } shouldBe null - } - "short circuit option" { - nullable { - val number = Some("s".length) - number.filter { it > 1 }.map(Int::toString).bind() - throw IllegalStateException("This should not be executed") - } shouldBe null - } - "when expression" { - nullable { - val number = "s".length.bind() - val string = when (number) { - 1 -> number.toString() - else -> null - }.bind() - string - } shouldBe "1" - } - "if expression" { - nullable { - val number = "s".length.bind() - val string = if (number == 1) { - number.toString() - } else { - null - }.bind() - string - } shouldBe "1" - } - "if expression short circuit" { - nullable { - val number = "s".length.bind() - val string = if (number != 1) { - number.toString() - } else { - null - }.bind() - string - } shouldBe null - } - "ensure null in nullable computation" { - checkAll(Arb.boolean(), Arb.int()) { predicate, i -> - nullable { - ensure(predicate) - i - } shouldBe if (predicate) i else null - } - } - - "ensureNotNull in nullable computation" { - fun square(i: Int): Int = i * i - checkAll(Arb.int().orNull()) { i: Int? -> - nullable { - val ii = i - ensureNotNull(ii) - square(ii) // Smart-cast by contract - } shouldBe i?.let(::square) - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/ResultTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/ResultTest.kt deleted file mode 100644 index 79e377605b8..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/computations/ResultTest.kt +++ /dev/null @@ -1,222 +0,0 @@ -package arrow.core.computations - -import arrow.core.Eval -import arrow.core.Tuple10 -import arrow.core.composeErrors -import arrow.core.flatMap -import arrow.core.handleErrorWith -import arrow.core.redeemWith -import arrow.core.test.result -import arrow.core.test.suspend -import arrow.core.test.throwable -import arrow.core.zip -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldNotBeNull -import io.kotest.matchers.result.shouldBeFailureOfType -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.map -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll -import kotlin.Result.Companion.failure -import kotlin.Result.Companion.success -import kotlin.coroutines.CoroutineContext -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.awaitAll -import kotlinx.coroutines.suspendCancellableCoroutine - -class ResultTest : StringSpec({ - "flatMap" { - checkAll(Arb.result(Arb.int()), Arb.result(Arb.string())) { ints, strs -> - val res = ints.flatMap { strs } - if (ints.isFailure) res shouldBe ints - else res shouldBe strs - } - } - - "handleErrorWith" { - checkAll(Arb.result(Arb.int()), Arb.result(Arb.string())) { ints, strs -> - val res = ints.handleErrorWith { strs } - if (ints.isFailure) res shouldBe strs - else res shouldBe ints - } - } - - "redeemWith" { - checkAll(Arb.result(Arb.int()), Arb.result(Arb.string()), Arb.result(Arb.string())) { ints, failed, success -> - val res = ints.redeemWith({ failed }, { success }) - if (ints.isFailure) res shouldBe failed - else res shouldBe success - } - } - - "zip" { - checkAll( - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - Arb.result(Arb.int()), - ) { a, b, c, d, e, f, g, h, i, j -> - val res = a.zip(b, c, d, e, f, g, h, i, j, ::Tuple10) - val all = listOf(a, b, c, d, e, f, g, h, i, j) - if (all.all { it.isSuccess }) res shouldBe success( - Tuple10( - a.getOrThrow(), - b.getOrThrow(), - c.getOrThrow(), - d.getOrThrow(), - e.getOrThrow(), - f.getOrThrow(), - g.getOrThrow(), - h.getOrThrow(), - i.getOrThrow(), - j.getOrThrow() - ) - ) else res shouldBe failure( - composeErrors( - a.exceptionOrNull(), - b.exceptionOrNull(), - c.exceptionOrNull(), - d.exceptionOrNull(), - e.exceptionOrNull(), - f.exceptionOrNull(), - g.exceptionOrNull(), - h.exceptionOrNull(), - i.exceptionOrNull(), - j.exceptionOrNull() - ).shouldNotBeNull() - ) - } - } - - "immediate values" { - checkAll(Arb.result(Arb.int())) { res -> - result { - res.bind() - } shouldBe res - } - } - - "suspended value" { - checkAll(Arb.result(Arb.int())) { res -> - result { - res.suspend().bind() - } shouldBe res - } - } - - "Rethrows immediate exceptions" { - checkAll(Arb.throwable(), Arb.int(), Arb.int()) { e, a, b -> - result { - success(a).bind() - success(b).suspend().bind() - throw e - } shouldBe failure(e) - } - } - - "result captures exception" { - checkAll(Arb.throwable(), Arb.int(), Arb.int()) { e, a, b -> - result { - success(a).bind() - success(b).suspend().bind() - e.suspend() - } shouldBe failure(e) - } - } - - "Can short-circuit from nested blocks" { - checkAll(Arb.throwable()) { e -> - result { - val x = eval { - failure(e).suspend().bind() - 5L - } - - x.value() - } shouldBe failure(e) - } - } - - "Can short-circuit suspended from nested blocks" { - checkAll(Arb.throwable().map { failure(it) }) { res -> - result { - val x = eval { - res.suspend().bind() - 5L - } - - x.value() - } shouldBe res - } - } - - "Can short-circuit after bind from nested blocks" { - checkAll(Arb.throwable().map { failure(it) }) { res -> - result { - val x = eval { - Eval.Now(1L).suspend().bind() - res.suspend().bind() - 5L - } - - 1 - } shouldBe res - } - } - - "Short-circuiting cancels KotlinX Coroutines" { - suspend fun completeOnCancellation(latch: CompletableDeferred, cancelled: CompletableDeferred): Unit = - suspendCancellableCoroutine { cont -> - cont.invokeOnCancellation { - if (!cancelled.complete(Unit)) fail("cancelled latch was completed twice") - else Unit - } - - if (!latch.complete(Unit)) fail("latch was completed twice") - else Unit - } - - val scope = CoroutineScope(Dispatchers.Default) - val latch = CompletableDeferred() - val cancelled = CompletableDeferred() - result { - val deferreds: List> = listOf( - scope.async { - completeOnCancellation(latch, cancelled) - success(1).bind() - }, - scope.async { - latch.await() - failure(RuntimeException()).bind() - } - ) - - deferreds.awaitAll().sum() - }.shouldBeFailureOfType() - - cancelled.await() - } - - "Computation blocks run on parent context" { - suspend fun currentContext(): CoroutineContext = - kotlin.coroutines.coroutineContext - - val parentCtx = currentContext() - result { - currentContext() shouldBe parentCtx - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EagerEffectSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EagerEffectSpec.kt deleted file mode 100644 index d7498532016..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EagerEffectSpec.kt +++ /dev/null @@ -1,145 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.identity -import arrow.core.left -import arrow.core.right -import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -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.long -import io.kotest.property.arbitrary.orNull -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll -import kotlinx.coroutines.CompletableDeferred - -class EagerEffectSpec : StringSpec({ - "try/catch - can recover from shift" { - checkAll(Arb.int(), Arb.string()) { i, s -> - eagerEffect { - try { - shift(s) - } 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() - eagerEffect { - try { - shift(s) - } 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 -> - eagerEffect { - val x: Int = - try { - shift(s) - } catch (e: Throwable) { - i - } - shift(s2) - }.fold(::identity) { fail("Should never come here") } shouldBe s2 - } - } - - "attempt - catch" { - checkAll(Arb.int(), Arb.long()) { i, l -> - eagerEffect { - attempt { - shift(l) - } catch { ll -> - ll shouldBe l - i - } - }.runCont() shouldBe i - } - } - - "attempt - no catch" { - checkAll(Arb.int(), Arb.long()) { i, l -> - eagerEffect { - attempt { - i - } catch { ll -> - ll shouldBe l - i + 1 - } - }.runCont() shouldBe i - } - } - - "immediate values" { eagerEffect { 1 }.toEither().getOrNull() shouldBe 1 } - - "immediate short-circuit" { eagerEffect { shift("hello") }.runCont() shouldBe "hello" } - - "Rethrows immediate exceptions" { - val e = RuntimeException("test") - Either.catch { eagerEffect { throw e }.runCont() } shouldBe Either.Left(e) - } - - "ensure null in eager either computation" { - checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, shift -> - either.eager { - ensure(predicate) { shift } - success - } shouldBe if (predicate) success.right() else shift.left() - } - } - - "ensureNotNull in eager either computation" { - fun square(i: Int): Int = i * i - - checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, shift: String -> - val res = - either.eager { - ensureNotNull(i) { shift } - square(i) // Smart-cast by contract - } - val expected = i?.let(::square)?.right() ?: shift.left() - res shouldBe expected - } - } - - "low-level use-case: distinguish between concurrency error and shift exception" { - val effect = eagerEffect { shift("Shift") } - val e = RuntimeException("test") - Either.catch { - eagerEffect { - try { - effect.bind() - } catch (shiftError: Suspend) { - fail("Should never come here") - } catch (eagerShiftError: Eager) { - throw e - } catch (otherError: Throwable) { - fail("Should never come here") - } - }.runCont() - } shouldBe Either.Left(e) - } - - "shift leaked results in ShiftLeakException" { - shouldThrow { - effect { - suspend { shift("failure") } - }.fold(::println) { it.invoke() } - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt deleted file mode 100644 index f151e810d9f..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt +++ /dev/null @@ -1,402 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.identity -import arrow.core.left -import arrow.core.right -import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.arbitrary -import io.kotest.property.arbitrary.boolean -import io.kotest.property.arbitrary.flatMap -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.long -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 kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -class EffectSpec : - StringSpec({ - "try/catch - can recover from shift" { - checkAll(Arb.int(), Arb.string()) { i, s -> - effect { - 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 -> - effect { - 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() - effect { - try { - shift(s) - } finally { - require(promise.complete(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() - effect { - 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 -> - effect { - 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 -> - effect { - val x: Int = - try { - shift(s.suspend()) - } catch (e: Throwable) { - i - } - shift(s2.suspend()) - } - .fold(::identity) { fail("Should never come here") } shouldBe s2 - } - } - - "attempt - catch" { - checkAll(Arb.int(), Arb.long()) { i, l -> - effect { - attempt { - shift(l) - } catch { ll -> - ll shouldBe l - i - } - }.runCont() shouldBe i - } - } - - "attempt - no catch" { - checkAll(Arb.int(), Arb.long()) { i, l -> - effect { - attempt { - i - } catch { ll -> - ll shouldBe l - i + 1 - } - }.runCont() shouldBe i - } - } - - "eagerEffect can be consumed within an Effect computation" { - checkAll(Arb.int(), Arb.int()) { a, b -> - val eager: EagerEffect = - eagerEffect { a } - - effect { - val aa = eager.bind() - aa + b.suspend() - }.runCont() shouldBe (a + b) - } - } - - "eagerEffect shift short-circuits effect computation" { - checkAll(Arb.string(), Arb.int()) { a, b -> - val eager: EagerEffect = - eagerEffect { shift(a) } - - effect { - val aa = eager.bind() - aa + b.suspend() - }.runCont() shouldBe a - } - } - - "immediate values" { effect { 1 }.value() shouldBe 1 } - - "suspended value" { effect { 1.suspend() }.value() shouldBe 1 } - - "immediate short-circuit" { - effect { shift("hello") }.runCont() shouldBe "hello" - } - - "suspended short-circuit" { - effect { shift("hello".suspend()) }.runCont() shouldBe "hello" - } - - "Rethrows immediate exceptions" { - val e = RuntimeException("test") - Either.catch { effect { throw e }.runCont() } shouldBe Either.Left(e) - } - - "Rethrows suspended exceptions" { - val e = RuntimeException("test") - Either.catch { effect { e.suspend() }.runCont() } shouldBe Either.Left(e) - } - - "Can short-circuit immediately from nested blocks" { - effect { - effect { shift("test") }.runCont() - fail("Should never reach this point") - } - .runCont() shouldBe "test" - } - - "Can short-circuit suspended from nested blocks" { - effect { - effect { shift("test".suspend()) }.runCont() - fail("Should never reach this point") - } - .runCont() shouldBe "test" - } - - "Can short-circuit immediately after suspending from nested blocks" { - effect { - effect { - 1L.suspend() - shift("test".suspend()) - } - .runCont() - fail("Should never reach this point") - } - .runCont() shouldBe "test" - } - - "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() - } - } - - "ensureNotNull in either computation" { - fun square(i: Int): Int = i * i - - checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, shift: String -> - val res = - either { - ensureNotNull(i) { shift } - square(i) // Smart-cast by contract - } - val expected = i?.let(::square)?.right() ?: shift.left() - res shouldBe expected - } - } - - "low-level use-case: distinguish between concurrency error and shift exception" { - val effect = effect { shift("Shift") } - val e = RuntimeException("test") - Either.catch { - effect { - try { - effect.bind() - } catch (eagerShiftError: Eager) { - fail("Should never come here") - } catch (shiftError: Suspend) { - e.suspend() - } catch (otherError: Throwable) { - fail("Should never come here") - } - }.runCont() - } shouldBe Either.Left(e) - } - - "low-level use-case: eager shift exception within effect computations doesn't change shift exception" { - val effect = eagerEffect { shift("Shift") } - val e = RuntimeException("test") - Either.catch { - effect { - try { - effect.bind() - } catch (eagerShiftError: Eager) { - fail("Should never come here") - } catch (shiftError: Suspend) { - e.suspend() - } catch (otherError: Throwable) { - fail("Should never come here") - } - }.runCont() - } shouldBe Either.Left(e) - } - - "#2760 - dispatching in nested Effect blocks does not make the nested Continuation to hang" { - checkAll(Arb.string()) { msg -> - fun failure(): Effect = effect { - withContext(Dispatchers.Default) {} - shift(Failure(msg)) - } - - effect { - failure().bind() - 1 - }.fold( - recover = { it }, - transform = { fail("Should never come here") }, - ) shouldBe Failure(msg) - } - } - - "#2779 - handleErrorWith does not make nested Continuations hang" { - checkAll(Arb.string()) { error -> - val failed: Effect = effect { - withContext(Dispatchers.Default) {} - shift(error) - } - - val newError: Effect, Int> = - failed.handleErrorWith { str -> - effect { shift(str.reversed().toList()) } - } - - newError.toEither() shouldBe Either.Left(error.reversed().toList()) - } - } - - "#2779 - bind nested in fold does not make nested Continuations hang" { - checkAll(Arb.string()) { error -> - val failed: Effect = effect { - withContext(Dispatchers.Default) {} - shift(error) - } - - val newError: Effect, Int> = - effect { - failed.fold({ r -> - effect, Int> { - shift(r.reversed().toList()) - }.bind() - }, ::identity) - } - - newError.toEither() shouldBe Either.Left(error.reversed().toList()) - } - } - - "Can handle thrown exceptions" { - checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> - effect { - throw RuntimeException(msg()) - }.fold( - { fallback() }, - ::identity, - ::identity - ) shouldBe fallback() - } - } - - "Can shift from thrown exceptions" { - checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> - effect { - effect { - throw RuntimeException(msg()) - }.fold( - { shift(fallback()) }, - ::identity, - { it.length } - ) - }.runCont() shouldBe fallback() - } - } - - "Can throw from thrown exceptions" { - checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> - shouldThrow { - effect { - throw RuntimeException(msg()) - }.fold( - { throw IllegalStateException(fallback()) }, - ::identity, - { it.length } - ) - }.message shouldBe fallback() - } - } - - "shift leaked results in ShiftLeakException" { - shouldThrow { - effect { - suspend { shift("failure") } - }.fold(::println) { f -> f() } - } - } - }) - -private data class Failure(val msg: String) - -suspend fun currentContext(): CoroutineContext = kotlin.coroutines.coroutineContext - -// Turn `A` into `suspend () -> A` which tests both the `immediate` and `COROUTINE_SUSPENDED` path. -private fun Arb.suspend(): Arb A> = - flatMap { a -> - arbitrary(listOf( - { a }, - suspend { a.suspend() } - )) { suspend { a.suspend() } } - } - -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 -} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/IorSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/IorSpec.kt deleted file mode 100644 index f00527e66e5..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/IorSpec.kt +++ /dev/null @@ -1,70 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.Ior -import arrow.core.toIorNel -import arrow.core.raise.iorNel -import arrow.core.test.nonEmptyList -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.int -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" { - 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!") - } - - "Concurrent - arrow.ior bind" { - checkAll(Arb.nonEmptyList(Arb.int())) { xs -> - ior(Semigroup.list()) { - xs.mapIndexed { index, s -> async { Ior.Both(listOf(s), index).bind() } }.awaitAll() - } - .mapLeft { it.toSet() } shouldBe Ior.Both(xs.toSet(), xs.indices.toList()) - } - } - - "Accumulates eagerly" { - ior.eager(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 eagerly" { - ior.eager(Semigroup.string()) { - val one = Ior.Both("Hello", 1).bind() - val two: Int = Either.Left(", World!").bind() - one + two - } shouldBe Ior.Left("Hello, World!") - } - - "iorNel accumulates using Nel" { - iorNel { - val one = Ior.Both("ErrorOne", 1).toIorNel().bind() - val two = Ior.Both("ErrorTwo", 2).toIorNel().bind() - one + two - } shouldBe Ior.Both(listOf("ErrorOne", "ErrorTwo"), 3) - } - }) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/NullableSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/NullableSpec.kt deleted file mode 100644 index bf038e10e0c..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/NullableSpec.kt +++ /dev/null @@ -1,121 +0,0 @@ -package arrow.core.continuations - -import arrow.core.Either -import arrow.core.Some -import io.kotest.core.spec.style.StringSpec -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.checkAll - -class NullableSpec : StringSpec({ - "ensure null in nullable computation" { - checkAll(Arb.boolean(), Arb.int()) { predicate, i -> - nullable.eager { - ensure(predicate) - i - } shouldBe if (predicate) i else null - } - } - - "ensureNotNull in nullable computation" { - fun square(i: Int): Int = i * i - checkAll(Arb.int().orNull()) { i: Int? -> - nullable { - ensureNotNull(i) - square(i) // Smart-cast by contract - } shouldBe i?.let(::square) - } - } - - "short circuit null" { - nullable { - val number: Int = "s".length - (number.takeIf { it > 1 }?.toString()).bind() - throw IllegalStateException("This should not be executed") - } shouldBe null - } - - "ensureNotNull short circuit" { - nullable { - val number: Int = "s".length - val x = ensureNotNull(number.takeIf { it > 1 }) - x - throw IllegalStateException("This should not be executed") - } shouldBe null - } - - "simple case" { - nullable { - "s".length.bind() - } shouldBe 1 - } - - "multiple types" { - nullable { - val number = "s".length - val string = number.toString().bind() - string - } shouldBe "1" - } - - "binding option in nullable" { - nullable { - val number = Some("s".length) - val string = number.map(Int::toString).bind() - string - } shouldBe "1" - } - - "short circuit option" { - nullable { - val number = Some("s".length) - number.filter { it > 1 }.map(Int::toString).bind() - throw IllegalStateException("This should not be executed") - } shouldBe null - } - - "when expression" { - nullable { - val number = "s".length.bind() - val string = when (number) { - 1 -> number.toString() - else -> null - }.bind() - string - } shouldBe "1" - } - - "if expression" { - nullable { - val number = "s".length.bind() - val string = if (number == 1) { - number.toString() - } else { - null - }.bind() - string - } shouldBe "1" - } - - "if expression short circuit" { - nullable { - val number = "s".length.bind() - val string = if (number != 1) { - number.toString() - } else { - null - }.bind() - string - } shouldBe null - } - - "Either can be bind" { - nullable { - val either: Either = Either.Right(4) - either.bind() + 3 - } shouldBe 7 - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/OptionSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/OptionSpec.kt deleted file mode 100644 index be7f03c6ba8..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/OptionSpec.kt +++ /dev/null @@ -1,48 +0,0 @@ -package arrow.core.continuations - -import arrow.core.None -import arrow.core.toOption -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.orNull -import io.kotest.property.checkAll - -class OptionSpec : StringSpec({ - "ensureNotNull in option computation" { - fun square(i: Int): Int = i * i - checkAll(Arb.int().orNull()) { i: Int? -> - option { - ensureNotNull(i) - square(i) // Smart-cast by contract - } shouldBe i.toOption().map(::square) - } - } - - "short circuit option" { - option { - val number: Int = "s".length - ensureNotNull(number.takeIf { it > 1 }) - throw IllegalStateException("This should not be executed") - } shouldBe None - } - - "ensureNotNull in eager option computation" { - fun square(i: Int): Int = i * i - checkAll(Arb.int().orNull()) { i: Int? -> - option { - ensureNotNull(i) - square(i) // Smart-cast by contract - } shouldBe i.toOption().map(::square) - } - } - - "eager short circuit null" { - option.eager { - val number: Int = "s".length - ensureNotNull(number.takeIf { it > 1 }) - throw IllegalStateException("This should not be executed") - } shouldBe None - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/StructuredConcurrencySpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/StructuredConcurrencySpec.kt deleted file mode 100644 index dd424f6f359..00000000000 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/StructuredConcurrencySpec.kt +++ /dev/null @@ -1,239 +0,0 @@ -package arrow.core.continuations - -import arrow.core.identity -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -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.Companion.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.awaitCancellation -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch -import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withTimeout - -class StructuredConcurrencySpec : StringSpec({ - "async - suspendCancellableCoroutine.invokeOnCancellation is called with Shifted Continuation" { - val started = CompletableDeferred() - val cancelled = CompletableDeferred() - - effect { - 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(2.seconds) { - cancelled.await().shouldNotBeNull().message shouldBe "Shifted Continuation" - } - } - - "Computation blocks run on parent context" { - val parentCtx = currentContext() - effect { currentContext() shouldBe parentCtx }.runCont() - } - - "Concurrent shift - async await" { - checkAll(Arb.int(), Arb.int()) { a, b -> - effect { - 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) - awaitCancellation() - }) { case -> require(exit.complete(case)) } - } - - effect { - 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 -> - effect { - 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) - awaitCancellation() - }) { case -> require(exit.complete(case)) } - } - - effect { - 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 -> - effect { - 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) - awaitCancellation() - }) { case -> require(exit.complete(case)) } - } - - effect { - 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 -> - shouldThrow { - coroutineScope { - val shiftedAsync = - effect> { - val fa = async { shift(a) } - async { shift(b) } - } - .fold({ fail("shift was never awaited, so it never took effect") }, ::identity) - shiftedAsync.await() - } - } - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt index ad826f6f1ad..534e6f4b21e 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/extensions/NumberInstancesTest.kt @@ -3,31 +3,54 @@ package arrow.core.extensions import arrow.core.test.laws.MonoidLaws import arrow.core.test.laws.SemiringLaws import arrow.core.test.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.byte import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.short +import kotlin.test.Test -class NumberInstancesTest : StringSpec({ +class NumberInstancesTest { - fun testAllLaws( + private fun testAllLawsSemiring( name: String, zero: F, combine: (F, F) -> F, one: F, combineMultiplicate: (F, F) -> F, - GEN: Arb, + gen: Arb, eq: (F, F) -> Boolean = { a, b -> a == b } - ) { - testLaws(SemiringLaws(name, zero, combine, one, combineMultiplicate, GEN, eq)) - testLaws(MonoidLaws(name, zero, combine, GEN, eq)) - } + ) = testLaws(SemiringLaws(name, zero, combine, one, combineMultiplicate, gen, eq)) - testAllLaws("Byte", 0, { x, y -> (x + y).toByte() }, 1, { x, y -> (x * y).toByte() }, Arb.byte()) - testAllLaws("Short", 0, { x, y -> (x + y).toShort() }, 1, { x, y -> (x * y).toShort() }, Arb.short()) - testAllLaws("Int", 0, Int::plus, 1, Int::times, Arb.int()) - testAllLaws("Long", 0, Long::plus, 1, Long::times, Arb.long()) + private fun testAllLawsMonoid( + name: String, + zero: F, + combine: (F, F) -> F, + gen: Arb, + eq: (F, F) -> Boolean = { a, b -> a == b } + ) = testLaws(MonoidLaws(name, zero, combine, gen, eq)) + + @Test fun testByteSemiring() = + testAllLawsSemiring("Byte", 0, { x, y -> (x + y).toByte() }, 1, { x, y -> (x * y).toByte() }, Arb.byte()) + + @Test fun testShortSemiring() = + testAllLawsSemiring("Short", 0, { x, y -> (x + y).toShort() }, 1, { x, y -> (x * y).toShort() }, Arb.short()) + + @Test fun testIntSemiring() = + testAllLawsSemiring("Int", 0, Int::plus, 1, Int::times, Arb.int()) + + @Test fun testLongSemiring() = + testAllLawsSemiring("Long", 0, Long::plus, 1, Long::times, Arb.long()) + + @Test fun testByteMonoid() = + testAllLawsMonoid("Byte", 0, { x, y -> (x + y).toByte() }, Arb.byte()) + + @Test fun testShortMonoid() = + testAllLawsMonoid("Short", 0, { x, y -> (x + y).toShort() }, Arb.short()) + + @Test fun testIntMonoid() = + testAllLawsMonoid("Int", 0, Int::plus, Arb.int()) -}) + @Test fun testLongMonoid() = + testAllLawsMonoid("Long", 0, Long::plus, Arb.long()) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EagerEffectSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EagerEffectSpec.kt index e468270df1a..b4954a66ae3 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EagerEffectSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EagerEffectSpec.kt @@ -4,10 +4,12 @@ import arrow.core.Either import arrow.core.identity import arrow.core.left import arrow.core.right +import io.kotest.assertions.fail import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe +import io.kotest.matchers.string.shouldStartWith +import io.kotest.matchers.types.shouldBeTypeOf import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int @@ -15,11 +17,13 @@ import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlin.test.Test import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.test.runTest @Suppress("UNREACHABLE_CODE", "UNUSED_EXPRESSION") -class EagerEffectSpec : StringSpec({ - "try/catch - can recover from raise" { +class EagerEffectSpec { + @Test fun tryCatchCanRecoverFromRaise() = runTest { checkAll(Arb.int(), Arb.string()) { i, s -> eagerEffect { try { @@ -31,7 +35,7 @@ class EagerEffectSpec : StringSpec({ } } - "try/catch - finally works" { + @Test fun tryCatchFinallyWorks() = runTest { checkAll(Arb.string(), Arb.int()) { s, i -> val promise = CompletableDeferred() eagerEffect { @@ -46,7 +50,7 @@ class EagerEffectSpec : StringSpec({ } } - "try/catch - First raise is ignored and second is returned" { + @Test fun tryCatchFirstRaiseIsIgnoredAndSecondIsReturned() = runTest { checkAll(Arb.int(), Arb.string(), Arb.string()) { i, s, s2 -> eagerEffect { try { @@ -59,7 +63,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - catch" { + @Test fun recoverCatch() = runTest { checkAll(Arb.int(), Arb.long()) { i, l -> eagerEffect { eagerEffect { @@ -72,7 +76,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - no catch" { + @Test fun recoverNoCatch() = runTest { checkAll(Arb.int(), Arb.long()) { i, l -> eagerEffect { eagerEffect { @@ -85,7 +89,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - raise from catch" { + @Test fun recoverRaiseFromCatch() = runTest { checkAll(Arb.long(), Arb.string()) { l, error -> eagerEffect { eagerEffect { @@ -98,18 +102,18 @@ class EagerEffectSpec : StringSpec({ } } - "success" { + @Test fun success() = runTest { eagerEffect { 1 } .fold({ unreachable() }, ::identity) shouldBe 1 } - "short-circuit" { + @Test fun shortCircuit() = runTest { eagerEffect { raise("hello") }.fold(::identity) { unreachable() } shouldBe "hello" } - "Rethrows exceptions" { + @Test fun rethrowsExceptions() = runTest { val e = RuntimeException("test") Either.catch { eagerEffect { throw e } @@ -117,7 +121,7 @@ class EagerEffectSpec : StringSpec({ } shouldBe Either.Left(e) } - "ensure null in eager either computation" { + @Test fun ensureNullInEagerEitherComputation() = runTest { checkAll(Arb.boolean(), Arb.int(), Arb.string()) { predicate, success, raise -> either { ensure(predicate) { raise } @@ -126,7 +130,7 @@ class EagerEffectSpec : StringSpec({ } } - "ensureNotNull in eager either computation" { + @Test fun ensureNotNullInEagerEitherComputation() = runTest { fun square(i: Int): Int = i * i checkAll(Arb.int().orNull(), Arb.string()) { i: Int?, raise: String -> @@ -139,7 +143,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - happy path" { + @Test fun recoverHappyPath() = runTest { checkAll(Arb.string()) { str -> eagerEffect { str @@ -148,7 +152,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - error path and recover" { + @Test fun recoverErrorPathAndRecover() = runTest { checkAll(Arb.int(), Arb.string()) { int, fallback -> eagerEffect { raise(int) @@ -158,7 +162,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - error path and re-raise" { + @Test fun recoverErrorPathAndReRaise() = runTest { checkAll(Arb.int(), Arb.string()) { int, fallback -> eagerEffect { raise(int) @@ -168,7 +172,7 @@ class EagerEffectSpec : StringSpec({ } } - "recover - error path and throw" { + @Test fun recoverErrorPathAndThrow() = runTest { checkAll(Arb.int(), Arb.string()) { int, msg -> shouldThrow { eagerEffect { @@ -180,7 +184,7 @@ class EagerEffectSpec : StringSpec({ } } - "catch - happy path" { + @Test fun catchHappyPath() = runTest { checkAll(Arb.string()) { str -> eagerEffect { str @@ -189,7 +193,7 @@ class EagerEffectSpec : StringSpec({ } } - "catch - error path and recover" { + @Test fun catchErrorPathAndRecover() = runTest { checkAll(Arb.string(), Arb.string()) { msg, fallback -> eagerEffect { throw RuntimeException(msg) @@ -198,7 +202,7 @@ class EagerEffectSpec : StringSpec({ } } - "catch - error path and re-raise" { + @Test fun catchErrorPathAndReRaise() = runTest { checkAll(Arb.string(), Arb.int()) { msg, fallback -> eagerEffect { throw RuntimeException(msg) @@ -207,7 +211,7 @@ class EagerEffectSpec : StringSpec({ } } - "catch - error path and throw" { + @Test fun catchErrorPathAndThrow() = runTest { checkAll(Arb.string(), Arb.string()) { msg, msg2 -> shouldThrow { eagerEffect { @@ -218,21 +222,21 @@ class EagerEffectSpec : StringSpec({ } } - "catch - reified exception and recover" { + @Test fun catchReifiedExceptionAndRecover() = runTest { eagerEffect { throw ArithmeticException() }.catch { _: ArithmeticException -> 1 } .fold({ unreachable() }, ::identity) shouldBe 1 } - "catch - reified exception and raise" { + @Test fun catchReifiedExceptionAndRaise() = runTest { eagerEffect { throw ArithmeticException("Boom!") }.catch { e: ArithmeticException -> raise(e.message.shouldNotBeNull()) } .fold(::identity) { unreachable() } shouldBe "Boom!" } - "catch - reified exception and no match" { + @Test fun catchReifiedExceptionAndNoMatch() = runTest { shouldThrow { eagerEffect { throw RuntimeException("Boom!") @@ -241,7 +245,38 @@ class EagerEffectSpec : StringSpec({ }.message shouldBe "Boom!" } - "mapError - raise and transform error" { + @Test fun shiftLeakedResultsInRaiseLeakExceptionWithException() = runTest { + shouldThrow { + val leak = CompletableDeferred Unit>() + eagerEffect { + leak.complete { raise("failure") } + throw RuntimeException("Boom") + }.fold( + { + it.shouldBeTypeOf().message shouldBe "Boom" + leak.await().invoke() + }, + { fail("Cannot be here") } + ) { fail("Cannot be here") } + }.message shouldStartWith "'raise' or 'bind' was leaked" + } + + @Test fun shiftLeakedResultsInRaiseLeakExceptionAfterRaise() = runTest { + shouldThrow { + val leak = CompletableDeferred Unit>() + eagerEffect { + leak.complete { raise("failure") } + raise("Boom!") + }.fold( + { unreachable() }, + { + it shouldBe "Boom!" + leak.await().invoke() + }) { fail("Cannot be here") } + }.message shouldStartWith "'raise' or 'bind' was leaked" + } + + @Test fun mapErrorRaiseAndTransformError() = runTest { checkAll(Arb.long(), Arb.string()) { l, s -> (eagerEffect { raise(l) @@ -252,10 +287,10 @@ class EagerEffectSpec : StringSpec({ } } - "mapError - success" { + @Test fun mapErrorSuccess() = runTest { checkAll(Arb.int()) { i -> (eagerEffect { i } mapError { unreachable() }) .get() shouldBe i } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EffectSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EffectSpec.kt index ab33d84d3f9..0cf35f71b66 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EffectSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/EffectSpec.kt @@ -12,7 +12,6 @@ import arrow.core.test.nonEmptySet import arrow.core.toNonEmptyListOrNull import io.kotest.assertions.fail import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldStartWith @@ -32,13 +31,15 @@ import kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.intrinsics.intercepted import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.startCoroutine +import kotlin.test.Test import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withContext @Suppress("UNREACHABLE_CODE") -class EffectSpec : StringSpec({ - "try/catch - can recover from raise" { +class EffectSpec { + @Test fun tryCatchCanRecoverFromRaise() = runTest { checkAll(Arb.int().suspend(), Arb.string().suspend()) { i, s -> effect { try { @@ -50,7 +51,7 @@ class EffectSpec : StringSpec({ } } - "try/catch - finally works" { + @Test fun tryCatchFinallyWorks() = runTest { checkAll(Arb.string().suspend(), Arb.int().suspend()) { s, i -> val promise = CompletableDeferred() effect { @@ -64,7 +65,7 @@ class EffectSpec : StringSpec({ } } - "try/catch - First raise is ignored and second is returned" { + @Test fun tryCatchFirstRaiseIsIgnoredAndSecondIsReturned() = runTest { checkAll(Arb.int().suspend(), Arb.string().suspend(), Arb.string().suspend()) { i, s, s2 -> effect { try { @@ -78,7 +79,7 @@ class EffectSpec : StringSpec({ } } - "recover - raise" { + @Test fun recoverRaise() = runTest { checkAll(Arb.int().suspend(), Arb.long().suspend()) { i, l -> effect { effect { @@ -91,7 +92,7 @@ class EffectSpec : StringSpec({ } } - "recover - raise and transform error" { + @Test fun recoverRaiseAndTransformError() = runTest { checkAll( Arb.long().suspend(), Arb.string().suspend() @@ -107,7 +108,7 @@ class EffectSpec : StringSpec({ } } - "recover - success" { + @Test fun recoverSuccess() = runTest { checkAll(Arb.int().suspend(), Arb.long().suspend()) { i, l -> effect { effect { i() } getOrElse { unreachable() } @@ -115,7 +116,7 @@ class EffectSpec : StringSpec({ } } - "recover + catch - raise and recover" { + @Test fun recoverCatchRaiseAndRecover() = runTest { checkAll(Arb.int().suspend(), Arb.long().suspend()) { i, l -> effect { effect { @@ -128,7 +129,7 @@ class EffectSpec : StringSpec({ } } - "recover + catch - raise and transform error" { + @Test fun recoverCatchRaiseAndTransformError() = runTest { checkAll(Arb.long().suspend(), Arb.string().suspend()) { l, s -> effect { effect { @@ -143,7 +144,7 @@ class EffectSpec : StringSpec({ val boom = RuntimeException("boom") - "recover + catch - throw and recover" { + @Test fun recoverCatchThrowAndRecover() = runTest { checkAll(Arb.int().suspend()) { i -> effect { effect { @@ -156,7 +157,7 @@ class EffectSpec : StringSpec({ } } - "recover + catch - throw and transform error" { + @Test fun recoverCatchThrowAndTransformError() = runTest { checkAll(Arb.string().suspend()) { s -> effect { effect { @@ -169,7 +170,7 @@ class EffectSpec : StringSpec({ } } - "recover + catch - raise and throw" { + @Test fun recoverCatchRaiseAndThrow() = runTest { checkAll(Arb.long().suspend(), Arb.string().suspend()) { l, s -> effect { effect { @@ -183,7 +184,7 @@ class EffectSpec : StringSpec({ } } - "recover + catch - throw and throw" { + @Test fun recoverCatchThrowAndThrow() = runTest { val boom2 = ArithmeticException("boom2") effect { effect { @@ -195,7 +196,7 @@ class EffectSpec : StringSpec({ }.fold(::identity, { unreachable() }) { unreachable() } shouldBe boom2 } - "recover + catch - success" { + @Test fun recoverCatchSuccess() = runTest { checkAll(Arb.int().suspend(), Arb.long().suspend()) { i, l -> effect { effect { i() } @@ -204,7 +205,7 @@ class EffectSpec : StringSpec({ } } - "catch - throw and throw" { + @Test fun catchThrowAndThrow() = runTest { val boom2 = ArithmeticException("boom2") effect { effect { @@ -216,7 +217,7 @@ class EffectSpec : StringSpec({ }.fold(::identity, { unreachable() }) { unreachable() } shouldBe boom2 } - "catch - throw and transform error" { + @Test fun catchThrowAndTransformError() = runTest { checkAll(Arb.string().suspend()) { s -> effect { effect { @@ -229,7 +230,7 @@ class EffectSpec : StringSpec({ } } - "catch - throw and recover" { + @Test fun catchThrowAndRecover() = runTest { checkAll(Arb.int().suspend()) { i -> effect { effect { @@ -242,7 +243,7 @@ class EffectSpec : StringSpec({ } } - "eagerEffect can be consumed within an Effect computation" { + @Test fun eagerEffectCanBeConsumedWithinAnEffectComputation() = runTest { checkAll(Arb.int(), Arb.int().suspend()) { a, b -> val eager: EagerEffect = eagerEffect { a } @@ -255,7 +256,7 @@ class EffectSpec : StringSpec({ } } - "eagerEffect raise short-circuits effect computation" { + @Test fun eagerEffectRaiseShortCircuitsEffectComputation() = runTest { checkAll(Arb.string(), Arb.int().suspend()) { a, b -> val eager: EagerEffect = eagerEffect { raise(a) } @@ -268,7 +269,7 @@ class EffectSpec : StringSpec({ } } - "eagerEffect can be consumed within an Effect computation with bind" { + @Test fun eagerEffectCanBeConsumedWithinAnEffectComputationWithBind() = runTest { checkAll(Arb.int(), Arb.int().suspend()) { a, b -> val eager: EagerEffect = eagerEffect { a } @@ -281,7 +282,7 @@ class EffectSpec : StringSpec({ } } - "eagerEffect raise short-circuits effect computation with bind" { + @Test fun eagerEffectRaiseShortCircuitsEffectComputationWithBind() = runTest { checkAll(Arb.string(), Arb.int().suspend()) { a, b -> val eager: EagerEffect = eagerEffect { raise(a) } @@ -294,14 +295,14 @@ class EffectSpec : StringSpec({ } } - "success" { + @Test fun success() = runTest { checkAll(Arb.int().suspend()) { i -> effect { i() } .getOrElse { unreachable() } shouldBe i() } } - "short-circuit" { + @Test fun shortCircuit() = runTest { checkAll(Arb.string().suspend()) { msg -> effect { raise(msg()) @@ -309,7 +310,7 @@ class EffectSpec : StringSpec({ } } - "Rethrows exceptions" { + @Test fun rethrowsExceptions() = runTest { checkAll(Arb.string().suspend()) { msg -> shouldThrow { effect { @@ -319,7 +320,7 @@ class EffectSpec : StringSpec({ } } - "Can short-circuit from nested blocks" { + @Test fun canShortCircuitFromNestedBlocks() = runTest { checkAll(Arb.string().suspend()) { msg -> effect { effect { raise(msg()) }.getOrElse { unreachable() } @@ -329,7 +330,7 @@ class EffectSpec : StringSpec({ } } - "Can short-circuit immediately after suspending from nested blocks" { + @Test fun canShortCircuitImmediatelyAfterSuspendingFromNestedBlocks() = runTest { checkAll(Arb.string().suspend()) { msg -> effect { effect { @@ -341,7 +342,7 @@ class EffectSpec : StringSpec({ } } - "ensure null in either computation" { + @Test fun ensureNullInEitherComputation() = runTest { checkAll( Arb.boolean().suspend(), Arb.int().suspend(), @@ -354,7 +355,7 @@ class EffectSpec : StringSpec({ } } - "ensureNotNull in either computation" { + @Test fun ensureNotNullInEitherComputation() = runTest { fun square(i: Int): Int = i * i checkAll(Arb.int().orNull().suspend(), Arb.string().suspend()) { i, raise -> @@ -369,7 +370,7 @@ class EffectSpec : StringSpec({ } } - "#2760 - dispatching in nested Effect blocks does not make the nested Continuation to hang" { + @Test fun issue2760DispatchingInNestedEffectBlocksDoesNotMakeTheNestedContinuationToHang() = runTest { checkAll(Arb.string()) { msg -> fun failure(): Effect = effect { withContext(Dispatchers.Default) {} @@ -386,7 +387,7 @@ class EffectSpec : StringSpec({ } } - "#2779 - handleErrorWith does not make nested Continuations hang" { + @Test fun issue2779HandleErrorWithDoesNotMakeNestedContinuationsHang() = runTest { checkAll(Arb.string()) { error -> val failed: Effect = effect { withContext(Dispatchers.Default) {} @@ -402,7 +403,7 @@ class EffectSpec : StringSpec({ } } - "#2779 - bind nested in fold does not make nested Continuations hang" { + @Test fun issue2779BindNestedInFoldDoesNotMakeNestedContinuationsHang() = runTest { checkAll(Arb.string()) { error -> val failed: Effect = effect { withContext(Dispatchers.Default) {} @@ -422,7 +423,7 @@ class EffectSpec : StringSpec({ } } - "Can handle thrown exceptions" { + @Test fun canHandleThrownExceptions() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> effect { throw RuntimeException(msg()) @@ -434,7 +435,7 @@ class EffectSpec : StringSpec({ } } - "Can raise from thrown exceptions" { + @Test fun canRaiseFromThrownExceptions() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> effect { effect { @@ -448,7 +449,7 @@ class EffectSpec : StringSpec({ } } - "Can throw from thrown exceptions" { + @Test fun canThrowFromThrownExceptions() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> shouldThrow { effect { @@ -462,7 +463,7 @@ class EffectSpec : StringSpec({ } } - "recover - happy path" { + @Test fun recoverHappyPath() = runTest { checkAll(Arb.string().suspend()) { str -> effect { str() @@ -471,7 +472,7 @@ class EffectSpec : StringSpec({ } } - "recover - error path and recover" { + @Test fun recoverErrorPathAndRecover() = runTest { checkAll(Arb.int().suspend(), Arb.string().suspend()) { int, fallback -> effect { raise(int()) @@ -481,7 +482,7 @@ class EffectSpec : StringSpec({ } } - "recover - error path and re-raise" { + @Test fun recoverErrorPathAndReRaise() = runTest { checkAll(Arb.int().suspend(), Arb.string().suspend()) { int, fallback -> effect { raise(int()) @@ -491,7 +492,7 @@ class EffectSpec : StringSpec({ } } - "recover - error path and throw" { + @Test fun recoverErrorPathAndThrow() = runTest { checkAll(Arb.int().suspend(), Arb.string().suspend()) { int, msg -> shouldThrow { effect { @@ -503,7 +504,7 @@ class EffectSpec : StringSpec({ } } - "catch - happy path" { + @Test fun catchHappyPath() = runTest { checkAll(Arb.string().suspend()) { str -> effect { str() @@ -512,7 +513,7 @@ class EffectSpec : StringSpec({ } } - "catch - error path and recover" { + @Test fun catchErrorPathAndRecover() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> effect { throw RuntimeException(msg()) @@ -521,7 +522,7 @@ class EffectSpec : StringSpec({ } } - "catch - error path and re-raise" { + @Test fun catchErrorPathAndReRaise() = runTest { checkAll(Arb.string().suspend(), Arb.int().suspend()) { msg, fallback -> effect { throw RuntimeException(msg()) @@ -530,7 +531,7 @@ class EffectSpec : StringSpec({ } } - "catch - error path and throw" { + @Test fun catchErrorPathAndThrow() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, msg2 -> effect { throw RuntimeException(msg()) @@ -541,7 +542,7 @@ class EffectSpec : StringSpec({ } } - "catch - reified error path and recover " { + @Test fun catchReifiedErrorPathAndRecover() = runTest { checkAll(Arb.string().suspend(), Arb.string().suspend()) { msg, fallback -> effect { throw ArithmeticException(msg()) @@ -552,7 +553,7 @@ class EffectSpec : StringSpec({ } } - "catch - reified error path and raise " { + @Test fun catchReifiedErrorPathAndRaise() = runTest { checkAll(Arb.string().suspend(), Arb.int().suspend()) { msg, error -> effect { throw ArithmeticException(msg()) @@ -563,7 +564,7 @@ class EffectSpec : StringSpec({ } } - "catch - reified error path and no match " { + @Test fun catchReifiedErrorPathAndNoMatch() = runTest { checkAll(Arb.string().suspend(), Arb.int().suspend()) { msg, error -> effect { throw RuntimeException(msg()) @@ -578,7 +579,7 @@ class EffectSpec : StringSpec({ } } - "catch - success" { + @Test fun catchSuccess() = runTest { checkAll(Arb.string().suspend()) { msg -> effect { msg() @@ -587,7 +588,7 @@ class EffectSpec : StringSpec({ } } - "catch - exception" { + @Test fun catchException() = runTest { checkAll(Arb.string().suspend()) { msg -> effect { throw RuntimeException(msg()) @@ -599,56 +600,56 @@ class EffectSpec : StringSpec({ } } - "accumulate, returns every error" { - checkAll(Arb.list(Arb.int(), range = 2..100)) { errors -> + @Test fun accumulateReturnsEveryError() = runTest { + checkAll(Arb.list(Arb.int(), range = 2..20)) { errors -> either, List> { mapOrAccumulate(errors) { raise(it) } } shouldBe errors.toNonEmptyListOrNull()!!.left() } } - "accumulate, returns no error" { - checkAll(Arb.list(Arb.int())) { elements -> + @Test fun accumulateReturnsNoError() = runTest { + checkAll(Arb.list(Arb.int(), range = 0..20)) { elements -> either, List> { mapOrAccumulate(elements) { it } } shouldBe elements.right() } } - "NonEmptyList - mapOrAccumulate, returns every error" { - checkAll(Arb.nonEmptyList(Arb.int(), range = 2..100)) { errors -> + @Test fun nonEmptyListMapOrAccumulateReturnsEveryError() = runTest { + checkAll(Arb.nonEmptyList(Arb.int(), range = 2..20)) { errors -> either, NonEmptyList> { mapOrAccumulate(errors) { raise(it) } } shouldBe errors.toNonEmptyListOrNull()!!.left() } } - "NonEmptyList - mapOrAccumulate, returns no error" { - checkAll(Arb.nonEmptyList(Arb.int())) { elements -> + @Test fun nonEmptyListMapOrAccumulateReturnsNoError() = runTest { + checkAll(Arb.nonEmptyList(Arb.int(), range = 0..20)) { elements -> either, NonEmptyList> { mapOrAccumulate(elements) { it } } shouldBe elements.right() } } - "NonEmptySet - mapOrAccumulate, returns every error" { - checkAll(Arb.nonEmptySet(Arb.int(), range = 2..100)) { errors -> + @Test fun nonEmptySetMapOrAccumulateReturnsEveryError() = runTest { + checkAll(Arb.nonEmptySet(Arb.int(), range = 2..20)) { errors -> either, NonEmptySet> { mapOrAccumulate(errors) { raise(it) } } shouldBe errors.toNonEmptyListOrNull()!!.left() } } - "NonEmptySet - mapOrAccumulate, returns no error" { - checkAll(Arb.nonEmptySet(Arb.int())) { elements -> + @Test fun nonEmptySetMapOrAccumulateReturnsNoError() = runTest { + checkAll(Arb.nonEmptySet(Arb.int(), range = 0..20)) { elements -> either, NonEmptySet> { mapOrAccumulate(elements) { it } } shouldBe elements.right() } } - "bindAll fails on first error" { - checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun bindAllFailsOnFirstError() = runTest { + checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.firstOrNull { it.isLeft() } ?: eithers.mapNotNull { it.getOrNull() }.right() either { eithers.bindAll() @@ -656,10 +657,8 @@ class EffectSpec : StringSpec({ } } - fun Either.leftOrNull(): E? = fold(::identity) { null } - - "accumulate - bindAll" { - checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun accumulateBindAll() = runTest { + checkAll(Arb.list(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.mapNotNull { it.leftOrNull() }.toNonEmptyListOrNull()?.left() ?: eithers.mapNotNull { it.getOrNull() }.right() @@ -672,8 +671,8 @@ class EffectSpec : StringSpec({ } } - "NonEmptyList - bindAll fails on first error" { - checkAll(Arb.nonEmptyList(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun nonEmptyListBindAllFailsOnFirstError() = runTest { + checkAll(Arb.nonEmptyList(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.firstOrNull { it.isLeft() } ?: eithers.mapNotNull { it.getOrNull() }.right() either { eithers.bindAll() @@ -681,8 +680,8 @@ class EffectSpec : StringSpec({ } } - "NonEmptyList - bindAll accumulate errors" { - checkAll(Arb.nonEmptyList(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun nonEmptyListBindAllAccumulateErrors() = runTest { + checkAll(Arb.nonEmptyList(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.mapNotNull { it.leftOrNull() }.toNonEmptyListOrNull()?.left() ?: eithers.mapNotNull { it.getOrNull() }.right() @@ -695,8 +694,8 @@ class EffectSpec : StringSpec({ } } - "NonEmptySet - bindAll fails on first error" { - checkAll(Arb.nonEmptySet(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun nonEmptySetBindAllFailsOnFirstError() = runTest { + checkAll(Arb.nonEmptySet(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.firstOrNull { it.isLeft() } ?: eithers.mapNotNull { it.getOrNull() }.toSet().right() either { eithers.bindAll() @@ -704,8 +703,8 @@ class EffectSpec : StringSpec({ } } - "NonEmptySet - bindAll accumulate errors" { - checkAll(Arb.nonEmptySet(Arb.either(Arb.int(), Arb.int()))) { eithers -> + @Test fun nonEmptySetBindAllAccumulateErrors() = runTest { + checkAll(Arb.nonEmptySet(Arb.either(Arb.int(), Arb.int()), range = 0..20)) { eithers -> val expected = eithers.mapNotNull { it.leftOrNull() }.toNonEmptyListOrNull()?.left() ?: eithers.mapNotNull { it.getOrNull() }.toSet().right() @@ -719,7 +718,7 @@ class EffectSpec : StringSpec({ } /* - "shift leaked results in RaiseLeakException" { + @Test fun shiftLeakedResultsInRaiseLeakException() = runTest { effect { suspend { raise("failure") } }.fold( @@ -730,7 +729,7 @@ class EffectSpec : StringSpec({ } */ - "shift leaked results in RaiseLeakException with exception" { + @Test fun shiftLeakedResultsInRaiseLeakExceptionWithException() = runTest { shouldThrow { val leak = CompletableDeferred Unit>() effect { @@ -746,7 +745,7 @@ class EffectSpec : StringSpec({ }.message shouldStartWith "'raise' or 'bind' was leaked" } - "shift leaked results in RaiseLeakException after raise" { + @Test fun shiftLeakedResultsInRaiseLeakExceptionAfterRaise() = runTest { shouldThrow { val leak = CompletableDeferred Unit>() effect { @@ -761,7 +760,7 @@ class EffectSpec : StringSpec({ }.message shouldStartWith "'raise' or 'bind' was leaked" } - "mapError - raise and transform error" { + @Test fun mapErrorRaiseAndTransformError() = runTest { checkAll( Arb.long().suspend(), Arb.string().suspend() @@ -775,13 +774,13 @@ class EffectSpec : StringSpec({ } } - "mapError - success" { + @Test fun mapErrorSuccess() = runTest { checkAll(Arb.int().suspend()) { i -> (effect { i() } mapError { unreachable() }) .get() shouldBe i() } } -}) +} private data class Failure(val msg: String) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/IorSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/IorSpec.kt index 71d7cd196e9..f53dd0280af 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/IorSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/IorSpec.kt @@ -3,22 +3,24 @@ package arrow.core.raise import arrow.core.Either import arrow.core.Ior import arrow.core.test.nonEmptyList +import arrow.core.toIorNel import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.checkAll +import kotlin.test.Test import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.test.runTest @Suppress( "UNREACHABLE_CODE", "IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION", "UNUSED_VARIABLE" ) -class IorSpec : StringSpec({ - "Accumulates" { +class IorSpec { + @Test fun accumulates() = runTest { ior(String::plus) { val one = Ior.Both("Hello", 1).bind() val two = Ior.Both(", World!", 2).bind() @@ -26,7 +28,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Both("Hello, World!", 3) } - "Accumulates and short-circuits with Left" { + @Test fun accumulatesAndShortCircuitsWithLeft() = runTest { ior(String::plus) { val one = Ior.Both("Hello", 1).bind() val two: Int = Ior.Left(", World!").bind() @@ -34,7 +36,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Left("Hello, World!") } - "Accumulates with Either" { + @Test fun accumulatesWithEither() = runTest { ior(String::plus) { val one = Ior.Both("Hello", 1).bind() val two: Int = Either.Left(", World!").bind() @@ -42,8 +44,8 @@ class IorSpec : StringSpec({ } shouldBe Ior.Left("Hello, World!") } - "Concurrent - arrow.ior bind" { - checkAll(Arb.nonEmptyList(Arb.int())) { xs -> + @Test fun concurrentArrowIorBind() = runTest { + checkAll(Arb.nonEmptyList(Arb.int(), range = 0 .. 20)) { xs -> ior(List::plus) { xs.mapIndexed { index, s -> async { Ior.Both(listOf(s), index).bind() } }.awaitAll() } @@ -51,7 +53,7 @@ class IorSpec : StringSpec({ } } - "Accumulates eagerly" { + @Test fun accumulatesEagerly() = runTest { ior(String::plus) { val one = Ior.Both("Hello", 1).bind() val two = Ior.Both(", World!", 2).bind() @@ -59,7 +61,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Both("Hello, World!", 3) } - "Accumulates with Either eagerly" { + @Test fun accumulatesWithEitherEagerly() = runTest { ior(String::plus) { val one = Ior.Both("Hello", 1).bind() val two: Int = Either.Left(", World!").bind() @@ -67,14 +69,14 @@ class IorSpec : StringSpec({ } shouldBe Ior.Left("Hello, World!") } - "Accumulates and short-circuits with raise" { + @Test fun accumulatesAndShortCircuits() = runTest { ior(String::plus) { Ior.Both("Hello", Unit).bind() raise(" World") } shouldBe Ior.Left("Hello World") } - "Ior rethrows exception" { + @Test fun iorRethrowsException() = runTest { val boom = RuntimeException("Boom!") shouldThrow { ior(String::plus) { @@ -83,7 +85,7 @@ class IorSpec : StringSpec({ }.message shouldBe "Boom!" } - "Recover works as expected" { + @Test fun recoverWorksAsExpected() = runTest { ior(String::plus) { val one = recover({ Ior.Both("Hi", Unit).bind() @@ -98,7 +100,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Both("Hi, World", 6) } - "recover with throw" { + @Test fun recoverWithThrow() = runTest { ior(String::plus) { val one = try { recover({ @@ -116,7 +118,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Both("Hi, World", 6) } - "recover with raise is a no-op" { + @Test fun recoverWithRaiseIsNoOp() = runTest { ior(String::plus) { val one: Int = recover({ @@ -131,7 +133,7 @@ class IorSpec : StringSpec({ } shouldBe Ior.Left("Hi, Hello") } - "try catch can recover from raise" { + @Test fun tryCatchRecoverRaise() = runTest { ior(String::plus) { val one = try { Ior.Both("Hi", Unit).bind() @@ -144,4 +146,12 @@ class IorSpec : StringSpec({ one + two + three } shouldBe Ior.Both("Hi, World", 6) } -}) + + @Test fun iorNelAccumulates() = runTest { + iorNel { + val one = Ior.Both("ErrorOne", 1).toIorNel().bind() + val two = Ior.Both("ErrorTwo", 2).toIorNel().bind() + one + two + } shouldBe Ior.Both(listOf("ErrorOne", "ErrorTwo"), 3) + } +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/MappersSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/MappersSpec.kt index 9f2571f0fdc..32c62a557fe 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/MappersSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/MappersSpec.kt @@ -6,8 +6,6 @@ import arrow.core.merge import arrow.core.none import arrow.core.test.either import arrow.core.toOption -import arrow.core.raise.toOption -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.constant @@ -17,89 +15,77 @@ import io.kotest.property.arbitrary.string import io.kotest.property.checkAll import kotlin.Result.Companion.failure import kotlin.Result.Companion.success +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class MappersSpec : StringSpec({ - "effect - toEither" { +class MappersSpec { + @Test fun effectToEither() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> effect { a.bind() }.toEither() shouldBe a } } - "eagerEffect - toEither" { + @Test fun eagerEffectToEither() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> eagerEffect { a.bind() }.toEither() shouldBe a } } - "effect - toValidated" { - checkAll(Arb.either(Arb.int(), Arb.string())) { a -> - effect { a.bind() }.toValidated() shouldBe a.toValidated() - } - } - - "eagerEffect - toValidated" { - checkAll(Arb.either(Arb.int(), Arb.string())) { a -> - eagerEffect { a.bind() }.toValidated() shouldBe a.toValidated() - } - } - - "effect - toIor" { + @Test fun effectToIor() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> effect { a.bind() }.toIor() shouldBe a.fold({ Ior.Left(it) }, { Ior.Right(it) }) } } - "eagerEffect - toIor" { + @Test fun eagerEffectToIor() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> eagerEffect { a.bind() }.toIor() shouldBe a.fold({ Ior.Left(it) }, { Ior.Right(it) }) } } - "effect - getOrNull" { + @Test fun effectGetOrNull() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> - effect { a.bind() }.orNull() shouldBe a.getOrNull() effect { a.bind() }.getOrNull() shouldBe a.getOrNull() } } - "eagerEffect - getOrNull" { + @Test fun eagerEffectGetOrNull() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> - eagerEffect { a.bind() }.orNull() shouldBe a.getOrNull() eagerEffect { a.bind() }.getOrNull() shouldBe a.getOrNull() } } - "effect - toOption { none() }" { + @Test fun effectToOptionNone() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> effect { a.bind() }.toOption { none() } shouldBe a.getOrNull().toOption() } } - "eagerEffect - toOption { none() }" { + @Test fun eagerEffectToOptionNone() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> eagerEffect { a.bind() }.toOption { none() } shouldBe a.getOrNull().toOption() } } - "effect - toOption" { + @Test fun effectToOption() = runTest { checkAll(Arb.either(Arb.constant(None), Arb.string())) { a -> effect { a.bind() }.toOption() shouldBe a.getOrNull().toOption() } } - "eagerEffect - toOption" { + @Test fun eagerEffectToOption() = runTest { checkAll(Arb.either(Arb.constant(None), Arb.string())) { a -> eagerEffect { a.bind() }.toOption() shouldBe a.getOrNull().toOption() } } - "effect - toResult { }" { + @Test fun effectToResultWithBlock() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> effect { a.bind() }.toResult { success(it) } shouldBe a.fold({ success(it) }, { success(it) }) } } - "eagerEffect - toResult { }" { + @Test fun eagerEffectToResultWithBlock() = runTest { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> eagerEffect { a.bind() }.toResult { success(it) } shouldBe a.fold({ success(it) }, { success(it) }) } @@ -107,47 +93,47 @@ class MappersSpec : StringSpec({ val boom = RuntimeException("Boom!") - "effect - toResult { } - exception" { + @Test fun effectToResultWithBlockException() = runTest { effect { throw boom }.toResult { success(it) } shouldBe failure(boom) } - "eagerEffect - toResult { } - exception" { + @Test fun eagerEffectToResultWithBlockException() = runTest { checkAll(Arb.string()) { a -> eagerEffect { throw boom }.toResult { success(it) } shouldBe failure(boom) } } - "effect - toResult()" { + @Test fun effectToResult() = runTest { checkAll(Arb.either(Arb.string().map { RuntimeException(it) }, Arb.string())) { a -> effect { a.bind() }.toResult() shouldBe a.fold({ failure(it) }, { success(it) }) } } - "eagerEffect - toResult()" { + @Test fun eagerEffectToResult() = runTest { checkAll(Arb.either(Arb.string().map { RuntimeException(it) }, Arb.string())) { a -> eagerEffect { a.bind() }.toResult() shouldBe a.fold({ failure(it) }, { success(it) }) } } - "effect - toResult() - exception" { + @Test fun effectToResultException() = runTest { effect { throw boom }.toResult() shouldBe failure(boom) } - "eagerEffect - toResult() - exception" { + @Test fun eagerEffectToResultException() = runTest { checkAll(Arb.string()) { a -> eagerEffect { throw boom }.toResult() shouldBe failure(boom) } } - "effect - merge" { + @Test fun effectMerge() = runTest { checkAll(Arb.either(Arb.string(), Arb.string())) { a -> effect { a.bind() }.merge() shouldBe a.merge() } } - "eagerEffect - merge" { + @Test fun eagerEffectMerge() = runTest { checkAll(Arb.either(Arb.string(), Arb.string())) { a -> eagerEffect { a.bind() }.merge() shouldBe a.merge() } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/NullableSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/NullableSpec.kt index 98de52812c2..433ddd713ca 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/NullableSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/NullableSpec.kt @@ -2,19 +2,19 @@ package arrow.core.raise import arrow.core.Either import arrow.core.Some -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.nulls.shouldNotBeNull +import arrow.core.test.any 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.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -@Suppress("UNREACHABLE_CODE") -class NullableSpec : StringSpec({ - "ensure null in nullable computation" { +@Suppress("IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION") +class NullableSpec { + @Test fun ensureNullInNullableComputation() = runTest { checkAll(Arb.boolean(), Arb.int()) { predicate, i -> nullable { ensure(predicate) @@ -23,7 +23,7 @@ class NullableSpec : StringSpec({ } } - "ensureNotNull in nullable computation" { + @Test fun ensureNotNullInNullableComputation() = runTest { fun square(i: Int): Int = i * i checkAll(Arb.int().orNull()) { i: Int? -> nullable { @@ -33,29 +33,29 @@ class NullableSpec : StringSpec({ } } - "short circuit null" { - nullable { + @Test fun shortCircuitNull() = runTest { + nullable { val number: Int = "s".length (number.takeIf { it > 1 }?.toString()).bind() throw IllegalStateException("This should not be executed") } shouldBe null } - "ensureNotNull short circuit" { - nullable { + @Test fun ensureNotNullShortCircuit() = runTest { + nullable { val number: Int = "s".length ensureNotNull(number.takeIf { it > 1 }) throw IllegalStateException("This should not be executed") } shouldBe null } - "simple case" { + @Test fun simpleCase() = runTest { nullable { "s".length.bind() } shouldBe 1 } - "multiple types" { + @Test fun multipleTypes() = runTest { nullable { val number = "s".length val string = number.toString().bind() @@ -63,7 +63,7 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "binding option in nullable" { + @Test fun bindingOptionInNullable() = runTest { nullable { val number = Some("s".length) val string = number.map(Int::toString).bind() @@ -71,7 +71,7 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "binding either in nullable" { + @Test fun bindingEitherInNullable() = runTest { nullable { val number = Either.Right("s".length) val string = number.map(Int::toString).bind() @@ -79,7 +79,7 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "binding either in nullable, ignore errors" { + @Test fun bindingEitherInNullableIgnoreErrors() = runTest { nullable { val number = Either.Right("s".length) as Either val string = ignoreErrors { number.map(Int::toString).bind() } @@ -87,15 +87,34 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "short circuit option" { - nullable { + @Test fun raisingInIgnoreErrorsReturnsNone() = runTest { + checkAll(Arb.any()) { a -> + nullable { + ignoreErrors { raise(a) } + } shouldBe null + } + } + + @Test fun ignoreErrorsAcceptsCallableReferences() = runTest { + fun Raise.foo(): Int = raise(42) + val bar: Raise.() -> Unit = { raise("s") } + nullable { + ignoreErrors(Raise::foo) + } shouldBe null + nullable { + ignoreErrors(bar) + } shouldBe null + } + + @Test fun shortCircuitOption() = runTest { + nullable { val number = Some("s".length) number.filter { it > 1 }.map(Int::toString).bind() throw IllegalStateException("This should not be executed") } shouldBe null } - "when expression" { + @Test fun whenExpression() = runTest { nullable { val number = "s".length.bind() val string = when (number) { @@ -106,7 +125,7 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "if expression" { + @Test fun ifExpression() = runTest { nullable { val number = "s".length.bind() val string = if (number == 1) { @@ -118,7 +137,7 @@ class NullableSpec : StringSpec({ } shouldBe "1" } - "if expression short circuit" { + @Test fun ifExpressionShortCircuit() = runTest { nullable { val number = "s".length.bind() val string = if (number != 1) { @@ -130,18 +149,18 @@ class NullableSpec : StringSpec({ } shouldBe null } - "Either can be bind" { + @Test fun eitherOfNothingAndSomethingCanBeBound() = runTest { nullable { val either: Either = Either.Right(4) either.bind() + 3 } shouldBe 7 } - "Recover works as expected" { + @Test fun recoverWorksAsExpected() = runTest { nullable { val one: Int = recover({ null.bind() }) { 1 } val two = 2.bind() one + two } shouldBe 3 } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/OptionSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/OptionSpec.kt index 7490e643be3..f7718213a8e 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/OptionSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/OptionSpec.kt @@ -1,20 +1,20 @@ package arrow.core.raise -import arrow.core.None -import arrow.core.Some -import arrow.core.some -import arrow.core.toOption -import io.kotest.core.spec.style.StringSpec +import arrow.core.* +import arrow.core.test.any 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.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class OptionSpec : StringSpec({ +@Suppress("IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION") +class OptionSpec { - "ensure" { + @Test fun ensure() = runTest { checkAll(Arb.boolean(), Arb.int()) { b, i -> option { ensure(b) @@ -23,7 +23,7 @@ class OptionSpec : StringSpec({ } } - "ensureNotNull in option computation" { + @Test fun ensureNotNullInOptionComputation() = runTest { fun square(i: Int): Int = i * i checkAll(Arb.int().orNull()) { i: Int? -> option { @@ -33,19 +33,26 @@ class OptionSpec : StringSpec({ } } - "short circuit option" { - @Suppress("UNREACHABLE_CODE") + @Test fun shortCircuitOption() = runTest { option { ensureNotNull(null) throw IllegalStateException("This should not be executed") } shouldBe None } - "Recover works as expected" { + @Test fun raisingInIgnoreErrorsReturnsNone() = runTest { + checkAll(Arb.any()) { a -> + option { + ignoreErrors { raise(a) } + } shouldBe None + } + } + + @Test fun RecoverWorksAsExpected() = runTest { option { val one: Int = recover({ None.bind() }) { 1 } val two = Some(2).bind() one + two } shouldBe Some(3) } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/RaiseAccumulateSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/RaiseAccumulateSpec.kt index 64584c77789..c8f68853a72 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/RaiseAccumulateSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/RaiseAccumulateSpec.kt @@ -3,11 +3,12 @@ package arrow.core.raise import arrow.core.NonEmptyList import arrow.core.left import arrow.core.nonEmptyListOf -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class RaiseAccumulateSpec : StringSpec({ - "RaiseAccumulate takes precedence over extension function" { +class RaiseAccumulateSpec { + @Test fun raiseAccumulateTakesPrecedenceOverExtensionFunction() = runTest { either, Int> { zipOrAccumulate( { ensure(false) { "false" } }, @@ -15,4 +16,4 @@ class RaiseAccumulateSpec : StringSpec({ ) { _, _ -> 1 } } shouldBe nonEmptyListOf("false", "1: IsFalse", "2: IsFalse").left() } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/ResultSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/ResultSpec.kt index db631c2700b..126f6c4b77b 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/ResultSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/ResultSpec.kt @@ -1,31 +1,31 @@ package arrow.core.raise -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -@Suppress("UNREACHABLE_CODE") -class ResultSpec : StringSpec({ +class ResultSpec { val boom = RuntimeException("Boom!") - "Result - exception" { + @Test fun resultException() = runTest { result { throw boom } shouldBe Result.failure(boom) } - "Result - success" { + @Test fun resultSuccess() = runTest { result { 1 } shouldBe Result.success(1) } - "Result - raise" { + @Test fun resultRaise() = runTest { result { raise(boom) } shouldBe Result.failure(boom) } - "Recover works as expected" { + @Test fun recoverWorksAsExpected() = runTest { result { val one: Int = recover({ Result.failure(boom).bind() }) { 1 } val two = Result.success(2).bind() one + two } shouldBe Result.success(3) } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/StructuredConcurrencySpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/StructuredConcurrencySpec.kt index ed13026edd8..c358316a75c 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/StructuredConcurrencySpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/StructuredConcurrencySpec.kt @@ -5,7 +5,6 @@ import arrow.fx.coroutines.ExitCase import arrow.fx.coroutines.guaranteeCase import io.kotest.assertions.fail import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.collections.shouldBeIn import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe @@ -15,6 +14,7 @@ import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlin.test.Test import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineScope @@ -27,11 +27,12 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.launch import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withTimeout @Suppress("DeferredResultUnused") -class StructuredConcurrencySpec : StringSpec({ - "async - suspendCancellableCoroutine.invokeOnCancellation is called with Raised Continuation" { +class StructuredConcurrencySpec { + @Test fun asyncSuspendCancellableCoroutineInvokeOnCancellationIsCalledWithRaisedContinuation() = runTest { val started = CompletableDeferred() val cancelled = CompletableDeferred() @@ -58,13 +59,13 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Computation blocks run on parent context" { + @Test fun computationBlocksRunOnParentContext() = runTest { val parentCtx = currentCoroutineContext() effect { currentCoroutineContext() shouldBe parentCtx } .fold({ fail("Should never be here") }, ::identity) } - "Concurrent raise - async await" { + @Test fun concurrentRaiseAsyncAwait() = runTest { checkAll(Arb.int(), Arb.int()) { a, b -> effect { coroutineScope { @@ -77,7 +78,7 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Concurrent raise - async await exit results" { + @Test fun concurrentRaiseAsyncAwaitExitResults() = runTest { checkAll(Arb.int()) { a -> val scopeExit = CompletableDeferred() val fbExit = CompletableDeferred() @@ -121,7 +122,7 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Concurrent raise - async" { + @Test fun concurrentRaiseAsync() = runTest { checkAll(Arb.int(), Arb.int()) { a, b -> effect { coroutineScope { @@ -135,7 +136,7 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Concurrent raise - async exit results" { + @Test fun concurrentRaiseAsyncExitResults() = runTest { checkAll(Arb.int(), Arb.string()) { a, str -> val exitScope = CompletableDeferred() val startLatches = (0..10).map { CompletableDeferred() } @@ -171,7 +172,7 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Concurrent raise - launch" { + @Test fun concurrentRaiseLaunch() = runTest { checkAll(Arb.int(), Arb.int()) { a, b -> effect { coroutineScope { @@ -184,7 +185,7 @@ class StructuredConcurrencySpec : StringSpec({ } } - "Concurrent raise - launch exit results" { + @Test fun concurrentRaiseLaunchExitResults() = runTest { checkAll(Arb.int(), Arb.string()) { a, str -> val scopeExit = CompletableDeferred() val startLatches = (0..10).map { CompletableDeferred() } @@ -222,7 +223,7 @@ class StructuredConcurrencySpec : StringSpec({ // `raise` escapes `cont` block, and gets rethrown inside `coroutineScope`. // Effectively awaiting/executing DSL code, outside of the DSL... - "async funky scenario #1 - Extract `raise` from `effect` through `async`" { + @Test fun asyncFunkyScenario1ExtractRaiseFromEffectThroughAsync() = runTest { checkAll(Arb.int(), Arb.int()) { a, b -> shouldThrow { coroutineScope { @@ -237,4 +238,4 @@ class StructuredConcurrencySpec : StringSpec({ }.message shouldStartWith "'raise' or 'bind' was leaked" } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt index 1e3058acbfb..85ca6c969bf 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/TraceSpec.kt @@ -2,17 +2,18 @@ package arrow.core.raise import arrow.core.right import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlin.test.Test import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.test.runTest @OptIn(ExperimentalTraceApi::class) -class TraceSpec : StringSpec({ - "trace is empty when no errors" { +class TraceSpec { + @Test fun traceIsEmptyWhenNoErrors() = runTest { checkAll(Arb.int()) { i -> either { traced({ i }) { _,_ -> unreachable() } @@ -20,7 +21,7 @@ class TraceSpec : StringSpec({ } } - "trace is empty with exception" { + @Test fun traceIsEmptyWithException() = runTest { checkAll(Arb.string()) { msg -> val error = RuntimeException(msg) shouldThrow { @@ -31,7 +32,7 @@ class TraceSpec : StringSpec({ } } - "nested tracing - identity" { + @Test fun nestedTracingIdentity() = runTest { val inner = CompletableDeferred() ior(String::plus) { traced({ @@ -44,7 +45,7 @@ class TraceSpec : StringSpec({ } } - "nested tracing - different types" { + @Test fun nestedTracingDifferentTypes() = runTest { either { traced({ traced ({ @@ -53,4 +54,4 @@ class TraceSpec : StringSpec({ }) { _, unit -> unit shouldBe Unit } } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/predef.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/predef.kt similarity index 50% rename from arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/predef.kt rename to arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/predef.kt index c608946d68b..07aac344e0b 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/predef.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/raise/predef.kt @@ -1,11 +1,11 @@ -package arrow.core.continuations +package arrow.core.raise import arrow.core.identity suspend fun Effect.value(): A = fold(::identity, ::identity) -suspend fun Effect<*, *>.runCont(): Any? = fold(::identity, ::identity) +suspend fun Effect.runCont(): Any? = fold(::identity, ::identity) fun EagerEffect.value(): A = fold(::identity, ::identity) -fun EagerEffect<*, *>.runCont(): Any? = fold(::identity, ::identity) +fun EagerEffect.runCont(): Any? = fold(::identity, ::identity) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt index 7ed39f82b30..3885baf1f0f 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt @@ -1,24 +1,13 @@ package arrow.core.test -import arrow.core.Either -import arrow.core.Endo -import arrow.core.Eval -import arrow.core.Ior -import arrow.core.NonEmptyList -import arrow.core.NonEmptySet -import arrow.core.Option -import arrow.core.Validated -import arrow.core.left -import arrow.core.memoize -import arrow.core.right -import arrow.core.toNonEmptySetOrNull -import arrow.core.toOption +import arrow.core.* import io.kotest.property.Arb import io.kotest.property.arbitrary.arbitrary import io.kotest.property.arbitrary.bind import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.constant +import io.kotest.property.arbitrary.filter import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.set @@ -41,7 +30,9 @@ import kotlin.coroutines.startCoroutine // copied from kotest-extensions-arrow fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.bind(arb, Arb.list(arb, range), ::NonEmptyList) + Arb.list(arb, max(range.first, 1) .. range.last) + .filter { it.isNotEmpty() } + .map { NonEmptyList(it) } fun Arb.Companion.nonEmptySet(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.set(arb, max(range.first, 1) .. range.last).map { it.toNonEmptySetOrNull()!! } @@ -50,11 +41,13 @@ fun Arb.Companion.sequence(arb: Arb, range: IntRange = 0 .. 100): Arb Arb.Companion.functionAToB(arb: Arb): Arb<(A) -> B> = arbitrary { random -> - { _: A -> arb.next(random) }.memoize() + val memoized = MemoizedDeepRecursiveFunction { _ -> arb.next(random) } + fun (x: A): B = memoized(x) } fun Arb.Companion.functionABCToD(arb: Arb): Arb<(A, B, C) -> D> = arbitrary { random -> - { _: A, _:B, _:C -> arb.next(random)}.memoize() + val memoized = MemoizedDeepRecursiveFunction, D> { _ -> arb.next(random) } + fun (x: A, y: B, z: C): D = memoized(Triple(x, y, z)) } fun Arb.Companion.throwable(): Arb = @@ -69,8 +62,6 @@ fun Arb.Companion.intSmall(factor: Int = 10000): Arb = fun Arb.Companion.longSmall(): Arb = Arb.long((Long.MIN_VALUE / 100000L)..(Long.MAX_VALUE / 100000L)) -fun Arb.Companion.endo(arb: Arb): Arb> = arb.map { a: A -> Endo { a } } - fun Arb.Companion.option(arb: Arb): Arb> = arb.orNull().map { it.toOption() } @@ -80,20 +71,19 @@ fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { return Arb.choice(arbLeft, arbRight) } -fun Arb.Companion.validated(arbE: Arb, arbA: Arb): Arb> = - Arb.either(arbE, arbA).map { Validated.fromEither(it) } - fun Arb.Companion.unit(): Arb = Arb.constant(Unit) fun Arb.Companion.ior(arbA: Arb, arbB: Arb): Arb> = arbA.alignWith(arbB) { it } -fun Arb.eval(): Arb> = - map { Eval.now(it) } - private fun Arb.alignWith(arbB: Arb, transform: (Ior) -> R): Arb = - Arb.bind(this, arbB) { a, b -> transform(Ior.Both(a, b)) } + Arb.choice( + this.map { Ior.Left(it) }, + Arb.bind(this, arbB) { a, b -> Ior.Both(a, b) }, + arbB.map { Ior.Right(it) } + ).map(transform) + fun Arb.Companion.suspendFunThatReturnsEitherAnyOrAnyOrThrows(): Arb Either> = choice( @@ -233,7 +223,7 @@ private fun Map?, Option?>>.destructured(): Pair< } fun Arb.Companion.map2(arbK: Arb, arbA: Arb, arbB: Arb): Arb, Map>> = - Arb.map(keyArb = arbK, valueArb = value2(arbA, arbB)) + Arb.map(keyArb = arbK, valueArb = value2(arbA, arbB), maxSize = 30) .map { it.destructured() } fun Arb.Companion.map3( @@ -242,5 +232,5 @@ fun Arb.Companion.map3( arbB: Arb, arbC: Arb ): Arb, Map, Map>> = - Arb.map(arbK, value3(arbA, arbB, arbC)) + Arb.map(arbK, value3(arbA, arbB, arbC), maxSize = 30) .map { it.destructured() } diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/GeneratorsTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/GeneratorsTest.kt index e23a4bb51be..4a6681befbe 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/GeneratorsTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/GeneratorsTest.kt @@ -1,6 +1,5 @@ package arrow.core.test -import io.kotest.core.spec.style.FreeSpec import io.kotest.inspectors.forAll import io.kotest.inspectors.forAtLeastOne import io.kotest.matchers.ints.shouldBeGreaterThan @@ -15,9 +14,11 @@ import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.next import io.kotest.property.arbitrary.orNull import io.kotest.property.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class GeneratorsTest : FreeSpec({ - "functionAToB: should return same result when invoked multiple times" { +class GeneratorsTest { + @Test fun functionAToBShouldReturnSameResultWhenInvokedMultipleTimes() = runTest { checkAll( Arb.int(), Arb.functionAToB(Arb.int()) @@ -26,7 +27,7 @@ class GeneratorsTest : FreeSpec({ } } - "functionAToB: should return some different values" { + @Test fun functionAToBShouldReturnSomeDifferentValues() = runTest { val a = Arb.int().next(fixedRandom) val a2 = Arb.int().next(fixedRandom) @@ -37,7 +38,7 @@ class GeneratorsTest : FreeSpec({ }.shouldNotBeNull() } - "functionABCToD: should return same result when invoked multiple times" { + @Test fun functionABCToDShouldReturnSameResultWhenInvokedMultipleTimes() = runTest { checkAll( Arb.int(), Arb.int(), @@ -48,7 +49,7 @@ class GeneratorsTest : FreeSpec({ } } - "functionABCToD: should return some different values" { + @Test fun functionABCToDShouldReturnSomeDifferentValues() = runTest { val a = Arb.int().next(fixedRandom) val a2 = Arb.int().next(fixedRandom) val b = Arb.int().next(fixedRandom) @@ -61,7 +62,7 @@ class GeneratorsTest : FreeSpec({ }.shouldNotBeNull() } - "Arb.map2: at least one sample should share no keys" { + @Test fun arbMap2AtLeastOneSampleShouldShareNoKeys() = runTest { val result = givenSamples( Arb.map2( Arb.int(), @@ -73,7 +74,7 @@ class GeneratorsTest : FreeSpec({ result.forAtLeastOne { it.shouldBeZero() } } - "Arb.map2: at least one sample should share some keys" { + @Test fun arbMap2AtLeastOneSampleShouldShareSomeKeys() = runTest { val result = givenSamples( Arb.map2( Arb.int(), @@ -85,7 +86,7 @@ class GeneratorsTest : FreeSpec({ result.forAtLeastOne { it.shouldBeGreaterThan(0) } } - "Arb.map2: no null values if the arb does not produce nullables" { + @Test fun arbMap2NoNullValuesIfTheArbDoesNotProduceNullables() = runTest { givenSamples(Arb.map2(Arb.int(), Arb.boolean(), Arb.boolean())) .forAll { sample -> sample.value.first.values.forAll { it.shouldNotBeNull() } @@ -93,27 +94,27 @@ class GeneratorsTest : FreeSpec({ } } - "Arb.map2: can contain null values if the arb produces nullables" { + @Test fun arbMap2CanContainNullValuesIfTheArbProducesNullables() = runTest { givenSamples(Arb.map2(Arb.int(), Arb.boolean().orNull(), Arb.boolean().orNull())) .forAtLeastOne { sample -> sample.value.first.values.forAtLeastOne { it.shouldBeNull() } } .forAtLeastOne { sample -> sample.value.second.values.forAtLeastOne { it.shouldBeNull() } } } - "Arb.map3: at least one sample should share no keys" { + @Test fun arbMap3AtLeastOneSampleShouldShareNoKeys() = runTest { val result = givenSamples(Arb.map3(Arb.int(), Arb.boolean(), Arb.boolean(), Arb.boolean())) .map { it.value.first.keys.intersect(it.value.second.keys).size }.toList() result.forAtLeastOne { it.shouldBeZero() } } - "Arb.map3: at least one sample should share some keys" { + @Test fun ArbMap3AtLeastOneSampleShouldShareSomeKeys() = runTest { val result = givenSamples(Arb.map3(Arb.int(), Arb.boolean(), Arb.boolean(), Arb.boolean())) .map { it.value.first.keys.intersect(it.value.second.keys).size }.toList() result.forAtLeastOne { it.shouldBeGreaterThan(0) } } - "Arb.map3: no null values if the arb does not produce nullables" { + @Test fun arbMap3NoNullValuesIfTheArbDoesNotProduceNullables() = runTest { givenSamples(Arb.map3(Arb.int(), Arb.boolean(), Arb.boolean(), Arb.boolean())) .forAll { sample -> sample.value.first.values.forAll { it.shouldNotBeNull() } @@ -122,13 +123,13 @@ class GeneratorsTest : FreeSpec({ } } - "Arb.map3: can contain null values if the arb produces nullables" { + @Test fun arbMap3CanContainNullValuesIfTheArbProducesNullables() = runTest { givenSamples(Arb.map3(Arb.int(), Arb.boolean().orNull(), Arb.boolean().orNull(), Arb.boolean().orNull())) .forAtLeastOne { sample -> sample.value.first.values.forAtLeastOne { it.shouldBeNull() } } .forAtLeastOne { sample -> sample.value.second.values.forAtLeastOne { it.shouldBeNull() } } .forAtLeastOne { sample -> sample.value.third.values.forAtLeastOne { it.shouldBeNull() } } } -}) +} private fun givenSamples(arb: Arb, count: Int = 250) = arb.generate(fixedRandom).take(count).toList() diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Laws.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Laws.kt index b2383454f66..6f5f25a6dc9 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Laws.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Laws.kt @@ -1,37 +1,32 @@ package arrow.core.test import io.kotest.assertions.fail -import io.kotest.core.names.TestName -import io.kotest.core.spec.style.StringSpec -import io.kotest.core.spec.style.scopes.StringSpecScope -import io.kotest.core.spec.style.scopes.addTest -import io.kotest.core.test.TestContext +import io.kotest.assertions.withClue +import kotlinx.coroutines.test.TestResult +import kotlinx.coroutines.test.runTest +import kotlin.time.Duration.Companion.seconds interface LawSet { val laws: List } -data class Law(val name: String, val test: suspend TestContext.() -> Unit) +data class Law(val name: String, val test: suspend () -> Unit) fun A.equalUnderTheLaw(b: A, f: (A, A) -> Boolean = { x, y -> x == y }): Boolean = if (f(this, b)) true else fail("Found $this but expected: $b") -fun StringSpec.testLaws(lawSet: LawSet): Unit = testLaws(lawSet.laws) +fun testLaws(lawSet: LawSet): TestResult = withClue("In $lawSet") { + testLaws(lawSet.laws) +} -fun StringSpec.testLaws(vararg laws: List): Unit = laws - .flatMap { list: List -> list.asIterable() } - .distinctBy { law: Law -> law.name } - .forEach { law: Law -> - addTest(TestName(null, law.name, false), false, null) { - law.test(StringSpecScope(this.coroutineContext, testCase)) +fun testLaws(vararg laws: List): TestResult = runTest(timeout = (30 * laws.size).seconds) { + laws + .flatMap(List::asIterable) + .distinctBy(Law::name) + .forEach { law: Law -> + withClue("Testing ${law.name}") { + law.test() + } } - } +} -fun StringSpec.testLaws(prefix: String, vararg laws: List): Unit = laws - .flatMap { list: List -> list.asIterable() } - .distinctBy { law: Law -> law.name } - .forEach { law: Law -> - addTest(TestName(prefix, law.name, false), false, null) { - law.test(StringSpecScope(this.coroutineContext, testCase)) - } - } diff --git a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/NonFatal.kt b/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/NonFatal.kt index 5074cadc9b4..b27c7f3bdcb 100644 --- a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/NonFatal.kt +++ b/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/NonFatal.kt @@ -2,11 +2,10 @@ @file:JvmName("NonFatalKt") package arrow.core -import arrow.continuations.generic.ControlThrowable import kotlin.coroutines.cancellation.CancellationException public actual fun NonFatal(t: Throwable): Boolean = when (t) { - is VirtualMachineError, is ThreadDeath, is InterruptedException, is LinkageError, is ControlThrowable, is CancellationException -> false + is VirtualMachineError, is ThreadDeath, is InterruptedException, is LinkageError, is CancellationException -> false else -> true } diff --git a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/AtomicRef.kt b/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/AtomicRef.kt deleted file mode 100644 index 564deb22311..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/AtomicRef.kt +++ /dev/null @@ -1,7 +0,0 @@ -@file:JvmName("AtomicReferenceActual") - -package arrow.core.continuations - -import java.util.concurrent.atomic.AtomicReference - -public actual typealias AtomicRef = AtomicReference diff --git a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt b/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt deleted file mode 100644 index 3d9525c7331..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt +++ /dev/null @@ -1,16 +0,0 @@ -package arrow.core.continuations - -import kotlin.coroutines.cancellation.CancellationException - -/* - * Inspired by KotlinX Coroutines: - * https://github.com/Kotlin/kotlinx.coroutines/blob/3788889ddfd2bcfedbff1bbca10ee56039e024a2/kotlinx-coroutines-core/jvm/src/Exceptions.kt#L29 - */ -public actual open class CancellationExceptionNoTrace : CancellationException("Shifted Continuation") { - override fun fillInStackTrace(): Throwable { - // Prevent Android <= 6.0 bug. - stackTrace = emptyArray() - // We don't need stacktrace on shift, it hurts performance. - return this - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/DeadlockTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/DeadlockTest.kt index 8c27c1173e3..f35bc066d08 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/DeadlockTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/DeadlockTest.kt @@ -1,28 +1,15 @@ package arrow.core -import io.kotest.core.spec.style.StringSpec import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class DeadlockTest : StringSpec({ +class DeadlockTest { - "classloader should not deadlock Validated initialization" { - runBlocking { - (0..10).map { i -> - GlobalScope.launch { - if (i % 2 == 0) { - Validated.Invalid(Unit) - } else { - Validated.Valid(null) - } - } - }.joinAll() - } - } - - "classloader should not deadlock Either initialization" { + @Test fun classLoaderShouldNotDeadlockEither() = runTest { runBlocking { (0..10).map { i -> GlobalScope.launch { @@ -32,11 +19,11 @@ class DeadlockTest : StringSpec({ Either.Right(null) } } - }.joinAll() - } + } + }.joinAll() } - "classloader should not deadlock Option initialization" { + @Test fun classLoaderShouldNotDeadlockOption() = runTest { runBlocking { (0..10).map { i -> GlobalScope.launch { @@ -50,7 +37,7 @@ class DeadlockTest : StringSpec({ } } - "classloader should not deadlock Ior initialization" { + @Test fun classLoaderShouldNotDeadlockIor() = runTest { runBlocking { (0..10).map { i -> GlobalScope.launch { @@ -63,18 +50,4 @@ class DeadlockTest : StringSpec({ }.joinAll() } } - - "classloader should not deadlock Eval initialization" { - runBlocking { - (0..10).map { i -> - GlobalScope.launch { - if (i % 2 == 0) { - Eval.Now(Unit) - } else { - Eval.Later { null } - } - } - }.joinAll() - } - } -}) +} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherJvmTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherJvmTest.kt deleted file mode 100644 index 0c71878577a..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherJvmTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package arrow.core - -import arrow.core.test.any -import arrow.core.test.suspendFunThatThrowsFatalThrowable -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.property.Arb -import io.kotest.property.checkAll - -class EitherJvmTest : StringSpec({ - "resolve should throw a Throwable when a fatal Throwable is thrown" { - checkAll( - Arb.suspendFunThatThrowsFatalThrowable(), - Arb.any(), - ) { f: suspend () -> Either, returnObject: Any -> - - val comparator: Comparator = - Comparator.comparingInt(Person::age) - .thenComparing(Person::name) - - shouldThrow { - Either.resolve( - f = { f() }, - success = { a -> handleWithPureFunction(a, returnObject) }, - error = { e -> handleWithPureFunction(e, returnObject) }, - throwable = { t -> handleWithPureFunction(t, returnObject) }, - unrecoverableState = { handleWithPureFunction(it) }, - ) - } - } - } -}) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherUsage.java deleted file mode 100644 index 15ce7a63594..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EitherUsage.java +++ /dev/null @@ -1,23 +0,0 @@ -package arrow.core; - -import kotlin.Unit; -import kotlin.jvm.functions.Function1; - -public class EitherUsage { - - public void testUsage() { - Either throwableIntegerEither = Either.tryCatch(() -> 1); - Either throwableIntegerEither1 = Either.tryCatchAndFlatten(() -> new Either.Right(1)); - Function1, Either> lift = Either.lift((b) -> b + 1); - Function1, Either> lift1 = Either.lift((a) -> a.toUpperCase(), (b) -> b + 1); - Either conditionally = Either.conditionally(true, () -> 1, () -> "1"); - Either unitIntegerEither = Either.fromNullable(1); - Integer resolve = Either.resolve( - () -> new Either.Right(1), - (a) -> new Either.Right(a + 1), - (b) -> new Either.Right(0), - (throwable) -> new Either.Left(throwable), - (throwable) -> new Either.Left(throwable) - ); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalJvmTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalJvmTest.kt deleted file mode 100644 index 269abf2acf0..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalJvmTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -package arrow.core - -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.property.Arb -import io.kotest.property.Sample -import io.kotest.property.arbitrary.arbitrary -import io.kotest.property.arbitrary.choice -import io.kotest.property.checkAll - -class EvalJvmTest : StringSpec({ - "stack safety stress test" { - checkAll(DeepEval.gen) { d: DeepEval -> - try { - d.eval.value() - } catch (e: StackOverflowError) { - fail("stack overflowed with eval-depth ${DeepEval.MAX_DEPTH}") - } - } - } -}) - -private data class DeepEval(val eval: Eval) { - sealed class O { - data class Map(val f: (Int) -> Int) : O() - data class FlatMap(val f: (Int) -> Eval) : O() - class Memoize : O() - class Defer : O() - - companion object { - val gen = Arb.choice( - arbitrary { O.Map { it + 1 } }, - arbitrary { O.FlatMap { Eval.Now(it) } }, - arbitrary { O.Memoize() }, - arbitrary { O.Defer() }, - ) - } - } - - companion object { - const val MAX_DEPTH = 10000 - - fun build(leaf: () -> Eval, os: List) = run { - tailrec fun step(i: Int, leaf: () -> Eval, cbs: MutableList<(Eval) -> Eval>): Eval = - if (i >= os.size) { - cbs.fold(leaf()) { e, f -> f(e) } - } else { - val o = os[i] - when (o) { - is O.Defer -> Eval.defer { - @Suppress("NON_TAIL_RECURSIVE_CALL") - step(i + 1, leaf, cbs) - } - is O.Memoize -> step(i + 1, leaf, cbs.also { it.add(0) { e: Eval -> e.memoize() } }) - is O.Map -> step(i + 1, leaf, cbs.also { it.add(0) { e: Eval -> e.map(o.f) } }) - is O.FlatMap -> step(i + 1, leaf, cbs.also { it.add(0) { e: Eval -> e.flatMap(o.f) } }) - } - } - - step(0, leaf, mutableListOf()) - } - - val gen = arbitrary { rs -> - val leaf = { Eval.Now(0) } - val eval = build(leaf, O.gen.samples().map(Sample::value).take(MAX_DEPTH).toList()) - DeepEval(eval) - } - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalUsage.java deleted file mode 100644 index 82d2d43f8be..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/EvalUsage.java +++ /dev/null @@ -1,12 +0,0 @@ -package arrow.core; - -public class EvalUsage { - - public void testUsage() { - Eval now = Eval.now(1); - Eval.Later later = Eval.later(() -> 1); - Eval raise = Eval.raise(new RuntimeException()); - Eval.Always always = Eval.always(() -> 1); - Eval.defer(() -> Eval.now(1)); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/IorUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/IorUsage.java index de771c5e38f..e68c26f6344 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/IorUsage.java +++ b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/IorUsage.java @@ -1,13 +1,9 @@ package arrow.core; -import kotlin.jvm.functions.Function1; - public class IorUsage { public void testUsage() { Ior, Integer> bothNel = Ior.bothNel(1, 2); Ior fromNullables = Ior.fromNullables(1, null); - Function1, Ior> lift = Ior.lift((b) -> b.toUpperCase()); - Function1, Ior> lift1 = Ior.lift((a) -> a + 1, (b) -> b.toUpperCase()); } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java deleted file mode 100644 index af0382a41c9..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java +++ /dev/null @@ -1,23 +0,0 @@ -package arrow.core; - -import java.util.Arrays; - -import static arrow.core.NonEmptyListKt.*; - -public class NonEmptyListUsage { - - public void testUsage() { - NonEmptyList integers = nonEmptyListOf(1, 2, 3, 4, 5); - int i = compareTo( - nonEmptyListOf(1, 2, 3, 4, 5), - nonEmptyListOf(1, 2, 3, 4, 5) - ); - NonEmptyList flatten = flatten(nonEmptyListOf( - nonEmptyListOf(1, 2), - nonEmptyListOf(3, 4) - )); - Option> nonEmptyListOption = NonEmptyList.fromList(Arrays.asList(1, 2, 3)); - NonEmptyList integers1 = NonEmptyList.fromListUnsafe(Arrays.asList(1, 2, 3)); - NonEmptyList integers2 = NonEmptyListKt.toNonEmptyListOrNull(Arrays.asList(1, 2, 3)); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonFatalJvmTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonFatalJvmTest.kt index a819be52fc9..c519c15f24d 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonFatalJvmTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonFatalJvmTest.kt @@ -1,10 +1,11 @@ package arrow.core import io.kotest.assertions.throwables.shouldThrowAny -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class NonFatalJvmTest : StringSpec({ +class NonFatalJvmTest { val fatals: List = listOf( InterruptedException(), @@ -15,16 +16,17 @@ class NonFatalJvmTest : StringSpec({ }, ) - "Test fatals using #invoke()" { + @Test fun testFatalsUsingInvoke() = runTest { fatals.forEach { NonFatal(it) shouldBe false } } - "Test fatals using Throwable#nonFatalOrThrow" { + + @Test fun testFatalsUsingThrowableNonFatalOrThrow() = runTest { fatals.forEach { shouldThrowAny { it.nonFatalOrThrow() } } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NullableUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NullableUsage.java deleted file mode 100644 index 51b5ac9b208..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NullableUsage.java +++ /dev/null @@ -1,8 +0,0 @@ -package arrow.core; - -public class NullableUsage { - - public void testUsage() { - Nullable.zip(1, null, 2, (a, b, c) -> a + b + c); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/OptionUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/OptionUsage.java index 23eb4be20b0..81c296a2386 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/OptionUsage.java +++ b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/OptionUsage.java @@ -1,17 +1,9 @@ package arrow.core; -import kotlin.jvm.functions.Function1; - public class OptionUsage { public void testUsage() { Option fromNullable = Option.fromNullable(null); - Option.tryCatch((throwable) -> { - throwable.printStackTrace(); - return None.INSTANCE; - }, () -> 1); - Option invoke = Option.invoke(1); - Function1, Option> lift = Option.lift((a) -> a.toUpperCase()); } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/ValidatedUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/ValidatedUsage.java deleted file mode 100644 index 26b63fdb4b4..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/ValidatedUsage.java +++ /dev/null @@ -1,19 +0,0 @@ -package arrow.core; - -import kotlin.Unit; -import kotlin.jvm.functions.Function1; - -public class ValidatedUsage { - - public void testUsage() { - Validated throwableIntegerValidated = Validated.tryCatch(() -> 1); - Validated stringIntegerValidated = Validated.tryCatch((throwable) -> throwable.getMessage(), () -> 1); - Function1, Validated> lift = Validated.lift((b) -> b + 1); - Function1, Validated> lift1 = Validated.lift((a) -> a.toUpperCase(), (b) -> b + 1); - Validated unitIntegerValidated = Validated.fromNullable(1, () -> Unit.INSTANCE); - Validated unitIntegerValidated1 = Validated.fromOption(Option.invoke(1), () -> Unit.INSTANCE); - Validated unitIntegerValidated2 = Validated.fromEither(Either.fromNullable(1)); - Validated, Integer> nonEmptyListIntegerValidated = Validated.validNel(1); - Validated, Integer> nonEmptyListObjectValidated = Validated.invalidNel("1"); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/MonoidUsageTest.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/MonoidUsageTest.java deleted file mode 100644 index 13bdafaea2c..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/MonoidUsageTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package arrow.typeclasses; - -import arrow.core.Either; -import arrow.core.Endo; -import arrow.core.Option; -import arrow.core.Validated; -import kotlin.Pair; -import kotlin.sequences.Sequence; - -import java.util.List; -import java.util.Map; - -public class MonoidUsageTest { - - public void testUsage() { - Monoid aByte = Monoid.Byte(); - Monoid aShort = Monoid.Short(); - Monoid bool = Monoid.Boolean(); - Monoid integer = Monoid.Integer(); - - Monoid string = Monoid.string(); - Monoid> list = Monoid.list(); - Monoid> sequence = Monoid.sequence(); - Monoid> either = Monoid.either(Monoid.Boolean(), Monoid.Integer()); - Monoid> endo = Monoid.endo(); - Monoid> map = Monoid.map(Semigroup.Integer()); - Monoid> option = Monoid.option(Semigroup.Integer()); - Monoid> validated = Monoid.validated(Semigroup.Integer(), Monoid.Boolean()); - Monoid> pair = Monoid.pair(Monoid.Boolean(), Monoid.Integer()); - - Monoid.constant(Monoid.Integer()); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemigroupUsageTest.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemigroupUsageTest.java deleted file mode 100644 index 57d4320f09c..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemigroupUsageTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package arrow.typeclasses; - -import arrow.core.*; -import kotlin.Pair; -import kotlin.sequences.Sequence; - -import java.util.List; -import java.util.Map; - -public class SemigroupUsageTest { - - public void testUsage() { - Semigroup bool = Semigroup.Boolean(); - Semigroup integer = Semigroup.Integer(); - Semigroup> list = Semigroup.list(); - Semigroup string = Semigroup.string(); - Semigroup> sequence = Semigroup.sequence(); - Semigroup> either = Semigroup.either(Semigroup.Boolean(), Semigroup.Integer()); - Semigroup> ior = Semigroup.ior(Semigroup.Boolean(), Semigroup.Integer()); - Semigroup> endo = Semigroup.endo(); - Semigroup> map = Semigroup.map(Semigroup.Integer()); - Semigroup> option = Semigroup.option(Semigroup.Integer()); - Semigroup> validated = Semigroup.validated(Semigroup.Boolean(), Semigroup.Integer()); - Semigroup> nonEmptyList = Semigroup.nonEmptyList(); - Semigroup> pair = Semigroup.pair(Semigroup.Boolean(), Semigroup.Integer()); - Semigroup> constant = Semigroup.constant(Semigroup.Integer()); - Semigroup aByte = Semigroup.Byte(); - Semigroup aShort = Semigroup.Short(); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemiringUsageTest.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemiringUsageTest.java deleted file mode 100644 index 05e2f5a64dc..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/typeclasses/SemiringUsageTest.java +++ /dev/null @@ -1,10 +0,0 @@ -package arrow.typeclasses; - -public class SemiringUsageTest { - - public void testUsage() { - Semiring integer = Semiring.Integer(); - Semiring aByte = Semiring.Byte(); - Semiring aShort = Semiring.Short(); - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/continuations/EffectUsage.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/EffectUsage.kt similarity index 84% rename from arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/continuations/EffectUsage.kt rename to arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/EffectUsage.kt index b61c79d6db7..d68a1cad54a 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/continuations/EffectUsage.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/EffectUsage.kt @@ -1,4 +1,4 @@ -package arrow.core.continuations +package arrow.core.raise import kotlinx.coroutines.runBlocking import kotlinx.coroutines.Dispatchers @@ -9,17 +9,17 @@ sealed interface OtherError : MyError { object Actual : OtherError } -context(EffectScope) +context(Raise) suspend fun subprogram(): Unit = println("Hello SubProgram!") -context(EffectScope) +context(Raise) suspend fun otherprogram(): Unit = println("Hello OtherProgram!") -context(EffectScope) +context(Raise) suspend fun fail(): MyResponse = - shift(OtherError.Actual) + raise(OtherError.Actual) fun main() = runBlocking(Dispatchers.Default) { @@ -38,11 +38,11 @@ object EmptyResponse : MyResponse data class ErrorResponse(val error: Throwable) : MyResponse data class BodyResponse(val body: String) : MyResponse -context(EffectScope) +context(Raise) suspend fun respondWithBody(): BodyResponse = BodyResponse("Hello Program!") -context(EffectScope) +context(Raise) suspend fun attemptOrError(): MyResponse = ErrorResponse(RuntimeException("Oh no!")) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/TraceJvmSpec.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/TraceJvmSpec.kt index caaf88af7ff..94d3d50c740 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/TraceJvmSpec.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/arrow/core/raise/TraceJvmSpec.kt @@ -1,11 +1,12 @@ package arrow.core.raise -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe - +import kotlin.test.Test +import kotlinx.coroutines.test.runTest + @OptIn(ExperimentalTraceApi::class) -class TraceJvmSpec : StringSpec({ - "Can trace a typed error" { +class TraceJvmSpec { + @Test fun canTraceATypedError() = runTest { either { traced({ raise(RuntimeException("")) }) { traced, raised -> // Remove first 2 lines: @@ -21,4 +22,4 @@ class TraceJvmSpec : StringSpec({ } } } -}) +} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-arrow-core-either-contains-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-arrow-core-either-contains-01.kt deleted file mode 100644 index 521fb6e272d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-arrow-core-either-contains-01.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleArrowCoreEitherContains01 - -import arrow.core.Either.Right -import arrow.core.Either.Left -import arrow.core.contains - -fun main() { - Right("something").contains("something") // Result: true - Right("something").contains("anything") // Result: false - Left("something").contains("something") // Result: false -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-01.kt deleted file mode 100644 index 3516aaae56c..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-01.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from EagerEffect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffect01 - -import arrow.core.continuations.eagerEffect -import io.kotest.matchers.shouldBe - -fun main() { - val shift = eagerEffect { - shift("Hello, World!") - }.fold({ str: String -> str }, { int -> int.toString() }) - shift shouldBe "Hello, World!" - - val res = eagerEffect { - 1000 - }.fold({ str: String -> str.length }, { int -> int }) - res shouldBe 1000 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-02.kt deleted file mode 100644 index 4fa5402ed60..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-02.kt +++ /dev/null @@ -1,26 +0,0 @@ -// This file was automatically generated from EagerEffect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffect02 - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Validated -import arrow.core.continuations.eagerEffect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -fun main() { - eagerEffect { - 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 }) - - eagerEffect { - 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") }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-01.kt deleted file mode 100644 index 5c14e191cc2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-01.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope01 - -import arrow.core.continuations.eagerEffect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -fun main() { - eagerEffect { - shift("SHIFT ME") - }.fold({ it shouldBe "SHIFT ME" }, { fail("Computation never finishes") }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-02.kt deleted file mode 100644 index 77b9d72a89e..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-02.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope02 - -import arrow.core.Either -import arrow.core.continuations.EagerEffect -import arrow.core.continuations.eagerEffect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -fun Either.toEagerEffect(): EagerEffect = eagerEffect { - fold({ e -> shift(e) }, ::identity) -} - -fun main() { - val either = Either.Left("failed") - eagerEffect { - val x: Int = either.toEagerEffect().bind() - x - }.toEither() shouldBe either -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-03.kt deleted file mode 100644 index c3044107ff5..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-03.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope03 - -import arrow.core.Either -import arrow.core.continuations.eagerEffect -import io.kotest.matchers.shouldBe - -fun main() { - val either = Either.Right(9) - eagerEffect { - val x: Int = either.bind() - x - }.toEither() shouldBe either -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-04.kt deleted file mode 100644 index c7e36de2b1b..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-04.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope04 - -import arrow.core.Validated -import arrow.core.continuations.eagerEffect -import io.kotest.matchers.shouldBe - -fun main() { - val validated = Validated.Valid(40) - eagerEffect { - val x: Int = validated.bind() - x - }.toValidated() shouldBe validated -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-05.kt deleted file mode 100644 index 91d6b7da7e7..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-05.kt +++ /dev/null @@ -1,15 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope05 - -import arrow.core.continuations.eagerEffect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -private val default = "failed" -fun main() { - val result = Result.success(1) - eagerEffect { - val x: Int = result.bind { _: Throwable -> default } - x - }.fold({ default }, ::identity) shouldBe result.getOrElse { default } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-06.kt deleted file mode 100644 index a21aa401fe2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-06.kt +++ /dev/null @@ -1,18 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope06 - -import arrow.core.None -import arrow.core.Option -import arrow.core.continuations.eagerEffect -import arrow.core.getOrElse -import arrow.core.identity -import io.kotest.matchers.shouldBe - -private val default = "failed" -fun main() { - val option: Option = None - eagerEffect { - val x: Int = option.bind { default } - x - }.fold({ default }, ::identity) shouldBe option.getOrElse { default } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-07.kt deleted file mode 100644 index 9338d3e4f54..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-07.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope07 - -import arrow.core.Either -import arrow.core.continuations.eagerEffect -import io.kotest.matchers.shouldBe - -fun main() { - val condition = true - val failure = "failed" - val int = 4 - eagerEffect { - ensure(condition) { failure } - int - }.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-08.kt deleted file mode 100644 index a68c64d66ca..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-08.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope08 - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Validated -import arrow.core.continuations.eagerEffect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -fun main() { - eagerEffect { - val x = Either.Right(1).bind() - val y = Validated.Valid(2).bind() - val z = - attempt { None.bind { "Option was empty" } } catch { 0 } - x + y + z - }.fold({ fail("Shift can never be the result") }, { it shouldBe 3 }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-09.kt deleted file mode 100644 index 9bd00d04b02..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eager-effect-scope-09.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from EagerEffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEagerEffectScope09 - -import arrow.core.continuations.eagerEffect -import arrow.core.continuations.ensureNotNull -import arrow.core.left -import arrow.core.right -import io.kotest.matchers.shouldBe - -fun main() { - val failure = "failed" - val int: Int? = null - eagerEffect { - ensureNotNull(int) { failure } - }.toEither() shouldBe (int?.right() ?: failure.left()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-01.kt deleted file mode 100644 index 19fc37c45ee..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-01.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffect01 - -import arrow.core.continuations.effect -import io.kotest.matchers.shouldBe - -suspend fun main() { - val shift = effect { - shift("Hello, World!") - }.fold({ str: String -> str }, { int -> int.toString() }) - shift shouldBe "Hello, World!" - - val res = effect { - 1000 - }.fold({ str: String -> str.length }, { int -> int }) - res shouldBe 1000 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-02.kt deleted file mode 100644 index 4073b9fdfce..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-02.kt +++ /dev/null @@ -1,26 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffect02 - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Validated -import arrow.core.continuations.effect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -suspend fun main() { - effect { - 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 }) - - effect { - 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") }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-01.kt index b6d7af378af..eb4cc8e5176 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-01.kt @@ -9,6 +9,6 @@ object Error val error = effect { raise(Error) } // Raise(error) -val a = error.recover { error -> User } // Success(User) -val b = error.recover { error -> raise("other-failure") } // Raise(other-failure) -val c = error.recover { error -> throw RuntimeException("BOOM") } // Exception(BOOM) +val a = error.recover { _ -> User } // Success(User) +val b = error.recover { _ -> raise("other-failure") } // Raise(other-failure) +val c = error.recover { _ -> throw RuntimeException("BOOM") } // Exception(BOOM) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-04.kt index 97ddc6117d2..72f5b3736e5 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-04.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-04.kt @@ -9,6 +9,6 @@ object Error val error = effect { raise(Error) } // Raise(error) -val a = error.mapError { error -> "some-failure" } // Raise(some-failure) +val a = error.mapError { _ -> "some-failure" } // Raise(some-failure) val b = error.mapError(Any::toString) // Raise(Error) -val c = error.mapError { error -> throw RuntimeException("BOOM") } // Exception(BOOM) +val c = error.mapError { _ -> throw RuntimeException("BOOM") } // Exception(BOOM) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-05.kt index d1fab1d6d94..73fd1a576cf 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-05.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-error-05.kt @@ -9,5 +9,5 @@ object Error val error = eagerEffect { raise(Error) } // Raise(error) -val a = error.mapError { error -> "some-failure" } // Raise(some-failure) +val a = error.mapError { _ -> "some-failure" } // Raise(some-failure) val b = error.mapError(Any::toString) // Raise(Error) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-01.kt deleted file mode 100644 index 87220b66503..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-01.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide01 - -import arrow.core.continuations.Effect -import arrow.core.continuations.effect -import arrow.core.continuations.ensureNotNull - -object EmptyPath - -fun readFile(path: String): Effect = effect { - if (path.isEmpty()) shift(EmptyPath) else Unit -} - -fun readFile2(path: String?): Effect = effect { - ensureNotNull(path) { EmptyPath } - ensure(path.isNotEmpty()) { EmptyPath } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-02.kt deleted file mode 100644 index 879d3c62f05..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-02.kt +++ /dev/null @@ -1,47 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide02 - -import arrow.core.Either -import arrow.core.Ior -import arrow.core.None -import arrow.core.continuations.Effect -import arrow.core.continuations.effect -import arrow.core.continuations.ensureNotNull -import io.kotest.matchers.collections.shouldNotBeEmpty -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeInstanceOf -import java.io.File -import java.io.FileNotFoundException - -@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?): Effect = effect { - 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 main() { - readFile("").toEither() shouldBe Either.Left(EmptyPath) - readFile("gradle.properties").toIor() shouldBe Ior.Left(FileNotFound("gradle.properties")) - readFile("README.MD").toOption { None } shouldBe None - - readFile("build.gradle.kts").fold({ _: FileError -> null }, { it }) - .shouldBeInstanceOf() - .body.shouldNotBeEmpty() -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-03.kt deleted file mode 100644 index cfd166ecda4..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-03.kt +++ /dev/null @@ -1,15 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide03 - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.continuations.Effect -import arrow.core.identity - -suspend fun Effect.toEither(): Either = - fold({ Either.Left(it) }) { Either.Right(it) } - -suspend fun Effect.toOption(): Option = - fold(::identity) { Some(it) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-04.kt deleted file mode 100644 index 039a7090e29..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-04.kt +++ /dev/null @@ -1,33 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide04 - -import arrow.core.Either -import arrow.core.continuations.Effect -import arrow.core.continuations.effect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -val failed: Effect = - effect { shift("failed") } - -val resolved: Effect = - failed.handleError { it.length } - -val newError: Effect, Int> = - failed.handleErrorWith { str -> - effect { shift(str.reversed().toList()) } - } - -val redeemed: Effect = - failed.redeem({ str -> str.length }, ::identity) - -val captured: Effect> = - effect { 1 }.attempt() - -suspend fun main() { - 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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-05.kt deleted file mode 100644 index 4ff9b792766..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-05.kt +++ /dev/null @@ -1,24 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide05 - -import arrow.core.continuations.effect -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.parZip -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.awaitCancellation - -suspend fun awaitExitCase(exit: CompletableDeferred): A = - guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } - - suspend fun main() { - val error = "Error" - val exit = CompletableDeferred() - effect { - 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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-06.kt deleted file mode 100644 index f13306a75eb..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-06.kt +++ /dev/null @@ -1,31 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide06 - -import arrow.core.continuations.effect -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.parTraverse -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.awaitCancellation - -suspend fun awaitExitCase(exit: CompletableDeferred): A = - guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } - -suspend fun CompletableDeferred.getOrNull(): A? = - if (isCompleted) await() else null - -suspend fun main() { - val error = "Error" - val exits = (0..3).map { CompletableDeferred() } - effect> { - (0..4).parTraverse { index -> - if (index == 4) shift(error) - else awaitExitCase(exits[index]) - } - }.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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-07.kt deleted file mode 100644 index 8d8340ed04e..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-07.kt +++ /dev/null @@ -1,30 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide07 - -import arrow.core.continuations.effect -import arrow.core.merge -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.raceN -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.awaitCancellation - -suspend fun awaitExitCase(exit: CompletableDeferred): A = - guaranteeCase(::awaitCancellation) { exitCase -> exit.complete(exitCase) } - -suspend fun CompletableDeferred.getOrNull(): A? = - if (isCompleted) await() else null - -suspend fun main() { - val error = "Error" - val exit = CompletableDeferred() - effect { - 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") }) - // It's possible not all parallel task got launched, and in those cases awaitCancellation never ran - exit.getOrNull()?.shouldBeTypeOf() -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-08.kt deleted file mode 100644 index d09c8f092a9..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-08.kt +++ /dev/null @@ -1,28 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide08 - -import arrow.core.continuations.effect -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.bracketCase -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf -import kotlinx.coroutines.CompletableDeferred -import java.io.BufferedReader -import java.io.File - -suspend fun main() { - val error = "Error" - val exit = CompletableDeferred() - effect { - 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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-09.kt deleted file mode 100644 index 33f99f70dc8..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-09.kt +++ /dev/null @@ -1,30 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide09 - -import arrow.core.continuations.effect -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.Resource -import arrow.fx.coroutines.fromAutoCloseable -import arrow.fx.coroutines.releaseCase -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeTypeOf -import kotlinx.coroutines.CompletableDeferred -import java.io.BufferedReader -import java.io.File - -suspend fun main() { - val error = "Error" - val exit = CompletableDeferred() - - fun bufferedReader(path: String): Resource = - Resource.fromAutoCloseable { File(path).bufferedReader() } - .releaseCase { _, exitCase -> exit.complete(exitCase) } - - effect { - 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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-10.kt deleted file mode 100644 index 1dcfa20d166..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-10.kt +++ /dev/null @@ -1,57 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide10 - -import arrow.core.continuations.Effect -import arrow.core.continuations.effect -import arrow.core.continuations.ensureNotNull -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.guaranteeCase -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import io.kotest.matchers.types.shouldBeInstanceOf -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.awaitCancellation -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.io.File -import java.io.FileNotFoundException - -@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?): Effect = effect { - 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 main() { - val exit = CompletableDeferred() - effect { - 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/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-11.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-11.kt deleted file mode 100644 index dbfd80371d3..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-11.kt +++ /dev/null @@ -1,26 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide11 - -import arrow.core.continuations.effect -import io.kotest.assertions.fail -import io.kotest.matchers.collections.shouldBeIn -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope - -suspend fun main() { - val errorA = "ErrorA" - val errorB = "ErrorB" - coroutineScope { - effect { - val fa = async { shift(errorA) } - val fb = async { shift(errorB) } - fa.await() + fb.await() - }.fold( - { error -> - println(error) - error shouldBeIn listOf(errorA, errorB) - }, - { fail("Int can never be the result") } - ) - } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-12.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-12.kt deleted file mode 100644 index da40654688d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-12.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide12 - -import arrow.core.continuations.effect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.launch - -suspend fun main() { - val errorA = "ErrorA" - val errorB = "ErrorB" - effect { - coroutineScope { - launch { shift(errorA) } - launch { shift(errorB) } - 45 - } - }.fold({ fail("Shift can never finish") }, ::println) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-13.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-13.kt deleted file mode 100644 index a11ce8f3684..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-13.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide13 - -import arrow.core.continuations.effect - -suspend fun main() { - - effect Unit> { - suspend { shift("error") } - }.fold({ }, { leakedShift -> leakedShift.invoke() }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-14.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-14.kt deleted file mode 100644 index 2417e0de106..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-guide-14.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from Effect.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectGuide14 - -import kotlinx.coroutines.launch -import kotlinx.coroutines.delay -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.runBlocking -import arrow.core.continuations.effect -import kotlin.time.Duration.Companion.seconds - -fun main(): Unit = runBlocking { - - effect { - launch { - delay(3.seconds) - shift("error") - } - 1 - }.fold(::println, ::println) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-01.kt deleted file mode 100644 index d46e9c0120f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-01.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope01 - -import arrow.core.continuations.effect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -suspend fun main() { - effect { - shift("SHIFT ME") - }.fold({ it shouldBe "SHIFT ME" }, { fail("Computation never finishes") }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-02.kt deleted file mode 100644 index 8add3675e39..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-02.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope02 - -import arrow.core.Either -import arrow.core.continuations.Effect -import arrow.core.continuations.effect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -suspend fun Either.toEffect(): Effect = effect { - fold({ e -> shift(e) }, ::identity) -} - -suspend fun main() { - val either = Either.Left("failed") - effect { - val x: Int = either.toEffect().bind() - x - }.toEither() shouldBe either -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-03.kt deleted file mode 100644 index 12a2a3eb6eb..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-03.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope03 - -import arrow.core.Either -import arrow.core.continuations.EagerEffect -import arrow.core.continuations.eagerEffect -import arrow.core.continuations.effect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -suspend fun Either.toEagerEffect(): EagerEffect = eagerEffect { - fold({ e -> shift(e) }, ::identity) -} - -suspend fun main() { - val either = Either.Left("failed") - effect { - val x: Int = either.toEagerEffect().bind() - x - }.toEither() shouldBe either -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-04.kt deleted file mode 100644 index 43d90183190..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-04.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope04 - -import arrow.core.Either -import arrow.core.continuations.effect -import io.kotest.matchers.shouldBe - -suspend fun main() { - val either = Either.Right(9) - effect { - val x: Int = either.bind() - x - }.toEither() shouldBe either -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-05.kt deleted file mode 100644 index 2a40e47b9af..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-05.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope05 - -import arrow.core.Validated -import arrow.core.continuations.effect -import io.kotest.matchers.shouldBe - -suspend fun main() { - val validated = Validated.Valid(40) - effect { - val x: Int = validated.bind() - x - }.toValidated() shouldBe validated -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-06.kt deleted file mode 100644 index 996f8515731..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-06.kt +++ /dev/null @@ -1,15 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope06 - -import arrow.core.continuations.effect -import arrow.core.identity -import io.kotest.matchers.shouldBe - -private val default = "failed" -suspend fun main() { - val result = Result.success(1) - effect { - val x: Int = result.bind { _: Throwable -> default } - x - }.fold({ default }, ::identity) shouldBe result.getOrElse { default } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-07.kt deleted file mode 100644 index 877a0362bb1..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-07.kt +++ /dev/null @@ -1,18 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope07 - -import arrow.core.None -import arrow.core.Option -import arrow.core.continuations.effect -import arrow.core.getOrElse -import arrow.core.identity -import io.kotest.matchers.shouldBe - -private val default = "failed" -suspend fun main() { - val option: Option = None - effect { - val x: Int = option.bind { default } - x - }.fold({ default }, ::identity) shouldBe option.getOrElse { default } -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-08.kt deleted file mode 100644 index 2df54254d0d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-08.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope08 - -import arrow.core.Either -import arrow.core.continuations.effect -import io.kotest.matchers.shouldBe - -suspend fun main() { - val condition = true - val failure = "failed" - val int = 4 - effect { - ensure(condition) { failure } - int - }.toEither() shouldBe if(condition) Either.Right(int) else Either.Left(failure) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-09.kt deleted file mode 100644 index 4b4ffa3eb7b..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-09.kt +++ /dev/null @@ -1,20 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope09 - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Validated -import arrow.core.continuations.effect -import io.kotest.assertions.fail -import io.kotest.matchers.shouldBe - -suspend fun main() { - effect { - val x = Either.Right(1).bind() - val y = Validated.Valid(2).bind() - val z = - attempt { None.bind { "Option was empty" } } catch { 0 } - x + y + z - }.fold({ fail("Shift can never be the result") }, { it shouldBe 3 }) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-10.kt deleted file mode 100644 index 0d0dc84b89e..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-effect-scope-10.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from EffectScope.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEffectScope10 - -import arrow.core.continuations.effect -import arrow.core.continuations.ensureNotNull -import arrow.core.left -import arrow.core.right -import io.kotest.matchers.shouldBe - -suspend fun main() { - val failure = "failed" - val int: Int? = null - effect { - ensureNotNull(int) { failure } - }.toEither() shouldBe (int?.right() ?: failure.left()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-01.kt index 313a4846eda..2239f19f668 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-01.kt @@ -1,12 +1,14 @@ // This file was automatically generated from Either.kt by Knit tool. Do not edit. package arrow.core.examples.exampleEither01 -import arrow.core.andThen - val throwsSomeStuff: (Int) -> Double = {x -> x.toDouble()} val throwsOtherThings: (Double) -> String = {x -> x.toString()} val moreThrowing: (String) -> List = {x -> listOf(x)} -val magic = throwsSomeStuff.andThen(throwsOtherThings).andThen(moreThrowing) +val magic: (Int) -> List = { x -> + val y = throwsSomeStuff(x) + val z = throwsOtherThings(y) + moreThrowing(z) +} fun main() { println ("magic = $magic") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-29.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-29.kt index 8242e495270..5d84da6fd75 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-29.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-29.kt @@ -2,12 +2,9 @@ package arrow.core.examples.exampleEither29 import arrow.core.Either -import arrow.core.Either.Left +import io.kotest.matchers.shouldBe -fun main() { - Either.Right(12).exists { it > 10 } // Result: true - Either.Right(7).exists { it > 10 } // Result: false - - val left: Either = Left(12) - left.exists { it > 10 } // Result: false +fun test() { + Either.Right(12).getOrNull() shouldBe 12 + Either.Left(12).getOrNull() shouldBe null } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-30.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-30.kt index c028afa1947..a7079e5990c 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-30.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-30.kt @@ -5,6 +5,6 @@ import arrow.core.Either import io.kotest.matchers.shouldBe fun test() { - Either.Right(12).getOrNull() shouldBe 12 - Either.Left(12).getOrNull() shouldBe null + Either.Right(12).leftOrNull() shouldBe null + Either.Left(12).leftOrNull() shouldBe 12 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-31.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-31.kt index ad28ddba595..e97cc18b45e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-31.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-31.kt @@ -2,9 +2,11 @@ package arrow.core.examples.exampleEither31 import arrow.core.Either +import arrow.core.Some +import arrow.core.None import io.kotest.matchers.shouldBe fun test() { - Either.Right(12).leftOrNull() shouldBe null - Either.Left(12).leftOrNull() shouldBe 12 + Either.Right(12).getOrNone() shouldBe Some(12) + Either.Left(12).getOrNone() shouldBe None } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-32.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-32.kt index e38a692acec..02f9c6d1dcf 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-32.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-32.kt @@ -2,11 +2,9 @@ package arrow.core.examples.exampleEither32 import arrow.core.Either -import arrow.core.Some -import arrow.core.None +import arrow.core.getOrElse import io.kotest.matchers.shouldBe fun test() { - Either.Right(12).getOrNone() shouldBe Some(12) - Either.Left(12).getOrNone() shouldBe None + Either.Left(12) getOrElse { it + 5 } shouldBe 17 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-33.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-33.kt index 4f86d88a4a3..6d1bc2c0694 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-33.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-33.kt @@ -1,10 +1,11 @@ // This file was automatically generated from Either.kt by Knit tool. Do not edit. package arrow.core.examples.exampleEither33 -import arrow.core.* +import arrow.core.Either.Left +import arrow.core.Either.Right +import arrow.core.merge - fun main(args: Array) { - //sampleStart - Either.Left("foo").isEmpty() // Result: true - Either.Right("foo").isEmpty() // Result: false +fun test() { + Right(12).merge() // Result: 12 + Left(12).merge() // Result: 12 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-34.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-34.kt index 1f9e07ab1d3..e103fb5e04e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-34.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-34.kt @@ -1,11 +1,12 @@ // This file was automatically generated from Either.kt by Knit tool. Do not edit. package arrow.core.examples.exampleEither34 - import arrow.core.* +import arrow.core.Either +import arrow.core.recover +import io.kotest.matchers.shouldBe - fun main(args: Array) { - //sampleStart - Either.Left("foo").isNotEmpty() // Result: false - Either.Right("foo").isNotEmpty() // Result: true - //sampleEnd +fun test() { + val error: Either = Either.Left("error") + val fallback: Either = error.recover { it.length } + fallback shouldBe Either.Right(5) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-35.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-35.kt index 2ac37b8e52d..25a2d584171 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-35.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-35.kt @@ -1,3 +1,12 @@ // This file was automatically generated from Either.kt by Knit tool. Do not edit. package arrow.core.examples.exampleEither35 +import arrow.core.Either +import arrow.core.recover +import io.kotest.matchers.shouldBe + +fun test() { + val error: Either = Either.Left("error") + val listOfErrors: Either, Int> = error.recover { raise(it.toList()) } + listOfErrors shouldBe Either.Left(listOf('e', 'r', 'r', 'o', 'r')) +} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-36.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-36.kt index 6b2f47a7cb1..c20356b7aa8 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-36.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-36.kt @@ -2,9 +2,20 @@ package arrow.core.examples.exampleEither36 import arrow.core.Either -import arrow.core.getOrElse +import arrow.core.catch +import io.kotest.assertions.throwables.shouldThrowUnit import io.kotest.matchers.shouldBe fun test() { - Either.Left(12) getOrElse { it + 5 } shouldBe 17 + val left: Either = Either.catch { throw RuntimeException("Boom!") } + + val caught: Either = left.catch { _: RuntimeException -> 1 } + val failure: Either = left.catch { _: RuntimeException -> raise("failure") } + + shouldThrowUnit { + val caught2: Either = left.catch { _: IllegalStateException -> 1 } + } + + caught shouldBe Either.Right(1) + failure shouldBe Either.Left("failure") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-37.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-37.kt deleted file mode 100644 index 3d3e96d3a45..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-37.kt +++ /dev/null @@ -1,10 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither37 - -import arrow.core.Either.Right -import arrow.core.Either.Left - -fun main() { - Right(12).orNull() // Result: 12 - Left(12).orNull() // Result: null -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-38.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-38.kt deleted file mode 100644 index 8e9df9d759f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-38.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither38 - -import arrow.core.Either.Right -import arrow.core.Either.Left -import arrow.core.getOrHandle - -fun main() { - Right(12).getOrHandle { 17 } // Result: 12 - Left(12).getOrHandle { it + 5 } // Result: 17 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-39.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-39.kt deleted file mode 100644 index 0d0355dbbf1..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-39.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither39 - -import arrow.core.Either.* -import arrow.core.Either -import arrow.core.filterOrElse - -fun main() { - Right(12).filterOrElse({ it > 10 }, { -1 }) // Result: Right(12) - Right(7).filterOrElse({ it > 10 }, { -1 }) // Result: Left(-1) - - val left: Either = Left(12) - left.filterOrElse({ it > 10 }, { -1 }) // Result: Left(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-40.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-40.kt deleted file mode 100644 index f77c0bcf9ab..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-40.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither40 - -import arrow.core.* - -suspend fun main(): Unit { - //sampleStart - Either.Right(7).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - .let(::println) // Either.Left(Value '7' is not equal to 10") - - Either.Right(10).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - .let(::println) // Either.Right(10) - - Either.Left(12).filterOrOther({ str: String -> str.contains("impossible") }, { -1 }) - .let(::println) // Either.Left(12) - //sampleEnd -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-41.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-41.kt deleted file mode 100644 index ff132b03d4f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-41.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither41 - -import arrow.core.Either.Left -import arrow.core.Either.Right -import arrow.core.merge - -fun test() { - Right(12).merge() // Result: 12 - Left(12).merge() // Result: 12 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-42.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-42.kt deleted file mode 100644 index ec8e1c34304..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-42.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither42 - -import arrow.core.Either.* -import arrow.core.leftIfNull - -fun main() { - Right(12).leftIfNull({ -1 }) // Result: Right(12) - Right(null).leftIfNull({ -1 }) // Result: Left(-1) - - Left(12).leftIfNull({ -1 }) // Result: Left(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-43.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-43.kt deleted file mode 100644 index 2b0a631c0bc..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-43.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither43 - -import arrow.core.rightIfNotNull - -fun main() { - "value".rightIfNotNull { "left" } // Right(b="value") - null.rightIfNotNull { "left" } // Left(a="left") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-44.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-44.kt deleted file mode 100644 index b31e2043ba4..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-44.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither44 - -import arrow.core.* - -fun main(args: Array) { - //sampleStart - val string: Either = "Hello".right() - val chars: Either = - string.widen() - //sampleEnd - println(chars) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-45.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-45.kt deleted file mode 100644 index e0479d763b2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-45.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither45 - -import arrow.core.Either -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Either = Either.Left("error") - val fallback: Either = error.recover { it.length } - fallback shouldBe Either.Right(5) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-46.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-46.kt deleted file mode 100644 index 69e88fd745f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-46.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither46 - -import arrow.core.Either -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Either = Either.Left("error") - val listOfErrors: Either, Int> = error.recover { raise(it.toList()) } - listOfErrors shouldBe Either.Left(listOf('e', 'r', 'r', 'o', 'r')) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-47.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-47.kt deleted file mode 100644 index afa0a926942..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-47.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither47 - -import arrow.core.Either -import arrow.core.catch -import io.kotest.assertions.throwables.shouldThrowUnit -import io.kotest.matchers.shouldBe - -fun test() { - val left: Either = Either.catch { throw RuntimeException("Boom!") } - - val caught: Either = left.catch { _: RuntimeException -> 1 } - val failure: Either = left.catch { _: RuntimeException -> raise("failure") } - - shouldThrowUnit { - val caught2: Either = left.catch { _: IllegalStateException -> 1 } - } - - caught shouldBe Either.Right(1) - failure shouldBe Either.Left("failure") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-48.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-48.kt deleted file mode 100644 index 8aa8c0e7a83..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-48.kt +++ /dev/null @@ -1,3 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither48 - diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-49.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-49.kt deleted file mode 100644 index 345862c7da2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-49.kt +++ /dev/null @@ -1,10 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither49 - -import arrow.core.Either -import arrow.core.getOrElse -import io.kotest.matchers.shouldBe - -fun test() { - Either.Left(12) getOrElse { it + 5 } shouldBe 17 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-50.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-50.kt deleted file mode 100644 index b26e1351247..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-50.kt +++ /dev/null @@ -1,10 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither50 - -import arrow.core.Either.Right -import arrow.core.Either.Left - -fun main() { - Right(12).orNull() // Result: 12 - Left(12).orNull() // Result: null -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-51.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-51.kt deleted file mode 100644 index 4d832b87354..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-51.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither51 - -import arrow.core.Either.Right -import arrow.core.Either.Left -import arrow.core.getOrHandle - -fun main() { - Right(12).getOrHandle { 17 } // Result: 12 - Left(12).getOrHandle { it + 5 } // Result: 17 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-52.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-52.kt deleted file mode 100644 index 1c08c82db4b..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-52.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither52 - -import arrow.core.Either.* -import arrow.core.Either -import arrow.core.filterOrElse - -fun main() { - Right(12).filterOrElse({ it > 10 }, { -1 }) // Result: Right(12) - Right(7).filterOrElse({ it > 10 }, { -1 }) // Result: Left(-1) - - val left: Either = Left(12) - left.filterOrElse({ it > 10 }, { -1 }) // Result: Left(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-53.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-53.kt deleted file mode 100644 index 641bb88ca21..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-53.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither53 - -import arrow.core.* - -suspend fun main(): Unit { - //sampleStart - Either.Right(7).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - .let(::println) // Either.Left(Value '7' is not equal to 10") - - Either.Right(10).filterOrOther({ it == 10 }, { "Value '$it' is not equal to 10" }) - .let(::println) // Either.Right(10) - - Either.Left(12).filterOrOther({ str: String -> str.contains("impossible") }, { -1 }) - .let(::println) // Either.Left(12) - //sampleEnd -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-54.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-54.kt deleted file mode 100644 index cb687671303..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-54.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither54 - -import arrow.core.Either.Left -import arrow.core.Either.Right -import arrow.core.merge - -fun test() { - Right(12).merge() // Result: 12 - Left(12).merge() // Result: 12 -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-55.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-55.kt deleted file mode 100644 index f15556fa688..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-55.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither55 - -import arrow.core.Either.* -import arrow.core.leftIfNull - -fun main() { - Right(12).leftIfNull({ -1 }) // Result: Right(12) - Right(null).leftIfNull({ -1 }) // Result: Left(-1) - - Left(12).leftIfNull({ -1 }) // Result: Left(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-56.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-56.kt deleted file mode 100644 index de7f6bf28ca..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-56.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither56 - -import arrow.core.rightIfNotNull - -fun main() { - "value".rightIfNotNull { "left" } // Right(b="value") - null.rightIfNotNull { "left" } // Left(a="left") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-57.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-57.kt deleted file mode 100644 index 4fb5842d64d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-57.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither57 - -import arrow.core.* - -fun main(args: Array) { - //sampleStart - val string: Either = "Hello".right() - val chars: Either = - string.widen() - //sampleEnd - println(chars) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-58.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-58.kt deleted file mode 100644 index e35cc2b2b3b..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-58.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither58 - -import arrow.core.Either -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Either = Either.Left("error") - val fallback: Either = error.recover { it.length } - fallback shouldBe Either.Right(5) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-59.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-59.kt deleted file mode 100644 index c9ff9ae335c..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-59.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither59 - -import arrow.core.Either -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Either = Either.Left("error") - val listOfErrors: Either, Int> = error.recover { shift(it.toList()) } - listOfErrors shouldBe Either.Left(listOf('e', 'r', 'r', 'o', 'r')) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-60.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-60.kt deleted file mode 100644 index 916bf35a1df..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-60.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from Either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEither60 - -import arrow.core.Either -import arrow.core.catch -import io.kotest.assertions.throwables.shouldThrowUnit -import io.kotest.matchers.shouldBe - -fun test() { - val left: Either = Either.catch { throw RuntimeException("Boom!") } - - val caught: Either = left.catch { _: RuntimeException -> 1 } - val failure: Either = left.catch { _: RuntimeException -> shift("failure") } - - shouldThrowUnit { - val caught2: Either = left.catch { _: IllegalStateException -> 1 } - } - - caught shouldBe Either.Right(1) - failure shouldBe Either.Left("failure") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-01.kt deleted file mode 100644 index e02ffc279db..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-01.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEitherComputations01 - -import arrow.core.computations.either - -suspend fun main() { - either { - ensure(true) { "" } - println("ensure(true) passes") - ensure(false) { "failed" } - 1 - } - .let(::println) -} -// println: "ensure(true) passes" -// res: Either.Left("failed") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-02.kt deleted file mode 100644 index ba2f60c2023..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-either-computations-02.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from either.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEitherComputations02 - -import arrow.core.computations.either -import arrow.core.computations.ensureNotNull - -suspend fun main() { - either { - val x: Int? = 1 - ensureNotNull(x) { "passes" } - println(x) - ensureNotNull(null) { "failed" } - } - .let(::println) -} -// println: "1" -// res: Either.Left("failed") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-01.kt deleted file mode 100644 index a66dcc08cd2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-01.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from Eval.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEval01 - -import arrow.core.Eval - -fun even(n: Int): Eval = - Eval.always { n == 0 }.flatMap { - if(it == true) Eval.now(true) - else odd(n - 1) - } - -fun odd(n: Int): Eval = - Eval.always { n == 0 }.flatMap { - if(it == true) Eval.now(false) - else even(n - 1) - } - -// if not wrapped in eval this type of computation would blow the stack and result in a StackOverflowError -fun main() { - println(odd(100000).value()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-02.kt deleted file mode 100644 index 0923e57eb8d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-02.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Eval.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEval02 - -import arrow.core.* - -fun main() { - val eager = Eval.now(1).map { it + 1 } - println(eager.value()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-03.kt deleted file mode 100644 index 7fd34596244..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-03.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Eval.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEval03 - -import arrow.core.* - -fun main() { - val lazyEvaled = Eval.later { "expensive computation" } - println(lazyEvaled.value()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-04.kt deleted file mode 100644 index 4b38eb8331a..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-eval-04.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Eval.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleEval04 - -import arrow.core.* - -fun main() { - val alwaysEvaled = Eval.always { "expensive computation" } - println(alwaysEvaled.value()) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-01.kt index a862230d1d2..ea0c4e2d6a9 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-01.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor01 import arrow.core.Ior fun main() { - Ior.Left("tulip").isRight // Result: false - Ior.Right("venus fly-trap").isRight // Result: true - Ior.Both("venus", "fly-trap").isRight // Result: false + Ior.Left("tulip").isLeft() // Result: true + Ior.Right("venus fly-trap").isLeft() // Result: false + Ior.Both("venus", "fly-trap").isLeft() // Result: false } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-02.kt index 54afb5ce8cb..8e909d18ff8 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-02.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-02.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor02 import arrow.core.Ior fun main() { - Ior.Left("tulip").isLeft // Result: true - Ior.Right("venus fly-trap").isLeft // Result: false - Ior.Both("venus", "fly-trap").isLeft // Result: false + Ior.Left("tulip").isRight() // Result: false + Ior.Right("venus fly-trap").isRight() // Result: true + Ior.Both("venus", "fly-trap").isRight() // Result: false } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-03.kt index 5c61a6f54ee..06db465d06c 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-03.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-03.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor03 import arrow.core.Ior fun main() { - Ior.Left("tulip").isBoth // Result: false - Ior.Right("venus fly-trap").isBoth // Result: false - Ior.Both("venus", "fly-trap").isBoth // Result: true + Ior.Left("tulip").isBoth() // Result: false + Ior.Right("venus fly-trap").isBoth() // Result: false + Ior.Both("venus", "fly-trap").isBoth() // Result: true } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-05.kt index 31da2770112..e3fc45dd583 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-05.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-05.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor05 import arrow.core.Ior fun main() { - Ior.Right(12).bimap ({ "flower" }, { 12 }) // Result: Right(12) - Ior.Left(12).bimap({ "flower" }, { 12 }) // Result: Left("flower") - Ior.Both(12, "power").bimap ({ it * 2 }, { b -> "flower $b" }) // Result: Both("flower power", 24) + Ior.Right(12).mapLeft { "flower" } // Result: Right(12) + Ior.Left(12).mapLeft { "flower" } // Result: Left("power") + Ior.Both(12, "power").mapLeft { "flower $it" } // Result: Both("flower 12", "power") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-06.kt index ddcba7ee21e..bfcabdf9925 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-06.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-06.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor06 import arrow.core.Ior fun main() { - Ior.Right(12).mapLeft { "flower" } // Result: Right(12) - Ior.Left(12).mapLeft { "flower" } // Result: Left("power") - Ior.Both(12, "power").mapLeft { "flower $it" } // Result: Both("flower 12", "power") + Ior.Left("left").swap() // Result: Right("left") + Ior.Right("right").swap() // Result: Left("right") + Ior.Both("left", "right").swap() // Result: Both("right", "left") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-07.kt index ae4f58d4278..1b670363d6e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-07.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-07.kt @@ -4,7 +4,7 @@ package arrow.core.examples.exampleIor07 import arrow.core.Ior fun main() { - Ior.Left("left").swap() // Result: Right("left") - Ior.Right("right").swap() // Result: Left("right") - Ior.Both("left", "right").swap() // Result: Both("right", "left") + Ior.Right(12).toEither() // Result: Either.Right(12) + Ior.Left(12).toEither() // Result: Either.Left(12) + Ior.Both("power", 12).toEither() // Result: Either.Right(12) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-08.kt index 3fad9702f90..9a01a122772 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-08.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-08.kt @@ -4,10 +4,9 @@ package arrow.core.examples.exampleIor08 import arrow.core.Ior fun main() { - val right = Ior.Right(12).padNull() // Result: Pair(null, 12) - val left = Ior.Left(12).padNull() // Result: Pair(12, null) - val both = Ior.Both("power", 12).padNull() // Result: Pair("power", 12) - + val right = Ior.Right(12).leftOrNull() // Result: null + val left = Ior.Left(12).leftOrNull() // Result: 12 + val both = Ior.Both(12, "power").leftOrNull() // Result: 12 println("right = $right") println("left = $left") println("both = $both") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-09.kt index 1433b18e7d8..e1a5469e45e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-09.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-09.kt @@ -4,7 +4,8 @@ package arrow.core.examples.exampleIor09 import arrow.core.Ior fun main() { - Ior.Right(12).toEither() // Result: Either.Right(12) - Ior.Left(12).toEither() // Result: Either.Left(12) - Ior.Both("power", 12).toEither() // Result: Either.Right(12) + val right: Ior = Ior.Right(12) + right.isLeft { it > 10 } // Result: false + Ior.Both(12, 7).isLeft { it > 10 } // Result: false + Ior.Left(12).isLeft { it > 10 } // Result: true } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-10.kt index de4e27ad71d..b54e4846b28 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-10.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-10.kt @@ -4,11 +4,8 @@ package arrow.core.examples.exampleIor10 import arrow.core.Ior fun main() { - val right = Ior.Right(12).orNull() // Result: 12 - val left = Ior.Left(12).orNull() // Result: null - val both = Ior.Both(12, "power").orNull() // Result: "power" - - println("right = $right") - println("left = $left") - println("both = $both") + Ior.Right(12).isRight { it > 10 } // Result: false + Ior.Both(12, 7).isRight { it > 10 } // Result: false + val left: Ior = Ior.Left(12) + left.isRight { it > 10 } // Result: true } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-11.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-11.kt index 90e3104ee0c..89f849c1541 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-11.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-11.kt @@ -4,10 +4,9 @@ package arrow.core.examples.exampleIor11 import arrow.core.Ior fun main() { - val right = Ior.Right(12).leftOrNull() // Result: null - val left = Ior.Left(12).leftOrNull() // Result: 12 - val both = Ior.Both(12, "power").leftOrNull() // Result: 12 - println("right = $right") - println("left = $left") - println("both = $both") + val right: Ior = Ior.Right(12) + right.isBoth( {it > 10}, {it > 6 }) // Result: false + Ior.Both(12, 7).isBoth( {it > 10}, {it > 6 })// Result: true + val left: Ior = Ior.Left(12) + left.isBoth ( {it > 10}, {it > 6 }) // Result: false } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-12.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-12.kt deleted file mode 100644 index 036dce24083..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-12.kt +++ /dev/null @@ -1,10 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor12 - -import arrow.core.Ior - -fun main() { - Ior.Right(12).toValidated() // Result: Valid(12) - Ior.Left(12).toValidated() // Result: Invalid(12) - Ior.Both(12, "power").toValidated() // Result: Valid("power") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-13.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-13.kt deleted file mode 100644 index bc719ff8273..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-13.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor13 - -import arrow.core.Ior - -fun main() { - Ior.Both(5, 12).exists { it > 10 } // Result: true - Ior.Right(12).exists { it > 10 } // Result: true - Ior.Right(7).exists { it > 10 } // Result: false - val left: Ior = Ior.Left(12) - left.exists { it > 10 } // Result: false -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-14.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-14.kt deleted file mode 100644 index 0bda0dd24cd..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-14.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor14 - -import arrow.core.Ior - -fun main() { - val right: Ior = Ior.Right(12) - right.isLeft { it > 10 } // Result: false - Ior.Both(12, 7).isLeft { it > 10 } // Result: false - Ior.Left(12).isLeft { it > 10 } // Result: true -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-15.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-15.kt deleted file mode 100644 index f30cc18e50d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-15.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor15 - -import arrow.core.Ior - -fun main() { - Ior.Right(12).isRight { it > 10 } // Result: false - Ior.Both(12, 7).isRight { it > 10 } // Result: false - val left: Ior = Ior.Left(12) - left.isRight { it > 10 } // Result: true -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-16.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-16.kt deleted file mode 100644 index 5f41023521e..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-16.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor16 - -import arrow.core.Ior - -fun main() { - val right: Ior = Ior.Right(12) - right.isBoth( {it > 10}, {it > 6 }) // Result: false - Ior.Both(12, 7).isBoth( {it > 10}, {it > 6 })// Result: true - val left: Ior = Ior.Left(12) - left.isBoth ( {it > 10}, {it > 6 }) // Result: false -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-17.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-17.kt deleted file mode 100644 index 3b400f931dd..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-ior-17.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Ior.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIor17 - -import arrow.core.* - -fun main(args: Array) { - //sampleStart - val string: Ior = Ior.Right("Hello") - val chars: Ior = - string.widen() - //sampleEnd - println(chars) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-14.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-14.kt index 0806b492922..cfd124b3a0b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-14.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-14.kt @@ -8,5 +8,5 @@ fun test() { listOf(1, 2, 3, 4).unalign { if(it % 2 == 0) it.rightIor() else it.leftIor() - } shouldBe Pair(listOf(1, 3), listOf(2, 4)) + } shouldBe Pair(listOf(1, null, 3, null), listOf(null, 2, null, 4)) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-18.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-18.kt index b127d9abb1b..6112994de79 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-18.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-18.kt @@ -2,13 +2,9 @@ package arrow.core.examples.exampleIterable18 import arrow.core.* +import io.kotest.matchers.shouldBe -fun main(args: Array) { - //sampleStart - val result = - listOf(1,2,3).ifThen(listOf("empty")) { i -> - listOf("$i, ${i + 1}") - } - //sampleEnd - println(result) +fun test() { + listOf("A".left(), 2.right(), "C".left(), 4.right()) + .separateEither() shouldBe Pair(listOf("A", "C"), listOf(2, 4)) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-19.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-19.kt index a0578244656..70727e5686b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-19.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-19.kt @@ -5,6 +5,8 @@ import arrow.core.* import io.kotest.matchers.shouldBe fun test() { - listOf("A".left(), 2.right(), "C".left(), 4.right()) - .separateEither() shouldBe Pair(listOf("A", "C"), listOf(2, 4)) + listOf(1, 2, 3, 4) + .separateEither { + if (it % 2 == 0) "even: $it".right() else "odd: $it".left() + } shouldBe Pair(listOf("odd: 1", "odd: 3"), listOf("even: 2", "even: 4")) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-20.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-20.kt deleted file mode 100644 index 650b1d11dc9..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-20.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Iterable.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleIterable20 - -import arrow.core.* -import io.kotest.matchers.shouldBe - -fun test() { - listOf(1, 2, 3, 4) - .separateEither { - if (it % 2 == 0) "even: $it".right() else "odd: $it".left() - } shouldBe Pair(listOf("odd: 1", "odd: 3"), listOf("even: 2", "even: 4")) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-map-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-map-02.kt index c7c4ffdd2e6..c61c582f042 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-map-02.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-map-02.kt @@ -6,6 +6,6 @@ import io.kotest.matchers.shouldBe fun test() { mapOf(1 to "A", 2 to "B").zip(mapOf(1 to "1", 2 to "2", 3 to "3")) { - key, a, b -> "$a ~ $b" + _, a, b -> "$a ~ $b" } shouldBe mapOf(1 to "A ~ 1", 2 to "B ~ 2") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatal-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatal-01.kt index 32ebd78ac2e..df6f9a58f15 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatal-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatal-01.kt @@ -11,7 +11,7 @@ fun unsafeFunction(i: Int): String = else -> "Hello" } -fun main(args: Array) { +fun main() { val nonFatal: Either = //sampleStart try { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatalorthrow-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatalorthrow-01.kt index 07bf2372556..56a31b281c2 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatalorthrow-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nonfatalorthrow-01.kt @@ -11,7 +11,7 @@ fun unsafeFunction(i: Int): String = else -> "Hello" } -fun main(args: Array) { +fun main() { val nonFatal: Either = //sampleStart try { diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-01.kt deleted file mode 100644 index 56bda9ce6f8..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-01.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from nullable.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleNullableComputations01 - -import arrow.core.computations.nullable - -suspend fun main() { - nullable { - ensure(true) - println("ensure(true) passes") - ensure(false) - 1 - } - .let(::println) -} -// println: "ensure(true) passes" -// res: null diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-02.kt deleted file mode 100644 index a14151a5e3f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-nullable-computations-02.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from nullable.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleNullableComputations02 - -import arrow.core.computations.nullable -import arrow.core.computations.ensureNotNull - -suspend fun main() { - nullable { - val x: Int? = 1 - ensureNotNull(x) - println(x) - ensureNotNull(null) - } - .let(::println) -} -// println: "1" -// res: null diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-16.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-16.kt index f4cc52a3a80..104c2c779d4 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-16.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-16.kt @@ -2,9 +2,9 @@ package arrow.core.examples.exampleOption16 import arrow.core.Some +import arrow.core.none - val value = - Some(1).zip(Some("Hello"), Some(20.0), ::Triple) fun main() { - println(value) + Some(12).onNone { println("flower") } // Result: Some(12) + none().onNone { println("flower") } // Result: prints "flower" and returns: None } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-17.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-17.kt index 4fc22facd84..edcc11f59aa 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-17.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-17.kt @@ -1,17 +1,10 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.exampleOption17 -import arrow.core.computations.option import arrow.core.Some -import arrow.core.Option +import arrow.core.none -suspend fun value(): Option = - option { - val a = Some(1).bind() - val b = Some(1 + a).bind() - val c = Some(1 + b).bind() - a + b + c -} -suspend fun main() { - println(value()) +fun main() { + Some(12).onSome { println("flower") } // Result: prints "flower" and returns: Some(12) + none().onSome { println("flower") } // Result: None } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-18.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-18.kt index e47211b5ef6..4011251b9ba 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-18.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-18.kt @@ -1,18 +1,14 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.exampleOption18 -import arrow.core.computations.option import arrow.core.Some -import arrow.core.none +import arrow.core.None import arrow.core.Option -suspend fun value(): Option = - option { - val x = none().bind() - val y = Some(1 + x).bind() - val z = Some(1 + y).bind() - x + y + z - } -suspend fun main() { - println(value()) +fun main() { + Some(12).isSome { it > 10 } // Result: true + Some(7).isSome { it > 10 } // Result: false + + val none: Option = None + none.isSome { it > 10 } // Result: false } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-19.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-19.kt index 1d9d8da23c4..3420045fd5a 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-19.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-19.kt @@ -1,10 +1,11 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.exampleOption19 +import arrow.core.None import arrow.core.Some -import arrow.core.none +import io.kotest.matchers.shouldBe -fun main() { - Some(12).onNone { println("flower") } // Result: Some(12) - none().onNone { println("flower") } // Result: prints "flower" and returns: None +fun test() { + Some(12).getOrNull() shouldBe 12 + None.getOrNull() shouldBe null } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-20.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-20.kt index 0813a51550a..8e11226743e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-20.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-20.kt @@ -1,10 +1,14 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.exampleOption20 -import arrow.core.Some +import arrow.core.Option import arrow.core.none +import arrow.core.Some +import arrow.core.recover +import io.kotest.matchers.shouldBe -fun main() { - Some(12).onSome { println("flower") } // Result: prints "flower" and returns: Some(12) - none().onSome { println("flower") } // Result: None +fun test() { + val error: Option = none() + val fallback: Option = error.recover { 5 } + fallback shouldBe Some(5) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-21.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-21.kt index fd454d93f83..a4e6dae74d9 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-21.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-21.kt @@ -1,10 +1,17 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.exampleOption21 -import arrow.core.Some +import arrow.core.Option import arrow.core.none +import arrow.core.Some +import arrow.core.recover +import io.kotest.matchers.shouldBe + +fun test() { + val error: Option = none() + fun fallback(): Option = Some(5) + fun failure(): Option = none() -fun main() { - Some(12).tapNone { println("flower") } // Result: Some(12) - none().tapNone { println("flower") } // Result: prints "flower" and returns: None + error.recover { fallback().bind() } shouldBe Some(5) + error.recover { failure().bind() } shouldBe none() } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-22.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-22.kt deleted file mode 100644 index 4b454526514..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-22.kt +++ /dev/null @@ -1,10 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption22 - -import arrow.core.Some -import arrow.core.none - -fun main() { - Some(12).tap { println("flower") } // Result: prints "flower" and returns: Some(12) - none().tap { println("flower") } // Result: None -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-23.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-23.kt deleted file mode 100644 index fc55738f1ca..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-23.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption23 - -import arrow.core.Some -import arrow.core.None -import arrow.core.Option - -fun main() { - Some(12).isSome { it > 10 } // Result: true - Some(7).isSome { it > 10 } // Result: false - - val none: Option = None - none.isSome { it > 10 } // Result: false -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-24.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-24.kt deleted file mode 100644 index 8fa7b0b4bcd..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-24.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption24 - -import arrow.core.None -import arrow.core.Some -import io.kotest.matchers.shouldBe - -fun test() { - Some(12).getOrNull() shouldBe 12 - None.getOrNull() shouldBe null -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-25.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-25.kt deleted file mode 100644 index 7a2a5bce8ed..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-25.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption25 - -import arrow.core.Some -import arrow.core.None -import arrow.core.Option - -fun main() { - Some(12).exists { it > 10 } // Result: true - Some(7).exists { it > 10 } // Result: false - - val none: Option = None - none.exists { it > 10 } // Result: false -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-26.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-26.kt deleted file mode 100644 index 8081a154033..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-26.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption26 - -import arrow.core.Some -import arrow.core.None -import arrow.core.Option - -fun main() { - Some(12).exists { it > 10 } // Result: 12 - Some(7).exists { it > 10 } // Result: null - - val none: Option = None - none.exists { it > 10 } // Result: null -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-27.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-27.kt deleted file mode 100644 index 5b54945e68a..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-27.kt +++ /dev/null @@ -1,3 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption27 - diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-28.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-28.kt deleted file mode 100644 index ba77029465d..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-28.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption28 - -import arrow.core.Option -import arrow.core.none -import arrow.core.Some -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Option = none() - val fallback: Option = error.recover { 5 } - fallback shouldBe Some(5) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-29.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-29.kt deleted file mode 100644 index 227c8ef5ada..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-29.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from Option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOption29 - -import arrow.core.Option -import arrow.core.none -import arrow.core.Some -import arrow.core.recover -import io.kotest.matchers.shouldBe - -fun test() { - val error: Option = none() - fun fallback(): Option = Some(5) - fun failure(): Option = none() - - error.recover { fallback().bind() } shouldBe Some(5) - error.recover { failure().bind() } shouldBe none() -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-01.kt deleted file mode 100644 index bd53693beba..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-01.kt +++ /dev/null @@ -1,16 +0,0 @@ -// This file was automatically generated from option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOptionComputations01 - -import arrow.core.computations.option - -suspend fun main() { - option { - ensure(true) - println("ensure(true) passes") - ensure(false) - 1 - } - .let(::println) -} -// println: "ensure(true) passes" -// res: None diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-02.kt deleted file mode 100644 index cc9f62c7d1b..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-option-computations-02.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from option.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleOptionComputations02 - -import arrow.core.computations.option -import arrow.core.computations.ensureNotNull - -suspend fun main() { - option { - val x: Int? = 1 - ensureNotNull(x) - println(x) - ensureNotNull(null) - } - .let(::println) -} -// println: "1" -// res: None diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-04.kt index 6fa5fe86c21..fe60fd2b1ce 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-04.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-04.kt @@ -43,8 +43,8 @@ val default4: Effect = val default5: Effect = foreign - .catch { ex: RuntimeException -> -1 } - .catch { ex: java.sql.SQLException -> -2 } + .catch { _: RuntimeException -> -1 } + .catch { _: java.sql.SQLException -> -2 } suspend fun java.sql.SQLException.isForeignKeyViolation(): Boolean = true diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-06.kt index 56f4bfaae96..13230c58403 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-06.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-06.kt @@ -5,7 +5,7 @@ import arrow.core.raise.effect import arrow.core.raise.fold import arrow.fx.coroutines.ExitCase import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.parTraverse +import arrow.fx.coroutines.parMap import io.kotest.assertions.fail import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,7 +22,7 @@ suspend fun main() { val error = "Error" val exits = (0..3).map { CompletableDeferred() } effect> { - (0..4).parTraverse { index -> + (0..4).parMap { index -> if (index == 4) raise(error) else awaitExitCase(exits[index]) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-08.kt index 7f52b2e77e1..73b82b9361f 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-08.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-08.kt @@ -18,7 +18,7 @@ suspend fun main() { effect { bracketCase( acquire = { File("build.gradle.kts").bufferedReader() }, - use = { reader: BufferedReader -> raise(error) }, + use = { _: BufferedReader -> raise(error) }, release = { reader, exitCase -> reader.close() exit.complete(exitCase) diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-03.kt index 26992486e9c..8ec23467cf1 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-03.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-03.kt @@ -9,7 +9,6 @@ import arrow.core.raise.either import arrow.core.raise.effect import arrow.core.raise.ior import arrow.core.raise.toEither -import arrow.typeclasses.Semigroup import io.kotest.matchers.shouldBe fun Raise.failure(): Int = raise("failed") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-05.kt index 83d6ebd0359..6449d5b0c86 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-05.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-05.kt @@ -13,7 +13,7 @@ fun test() { either { val x = one.bind() - val y = recover({ left.bind() }) { failure : String -> 1 } + val y = recover({ left.bind() }) { _ : String -> 1 } x + y } shouldBe Either.Right(2) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-06.kt index 73ef8a21ede..da5185f1b0e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-06.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-06.kt @@ -10,6 +10,6 @@ fun test() { recover({ raise("failed") }) { str -> str.length } shouldBe 6 either { - recover({ raise("failed") }) { str -> raise(-1) } + recover({ raise("failed") }) { _ -> raise(-1) } } shouldBe Either.Left(-1) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-09.kt index cbf67703845..3e678e2fb3b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-09.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-09.kt @@ -7,7 +7,7 @@ import arrow.core.raise.catch import io.kotest.matchers.shouldBe fun test() { - catch({ throw RuntimeException("BOOM") }) { t -> + catch({ throw RuntimeException("BOOM") }) { _ -> "fallback" } shouldBe "fallback" diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-10.kt index 94834cbbb6d..923e84e7c2b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-10.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-10.kt @@ -7,7 +7,7 @@ import arrow.core.raise.catch import io.kotest.matchers.shouldBe fun test() { - catch({ throw RuntimeException("BOOM") }) { t -> + catch({ throw RuntimeException("BOOM") }) { _ -> "fallback" } shouldBe "fallback" diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-result-computations-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-result-computations-01.kt deleted file mode 100644 index 66f22e58f7f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-result-computations-01.kt +++ /dev/null @@ -1,23 +0,0 @@ -// This file was automatically generated from result.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleResultComputations01 - -import arrow.core.* -import arrow.core.computations.result - -fun main() { - result { // We can safely use assertion based operation inside blocks - kotlin.require(false) { "Boom" } - } // Result.Failure(IllegalArgumentException("Boom")) - - result { - Result.failure(RuntimeException("Boom")) - .recover { 1 } - .bind() - } // Result.Success(1) - - result { - val x = Result.success(1).bind() - val y = Result.success(x + 1).bind() - x + y - } // Result.Success(3) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-01.kt deleted file mode 100644 index dcefb6f4865..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-01.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Semiring.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSemiring01 - -import arrow.typeclasses.Semiring - -fun main(args: Array) { - val result = - //sampleStart - Semiring.int().run { 1.combine(2) } - //sampleEnd - println(result) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-02.kt deleted file mode 100644 index b9bc9d80f41..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-02.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Semiring.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSemiring02 - -import arrow.typeclasses.Semiring - -fun main(args: Array) { - val result = - //sampleStart - Semiring.int().run { 2.combineMultiplicate(3) } - //sampleEnd - println(result) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-03.kt deleted file mode 100644 index 663866438fd..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-03.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Semiring.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSemiring03 - -import arrow.typeclasses.Semiring - -fun main(args: Array) { - val result = - //sampleStart - Semiring.int().run { - 1 + 2 - } - //sampleEnd - println(result) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-04.kt deleted file mode 100644 index c96dc96f2a6..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-semiring-04.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Semiring.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSemiring04 - -import arrow.typeclasses.Semiring - -fun main(args: Array) { - val result = - //sampleStart - Semiring.int().run { - 2 * 3 - } - //sampleEnd - println(result) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-03.kt index 22d99f25487..7edba50e1e9 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-03.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-03.kt @@ -1,14 +1,11 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence03 -import arrow.core.ifThen +import arrow.core.* +import io.kotest.matchers.shouldBe -fun main(args: Array) { - //sampleStart - val result = - sequenceOf(1,2,3).ifThen(sequenceOf("empty")) { i -> - sequenceOf("$i, ${i + 1}") - } - //sampleEnd - println(result.toList()) +fun test() { + val tags = generateSequence { "#" }.take(5) + val numbers = generateSequence(0) { it + 1 }.take(3) + tags.interleave(numbers).toList() shouldBe listOf("#", 0, "#", 1, "#", 2, "#", "#") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-04.kt index 16dcbebfe71..f9b1b426629 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-04.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-04.kt @@ -1,11 +1,14 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence04 -import arrow.core.* -import io.kotest.matchers.shouldBe +import arrow.core.leftPadZip -fun test() { - val tags = generateSequence { "#" }.take(5) - val numbers = generateSequence(0) { it + 1 }.take(3) - tags.interleave(numbers).toList() shouldBe listOf("#", 0, "#", 1, "#", 2, "#", "#") +val left = sequenceOf(1, 2).leftPadZip(sequenceOf(3)) { l, r -> l?.plus(r) ?: r } // Result: [4] +val right = sequenceOf(1).leftPadZip(sequenceOf(3, 4)) { l, r -> l?.plus(r) ?: r } // Result: [4, 4] +val both = sequenceOf(1, 2).leftPadZip(sequenceOf(3, 4)) { l, r -> l?.plus(r) ?: r } // Result: [4, 6] + +fun main() { + println("left = $left") + println("right = $right") + println("both = $both") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-05.kt index 025d052dd5a..f14ccc16a99 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-05.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-05.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleSequence05 import arrow.core.leftPadZip -val left = sequenceOf(1, 2).leftPadZip(sequenceOf(3)) { l, r -> l?.plus(r) ?: r } // Result: [4] -val right = sequenceOf(1).leftPadZip(sequenceOf(3, 4)) { l, r -> l?.plus(r) ?: r } // Result: [4, 4] -val both = sequenceOf(1, 2).leftPadZip(sequenceOf(3, 4)) { l, r -> l?.plus(r) ?: r } // Result: [4, 6] +val padRight = sequenceOf(1, 2).leftPadZip(sequenceOf("a")) // Result: [Pair(1, "a")] +val padLeft = sequenceOf(1).leftPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] +val noPadding = sequenceOf(1, 2).leftPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] fun main() { - println("left = $left") - println("right = $right") - println("both = $both") + println("padRight = $padRight") + println("padLeft = $padLeft") + println("noPadding = $noPadding") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-06.kt index bcff445249b..9ae4ac63b87 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-06.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-06.kt @@ -1,11 +1,11 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence06 -import arrow.core.leftPadZip +import arrow.core.padZip -val padRight = sequenceOf(1, 2).leftPadZip(sequenceOf("a")) // Result: [Pair(1, "a")] -val padLeft = sequenceOf(1).leftPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] -val noPadding = sequenceOf(1, 2).leftPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] +val padRight = sequenceOf(1, 2).padZip(sequenceOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] +val padLeft = sequenceOf(1).padZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] +val noPadding = sequenceOf(1, 2).padZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] fun main() { println("padRight = $padRight") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-07.kt index d4f7e45722e..e600cdd2254 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-07.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-07.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleSequence07 import arrow.core.padZip -val padRight = sequenceOf(1, 2).padZip(sequenceOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] -val padLeft = sequenceOf(1).padZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] -val noPadding = sequenceOf(1, 2).padZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] +val padZipRight = sequenceOf(1, 2).padZip(sequenceOf(3)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 2] +val padZipLeft = sequenceOf(1).padZip(sequenceOf(3, 4)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 4] +val noPadding = sequenceOf(1, 2).padZip(sequenceOf(3, 4)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 6] fun main() { - println("padRight = $padRight") - println("padLeft = $padLeft") + println("padZipRight = $padZipRight") + println("padZipLeft = $padZipLeft") println("noPadding = $noPadding") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-08.kt index 1b85b72cfbc..d3c757b1c0c 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-08.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-08.kt @@ -1,14 +1,14 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence08 -import arrow.core.padZip +import arrow.core.rightPadZip -val padZipRight = sequenceOf(1, 2).padZip(sequenceOf(3)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 2] -val padZipLeft = sequenceOf(1).padZip(sequenceOf(3, 4)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 4] -val noPadding = sequenceOf(1, 2).padZip(sequenceOf(3, 4)) { l, r -> (l?:0) + (r?:0) } // Result: [4, 6] +val left = sequenceOf(1, 2).rightPadZip(sequenceOf(3)) { l, r -> l + (r?:0) } // Result: [4, 2] +val right = sequenceOf(1).rightPadZip(sequenceOf(3, 4)) { l, r -> l + (r?:0) } // Result: [4] +val both = sequenceOf(1, 2).rightPadZip(sequenceOf(3, 4)) { l, r -> l + (r?:0) } // Result: [4, 6] fun main() { - println("padZipRight = $padZipRight") - println("padZipLeft = $padZipLeft") - println("noPadding = $noPadding") + println("left = $left") + println("right = $right") + println("both = $both") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-09.kt index ae75fa6cd22..1e2c93bd8b7 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-09.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-09.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleSequence09 import arrow.core.rightPadZip -val left = sequenceOf(1, 2).rightPadZip(sequenceOf(3)) { l, r -> l + (r?:0) } // Result: [4, 2] -val right = sequenceOf(1).rightPadZip(sequenceOf(3, 4)) { l, r -> l + (r?:0) } // Result: [4] -val both = sequenceOf(1, 2).rightPadZip(sequenceOf(3, 4)) { l, r -> l + (r?:0) } // Result: [4, 6] +val padRight = sequenceOf(1, 2).rightPadZip(sequenceOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] +val padLeft = sequenceOf(1).rightPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a")] +val noPadding = sequenceOf(1, 2).rightPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] fun main() { - println("left = $left") - println("right = $right") - println("both = $both") + println("padRight = $padRight") + println("padLeft = $padLeft") + println("noPadding = $noPadding") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-10.kt index ecc6a38dab9..c4afea225e2 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-10.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-10.kt @@ -1,14 +1,13 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence10 -import arrow.core.rightPadZip +import arrow.core.split +import io.kotest.matchers.shouldBe -val padRight = sequenceOf(1, 2).rightPadZip(sequenceOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] -val padLeft = sequenceOf(1).rightPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a")] -val noPadding = sequenceOf(1, 2).rightPadZip(sequenceOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] - -fun main() { - println("padRight = $padRight") - println("padLeft = $padLeft") - println("noPadding = $noPadding") +fun test() { + sequenceOf("A", "B", "C").split()?.let { (tail, head) -> + head shouldBe "A" + tail.toList() shouldBe listOf("B", "C") + } + emptySequence().split() shouldBe null } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-11.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-11.kt index dac1899f073..c8a06580d4b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-11.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-11.kt @@ -1,13 +1,13 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence11 -import arrow.core.split -import io.kotest.matchers.shouldBe +import arrow.core.bothIor +import arrow.core.leftIor +import arrow.core.unalign -fun test() { - sequenceOf("A", "B", "C").split()?.let { (tail, head) -> - head shouldBe "A" - tail.toList() shouldBe listOf("B", "C") - } - emptySequence().split() shouldBe null +fun main() { + //sampleStart + val result = sequenceOf(("A" to 1).bothIor(), ("B" to 2).bothIor(), "C".leftIor()).unalign() + //sampleEnd + println("(${result.first}, ${result.second})") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-12.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-12.kt index d23efa81b24..768b3e87ec1 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-12.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-12.kt @@ -1,13 +1,12 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence12 -import arrow.core.bothIor import arrow.core.leftIor import arrow.core.unalign -fun main(args: Array) { +fun main() { //sampleStart - val result = sequenceOf(("A" to 1).bothIor(), ("B" to 2).bothIor(), "C".leftIor()).unalign() + val result = sequenceOf(1, 2, 3).unalign { it.leftIor() } //sampleEnd - println("(${result.first}, ${result.second})") + println("(${result.first.toList()}, ${result.second.toList()})") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-13.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-13.kt index 5f18e813bc1..45cc0c7710b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-13.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-13.kt @@ -1,12 +1,11 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence13 -import arrow.core.leftIor -import arrow.core.unalign +import arrow.core.unweave -fun main(args: Array) { +fun main() { //sampleStart - val result = sequenceOf(1, 2, 3).unalign { it.leftIor() } + val result = sequenceOf(1,2,3).unweave { i -> sequenceOf("$i, ${i + 1}") } //sampleEnd - println("(${result.first.toList()}, ${result.second.toList()})") + println(result.toList()) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-14.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-14.kt index 511d154024a..835b67cdb14 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-14.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-14.kt @@ -1,11 +1,11 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence14 -import arrow.core.unweave +import arrow.core.unzip -fun main(args: Array) { +fun main() { //sampleStart - val result = sequenceOf(1,2,3).unweave { i -> sequenceOf("$i, ${i + 1}") } + val result = sequenceOf("A" to 1, "B" to 2).unzip() //sampleEnd - println(result.toList()) + println("(${result.first}, ${result.second})") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-15.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-15.kt index f565abbb968..e45890c3984 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-15.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-15.kt @@ -3,9 +3,14 @@ package arrow.core.examples.exampleSequence15 import arrow.core.unzip -fun main(args: Array) { +fun main() { //sampleStart - val result = sequenceOf("A" to 1, "B" to 2).unzip() + val result = + sequenceOf("A:1", "B:2", "C:3").unzip { e -> + e.split(":").let { + it.first() to it.last() + } + } //sampleEnd println("(${result.first}, ${result.second})") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-16.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-16.kt index 41dba1d23d2..bef9a73013e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-16.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-16.kt @@ -1,16 +1,15 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.exampleSequence16 -import arrow.core.unzip +import arrow.core.None +import arrow.core.Some +import arrow.core.filterOption +import io.kotest.matchers.shouldBe -fun main(args: Array) { - //sampleStart - val result = - sequenceOf("A:1", "B:2", "C:3").unzip { e -> - e.split(":").let { - it.first() to it.last() - } - } - //sampleEnd - println("(${result.first}, ${result.second})") +fun test() { +generateSequence(0) { it + 1 } + .map { if (it % 2 == 0) Some(it) else None } + .filterOption() + .take(5) + .toList() shouldBe listOf(0, 2, 4, 6, 8) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-17.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-17.kt deleted file mode 100644 index f08eec01d58..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-17.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Sequence.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSequence17 - -import arrow.core.widen - -fun main(args: Array) { - val original: Sequence = sequenceOf("Hello World") - val result: Sequence = original.widen() -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-18.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-18.kt deleted file mode 100644 index 80df0bf6c81..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-sequence-18.kt +++ /dev/null @@ -1,15 +0,0 @@ -// This file was automatically generated from Sequence.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleSequence18 - -import arrow.core.None -import arrow.core.Some -import arrow.core.filterOption -import io.kotest.matchers.shouldBe - -fun test() { -generateSequence(0) { it + 1 } - .map { if (it % 2 == 0) Some(it) else None } - .filterOption() - .take(5) - .toList() shouldBe listOf(0, 2, 4, 6, 8) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-01.kt deleted file mode 100644 index fc02b28723c..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-01.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated01 - -import arrow.core.* - -fun main(args: Array) { - //sampleStart - val f = Validated.lift(String::toUpperCase, Int::inc) - val res1 = f("test".invalid()) - val res2 = f(1.valid()) - //sampleEnd - println("res1: $res1") - println("res2: $res2") -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-02.kt deleted file mode 100644 index 68849d20db2..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-02.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated02 - -import arrow.core.* - -fun main(args: Array) { - val result = - //sampleStart - "Hello World".valid().void() - //sampleEnd - println(result) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-03.kt deleted file mode 100644 index e5b5f1336cf..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-03.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated03 - -import arrow.core.Validated - -fun main() { - Validated.Valid(12).tapInvalid { println("flower") } // Result: Valid(12) - Validated.Invalid(12).tapInvalid { println("flower") } // Result: prints "flower" and returns: Invalid(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-04.kt deleted file mode 100644 index c13fa930955..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-04.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated04 - -import arrow.core.Validated - -fun main() { - Validated.Valid(12).tap { println("flower") } // Result: prints "flower" and returns: Valid(12) - Validated.Invalid(12).tap { println("flower") } // Result: Invalid(12) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-05.kt deleted file mode 100644 index af73083b797..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-05.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated05 - -import arrow.core.* - -fun main(args: Array) { - //sampleStart - val string: Validated = "Hello".valid() - val chars: Validated = - string.widen() - //sampleEnd - println(chars) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-06.kt deleted file mode 100644 index 4cf01a61751..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-validated-06.kt +++ /dev/null @@ -1,11 +0,0 @@ -// This file was automatically generated from Validated.kt by Knit tool. Do not edit. -package arrow.core.examples.exampleValidated06 - -import arrow.core.Validated -import arrow.core.andThen - -fun main() { - Validated.Valid(5).andThen { Validated.Valid(10) } // Result: Valid(10) - Validated.Valid(5).andThen { Validated.Invalid(10) } // Result: Invalid(10) - Validated.Invalid(5).andThen { Validated.Valid(10) } // Result: Invalid(5) -} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/EitherKnitTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/EitherKnitTest.kt index 6e996f6d808..e8d56994cfe 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/EitherKnitTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/EitherKnitTest.kt @@ -1,69 +1,68 @@ // This file was automatically generated from Either.kt by Knit tool. Do not edit. package arrow.core.examples.test -import io.kotest.core.spec.style.StringSpec +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class EitherKnitTest : StringSpec({ - "ExampleEither21" { +class EitherKnitTest { + @Test fun exampleEither21() = runTest { arrow.core.examples.exampleEither21.test() } - "ExampleEither22" { + @Test fun exampleEither22() = runTest { arrow.core.examples.exampleEither22.test() } - "ExampleEither23" { + @Test fun exampleEither23() = runTest { arrow.core.examples.exampleEither23.test() } - "ExampleEither25" { + @Test fun exampleEither25() = runTest { arrow.core.examples.exampleEither25.test() } - "ExampleEither26" { + @Test fun exampleEither26() = runTest { arrow.core.examples.exampleEither26.test() } - "ExampleEither27" { + @Test fun exampleEither27() = runTest { arrow.core.examples.exampleEither27.test() } - "ExampleEither28" { + @Test fun exampleEither28() = runTest { arrow.core.examples.exampleEither28.test() } - "ExampleEither30" { + @Test fun exampleEither29() = runTest { + arrow.core.examples.exampleEither29.test() + } + + @Test fun exampleEither30() = runTest { arrow.core.examples.exampleEither30.test() } - "ExampleEither31" { + @Test fun exampleEither31() = runTest { arrow.core.examples.exampleEither31.test() } - "ExampleEither32" { + @Test fun exampleEither32() = runTest { arrow.core.examples.exampleEither32.test() } - "ExampleEither36" { - arrow.core.examples.exampleEither36.test() - } - - "ExampleEither41" { - arrow.core.examples.exampleEither41.test() + @Test fun exampleEither33() = runTest { + arrow.core.examples.exampleEither33.test() } - "ExampleEither45" { - arrow.core.examples.exampleEither45.test() + @Test fun exampleEither34() = runTest { + arrow.core.examples.exampleEither34.test() } - "ExampleEither46" { - arrow.core.examples.exampleEither46.test() + @Test fun exampleEither35() = runTest { + arrow.core.examples.exampleEither35.test() } - "ExampleEither47" { - arrow.core.examples.exampleEither47.test() + @Test fun exampleEither36() = runTest { + arrow.core.examples.exampleEither36.test() } -}) { - override fun timeout(): Long = 1000 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/IterableKnitTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/IterableKnitTest.kt index 50bec236a9e..b4cac12b2ea 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/IterableKnitTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/IterableKnitTest.kt @@ -1,81 +1,80 @@ // This file was automatically generated from Iterable.kt by Knit tool. Do not edit. package arrow.core.examples.test -import io.kotest.core.spec.style.StringSpec +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class IterableKnitTest : StringSpec({ - "ExampleIterable01" { +class IterableKnitTest { + @Test fun exampleIterable01() = runTest { arrow.core.examples.exampleIterable01.test() } - "ExampleIterable02" { + @Test fun exampleIterable02() = runTest { arrow.core.examples.exampleIterable02.test() } - "ExampleIterable03" { + @Test fun exampleIterable03() = runTest { arrow.core.examples.exampleIterable03.test() } - "ExampleIterable04" { + @Test fun exampleIterable04() = runTest { arrow.core.examples.exampleIterable04.test() } - "ExampleIterable05" { + @Test fun exampleIterable05() = runTest { arrow.core.examples.exampleIterable05.test() } - "ExampleIterable06" { + @Test fun exampleIterable06() = runTest { arrow.core.examples.exampleIterable06.test() } - "ExampleIterable07" { + @Test fun exampleIterable07() = runTest { arrow.core.examples.exampleIterable07.test() } - "ExampleIterable08" { + @Test fun exampleIterable08() = runTest { arrow.core.examples.exampleIterable08.test() } - "ExampleIterable09" { + @Test fun exampleIterable09() = runTest { arrow.core.examples.exampleIterable09.test() } - "ExampleIterable10" { + @Test fun exampleIterable10() = runTest { arrow.core.examples.exampleIterable10.test() } - "ExampleIterable11" { + @Test fun exampleIterable11() = runTest { arrow.core.examples.exampleIterable11.test() } - "ExampleIterable12" { + @Test fun exampleIterable12() = runTest { arrow.core.examples.exampleIterable12.test() } - "ExampleIterable13" { + @Test fun exampleIterable13() = runTest { arrow.core.examples.exampleIterable13.test() } - "ExampleIterable14" { + @Test fun exampleIterable14() = runTest { arrow.core.examples.exampleIterable14.test() } - "ExampleIterable15" { + @Test fun exampleIterable15() = runTest { arrow.core.examples.exampleIterable15.test() } - "ExampleIterable16" { + @Test fun exampleIterable16() = runTest { arrow.core.examples.exampleIterable16.test() } - "ExampleIterable19" { - arrow.core.examples.exampleIterable19.test() + @Test fun exampleIterable18() = runTest { + arrow.core.examples.exampleIterable18.test() } - "ExampleIterable20" { - arrow.core.examples.exampleIterable20.test() + @Test fun exampleIterable19() = runTest { + arrow.core.examples.exampleIterable19.test() } -}) { - override fun timeout(): Long = 1000 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/OptionKnitTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/OptionKnitTest.kt index 1073ac2bc5d..7c575f41326 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/OptionKnitTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/OptionKnitTest.kt @@ -1,17 +1,16 @@ // This file was automatically generated from Option.kt by Knit tool. Do not edit. package arrow.core.examples.test -import io.kotest.core.spec.style.StringSpec +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class OptionKnitTest : StringSpec({ - "ExampleOption28" { - arrow.core.examples.exampleOption28.test() +class OptionKnitTest { + @Test fun exampleOption20() = runTest { + arrow.core.examples.exampleOption20.test() } - "ExampleOption29" { - arrow.core.examples.exampleOption29.test() + @Test fun exampleOption21() = runTest { + arrow.core.examples.exampleOption21.test() } -}) { - override fun timeout(): Long = 1000 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/RaiseKnitTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/RaiseKnitTest.kt index 97e2e8158e6..f1710a181f9 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/RaiseKnitTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/RaiseKnitTest.kt @@ -1,53 +1,52 @@ // This file was automatically generated from Raise.kt by Knit tool. Do not edit. package arrow.core.examples.test -import io.kotest.core.spec.style.StringSpec +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class RaiseKnitTest : StringSpec({ - "ExampleRaiseDsl02" { +class RaiseKnitTest { + @Test fun exampleRaiseDsl02() = runTest { arrow.core.examples.exampleRaiseDsl02.test() } - "ExampleRaiseDsl03" { + @Test fun exampleRaiseDsl03() = runTest { arrow.core.examples.exampleRaiseDsl03.test() } - "ExampleRaiseDsl04" { + @Test fun exampleRaiseDsl04() = runTest { arrow.core.examples.exampleRaiseDsl04.test() } - "ExampleRaiseDsl05" { + @Test fun exampleRaiseDsl05() = runTest { arrow.core.examples.exampleRaiseDsl05.test() } - "ExampleRaiseDsl06" { + @Test fun exampleRaiseDsl06() = runTest { arrow.core.examples.exampleRaiseDsl06.test() } - "ExampleRaiseDsl07" { + @Test fun exampleRaiseDsl07() = runTest { arrow.core.examples.exampleRaiseDsl07.test() } - "ExampleRaiseDsl08" { + @Test fun exampleRaiseDsl08() = runTest { arrow.core.examples.exampleRaiseDsl08.test() } - "ExampleRaiseDsl09" { + @Test fun exampleRaiseDsl09() = runTest { arrow.core.examples.exampleRaiseDsl09.test() } - "ExampleRaiseDsl10" { + @Test fun exampleRaiseDsl10() = runTest { arrow.core.examples.exampleRaiseDsl10.test() } - "ExampleRaiseDsl11" { + @Test fun exampleRaiseDsl11() = runTest { arrow.core.examples.exampleRaiseDsl11.test() } - "ExampleRaiseDsl12" { + @Test fun exampleRaiseDsl12() = runTest { arrow.core.examples.exampleRaiseDsl12.test() } -}) { - override fun timeout(): Long = 1000 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/SequenceKnitTest.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/SequenceKnitTest.kt index 2ad713d464f..58b5ceedf85 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/SequenceKnitTest.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/SequenceKnitTest.kt @@ -1,29 +1,28 @@ // This file was automatically generated from Sequence.kt by Knit tool. Do not edit. package arrow.core.examples.test -import io.kotest.core.spec.style.StringSpec +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class SequenceKnitTest : StringSpec({ - "ExampleSequence01" { +class SequenceKnitTest { + @Test fun exampleSequence01() = runTest { arrow.core.examples.exampleSequence01.test() } - "ExampleSequence02" { + @Test fun exampleSequence02() = runTest { arrow.core.examples.exampleSequence02.test() } - "ExampleSequence04" { - arrow.core.examples.exampleSequence04.test() + @Test fun exampleSequence03() = runTest { + arrow.core.examples.exampleSequence03.test() } - "ExampleSequence11" { - arrow.core.examples.exampleSequence11.test() + @Test fun exampleSequence10() = runTest { + arrow.core.examples.exampleSequence10.test() } - "ExampleSequence18" { - arrow.core.examples.exampleSequence18.test() + @Test fun exampleSequence16() = runTest { + arrow.core.examples.exampleSequence16.test() } -}) { - override fun timeout(): Long = 1000 } diff --git a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/NonFatal.kt b/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/NonFatal.kt index 6f6aead04a3..befa68dc021 100644 --- a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/NonFatal.kt +++ b/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/NonFatal.kt @@ -1,10 +1,9 @@ package arrow.core -import arrow.continuations.generic.ControlThrowable import kotlin.coroutines.cancellation.CancellationException public actual fun NonFatal(t: Throwable): Boolean = when (t) { - is ControlThrowable, is CancellationException -> false + is CancellationException -> false else -> true } diff --git a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/AtomicRef.kt b/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/AtomicRef.kt deleted file mode 100644 index d839476478d..00000000000 --- a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/AtomicRef.kt +++ /dev/null @@ -1,30 +0,0 @@ -package arrow.core.continuations - -public actual class AtomicRef actual constructor(initialValue: V) { - private var internalValue: V = initialValue - - /** - * Compare current value with expected and set to new if they're the same. Note, 'compare' is checking - * the actual object id, not 'equals'. - */ - public actual fun compareAndSet(expected: V, new: V): Boolean { - return if (expected === internalValue) { - internalValue = new - true - } else { - false - } - } - - public actual fun getAndSet(value: V): V { - val oldValue = internalValue - internalValue = value - return oldValue - } - - public actual fun get(): V = internalValue - - public actual fun set(value: V) { - internalValue = value - } -} diff --git a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt b/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt deleted file mode 100644 index cb795a5a30e..00000000000 --- a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/continuations/CancellationExceptionNoTrace.kt +++ /dev/null @@ -1,5 +0,0 @@ -package arrow.core.continuations - -import kotlin.coroutines.cancellation.CancellationException - -public actual open class CancellationExceptionNoTrace : CancellationException("Shifted Continuation") diff --git a/arrow-libs/core/arrow-eval/api/arrow-eval.api b/arrow-libs/core/arrow-eval/api/arrow-eval.api index 7015bbad624..588bf738e18 100644 --- a/arrow-libs/core/arrow-eval/api/arrow-eval.api +++ b/arrow-libs/core/arrow-eval/api/arrow-eval.api @@ -90,7 +90,6 @@ public final class arrow/eval/Eval$Now$Companion { public final class arrow/eval/EvalKt { public static final fun iterateRight (Ljava/util/Iterator;Larrow/eval/Eval;Lkotlin/jvm/functions/Function2;)Larrow/eval/Eval; public static final fun replicate (Larrow/eval/Eval;I)Larrow/eval/Eval; - public static final fun replicate (Larrow/eval/Eval;ILarrow/typeclasses/Monoid;)Larrow/eval/Eval; public static final fun replicate (Larrow/eval/Eval;ILkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;)Larrow/eval/Eval; public static final fun zip (Larrow/eval/Eval;Larrow/eval/Eval;)Larrow/eval/Eval; public static final fun zip (Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Larrow/eval/Eval;Lkotlin/jvm/functions/Function10;)Larrow/eval/Eval; diff --git a/arrow-libs/core/arrow-eval/src/commonMain/kotlin/arrow/eval/Eval.kt b/arrow-libs/core/arrow-eval/src/commonMain/kotlin/arrow/eval/Eval.kt index c3387e6c0a1..d180084fb51 100644 --- a/arrow-libs/core/arrow-eval/src/commonMain/kotlin/arrow/eval/Eval.kt +++ b/arrow-libs/core/arrow-eval/src/commonMain/kotlin/arrow/eval/Eval.kt @@ -4,8 +4,6 @@ import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.getOrElse -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation import kotlin.js.JsName import kotlin.jvm.JvmStatic @@ -573,7 +571,3 @@ public fun Eval.replicate(n: Int, initial: () -> B, combine: (A, B) -> public fun Eval.replicate(n: Int): Eval> = replicate(n, { emptyList() }) { x, xs -> listOf(x) + xs } - -@Deprecated(MonoidDeprecation, ReplaceWith("replicate(n, MA::empty) { x, xs -> MA.run { x + xs } }", "arrow.eval.replicate")) -public fun Eval.replicate(n: Int, MA: Monoid): Eval = - replicate(n, MA::empty) { x, xs -> MA.run { x + xs } } diff --git a/arrow-libs/core/arrow-functions/api/arrow-functions.api b/arrow-libs/core/arrow-functions/api/arrow-functions.api new file mode 100644 index 00000000000..8591244216c --- /dev/null +++ b/arrow-libs/core/arrow-functions/api/arrow-functions.api @@ -0,0 +1,612 @@ +public final class arrow/core/Composition { + public static final fun andThen (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function0; + public static final fun andThen (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; + public static final fun andThen (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; + public static final fun compose (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; +} + +public final class arrow/core/Currying { + public static final fun curried (Lkotlin/jvm/functions/Function10;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function11;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function12;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function13;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function14;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function15;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function16;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function17;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function18;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function19;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function20;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function21;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function22;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function6;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function7;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function8;)Lkotlin/jvm/functions/Function1; + public static final fun curried (Lkotlin/jvm/functions/Function9;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function10;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function11;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function12;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function13;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function14;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function15;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function16;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function17;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function18;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function19;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function20;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function21;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function22;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function6;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function7;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function8;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/Function9;)Lkotlin/jvm/functions/Function1; + public static final fun curriedEffect (Lkotlin/jvm/functions/FunctionN;)Lkotlin/jvm/functions/Function1; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function10; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function11; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function12; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function13; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function14; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function15; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function16; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function17; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function18; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function19; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function20; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function21; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function22; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function4; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function5; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function6; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function7; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function8; + public static final fun uncurried (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function9; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function10; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function11; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function12; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function13; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function14; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function15; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function16; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function17; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function18; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function19; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function20; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function21; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function22; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function3; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function4; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function5; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function6; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function7; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function8; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function9; + public static final fun uncurriedEffect (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/FunctionN; +} + +public final class arrow/core/Memoization { + public static final fun memoize (Lkotlin/jvm/functions/Function0;)Lkotlin/jvm/functions/Function0; + public static final fun memoize (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; + public static final fun memoize (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; + public static final fun memoize (Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function3; + public static final fun memoize (Lkotlin/jvm/functions/Function4;)Lkotlin/jvm/functions/Function4; + public static final fun memoize (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function5; +} + +public final class arrow/core/Partials { + public static final fun partially1 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially1 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially1 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially1 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially1 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially1 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially1 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially1 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially1 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially1 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially1 (Lkotlin/jvm/functions/Function1;Ljava/lang/Object;)Lkotlin/jvm/functions/Function0; + public static final fun partially1 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially1 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially1 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially1 (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; + public static final fun partially1 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun partially1 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially1 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially1 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially1 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially1 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially1 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially10 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially10 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially10 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially10 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially10 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially10 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially10 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially10 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially10 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially10 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially10 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially10 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially10 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially10Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially10Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially11 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially11 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially11 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially11 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially11 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially11 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially11 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially11 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially11 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially11 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially11 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially11 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially11Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially11Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially12 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially12 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially12 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially12 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially12 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially12 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially12 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially12 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially12 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially12 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially12 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially12Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially12Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially13 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially13 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially13 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially13 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially13 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially13 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially13 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially13 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially13 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially13 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially13Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially13Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially14 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially14 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially14 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially14 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially14 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially14 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially14 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially14 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially14 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially14Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially14Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially15 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially15 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially15 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially15 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially15 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially15 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially15 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially15 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially15Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially15Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially16 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially16 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially16 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially16 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially16 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially16 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially16 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially16Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially16Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially17 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially17 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially17 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially17 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially17 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially17 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially17Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially17Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially17Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially17Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially17Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially17Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially18 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially18 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially18 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially18 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially18 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially18Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially18Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially18Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially18Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially18Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially19 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially19 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially19 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially19 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially19Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially19Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially19Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially19Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially1Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially1Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially2 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially2 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially2 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially2 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially2 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially2 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially2 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially2 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially2 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially2 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially2 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially2 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially2 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially2 (Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Lkotlin/jvm/functions/Function1; + public static final fun partially2 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun partially2 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially2 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially2 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially2 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially2 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially2 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially20 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially20 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially20 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially20Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially20Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially20Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially21 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially21 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially21Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially21Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially22 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially22Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially2Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially2Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially3 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially3 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially3 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially3 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially3 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially3 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially3 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially3 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially3 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially3 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially3 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially3 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially3 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially3 (Lkotlin/jvm/functions/Function3;Ljava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun partially3 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially3 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially3 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially3 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially3 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially3 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially3Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially3Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially4 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially4 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially4 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially4 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially4 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially4 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially4 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially4 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially4 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially4 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially4 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially4 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially4 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially4 (Lkotlin/jvm/functions/Function4;Ljava/lang/Object;)Lkotlin/jvm/functions/Function3; + public static final fun partially4 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially4 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially4 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially4 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially4 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially4Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially4Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially5 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially5 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially5 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially5 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially5 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially5 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially5 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially5 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially5 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially5 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially5 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially5 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially5 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially5 (Lkotlin/jvm/functions/Function5;Ljava/lang/Object;)Lkotlin/jvm/functions/Function4; + public static final fun partially5 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially5 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially5 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially5 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially5Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially5Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially6 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially6 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially6 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially6 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially6 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially6 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially6 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially6 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially6 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially6 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially6 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially6 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially6 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially6 (Lkotlin/jvm/functions/Function6;Ljava/lang/Object;)Lkotlin/jvm/functions/Function5; + public static final fun partially6 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially6 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially6 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially6Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially6Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially7 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially7 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially7 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially7 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially7 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially7 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially7 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially7 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially7 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially7 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially7 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially7 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially7 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially7 (Lkotlin/jvm/functions/Function7;Ljava/lang/Object;)Lkotlin/jvm/functions/Function6; + public static final fun partially7 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially7 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially7Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially7Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially8 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially8 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially8 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially8 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially8 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially8 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially8 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially8 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially8 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially8 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially8 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially8 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially8 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially8 (Lkotlin/jvm/functions/Function8;Ljava/lang/Object;)Lkotlin/jvm/functions/Function7; + public static final fun partially8 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially8Effect (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially8Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; + public static final fun partially9 (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially9 (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially9 (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially9 (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially9 (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially9 (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially9 (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially9 (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially9 (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially9 (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially9 (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially9 (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially9 (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially9 (Lkotlin/jvm/functions/Function9;Ljava/lang/Object;)Lkotlin/jvm/functions/Function8; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function10;Ljava/lang/Object;)Lkotlin/jvm/functions/Function9; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function11;Ljava/lang/Object;)Lkotlin/jvm/functions/Function10; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function12;Ljava/lang/Object;)Lkotlin/jvm/functions/Function11; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function13;Ljava/lang/Object;)Lkotlin/jvm/functions/Function12; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function14;Ljava/lang/Object;)Lkotlin/jvm/functions/Function13; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function15;Ljava/lang/Object;)Lkotlin/jvm/functions/Function14; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function16;Ljava/lang/Object;)Lkotlin/jvm/functions/Function15; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function17;Ljava/lang/Object;)Lkotlin/jvm/functions/Function16; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function18;Ljava/lang/Object;)Lkotlin/jvm/functions/Function17; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function19;Ljava/lang/Object;)Lkotlin/jvm/functions/Function18; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function20;Ljava/lang/Object;)Lkotlin/jvm/functions/Function19; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function21;Ljava/lang/Object;)Lkotlin/jvm/functions/Function20; + public static final fun partially9Effect (Lkotlin/jvm/functions/Function22;Ljava/lang/Object;)Lkotlin/jvm/functions/Function21; + public static final fun partially9Effect (Lkotlin/jvm/functions/FunctionN;Ljava/lang/Object;)Lkotlin/jvm/functions/Function22; +} + diff --git a/arrow-libs/core/arrow-continuations/build.gradle.kts b/arrow-libs/core/arrow-functions/build.gradle.kts similarity index 72% rename from arrow-libs/core/arrow-continuations/build.gradle.kts rename to arrow-libs/core/arrow-functions/build.gradle.kts index 56725c06ba7..748b9680ca8 100644 --- a/arrow-libs/core/arrow-continuations/build.gradle.kts +++ b/arrow-libs/core/arrow-functions/build.gradle.kts @@ -5,7 +5,6 @@ plugins { alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.spotless) } @@ -22,22 +21,20 @@ kotlin { sourceSets { commonMain { dependencies { - implementation(libs.kotlin.stdlib) + api(projects.arrowAtomic) + api(projects.arrowAnnotations) + api(libs.kotlin.stdlib) } } commonTest { dependencies { - implementation(projects.arrowCore) - implementation(libs.kotest.frameworkEngine) + implementation(projects.arrowFxCoroutines) + implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } } - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) - } - } } jvm { @@ -48,3 +45,7 @@ kotlin { } } } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/core/arrow-continuations/gradle.properties b/arrow-libs/core/arrow-functions/gradle.properties similarity index 73% rename from arrow-libs/core/arrow-continuations/gradle.properties rename to arrow-libs/core/arrow-functions/gradle.properties index b657b4ed748..19c64baf9cb 100644 --- a/arrow-libs/core/arrow-continuations/gradle.properties +++ b/arrow-libs/core/arrow-functions/gradle.properties @@ -1,4 +1,4 @@ # Maven publishing configuration -pom.name=Arrow Continuations +pom.name=Arrow Functions # Build configuration kapt.incremental.apt=false diff --git a/arrow-libs/core/arrow-functions/knit.properties b/arrow-libs/core/arrow-functions/knit.properties new file mode 100644 index 00000000000..c3328691738 --- /dev/null +++ b/arrow-libs/core/arrow-functions/knit.properties @@ -0,0 +1,6 @@ +knit.package=arrow.core.examples +knit.dir=src/jvmTest/kotlin/examples/ + +test.package=arrow.core.examples.test +test.dir=src/jvmTest/kotlin/examples/test/ +test.template=knit.test.template \ No newline at end of file diff --git a/arrow-libs/core/arrow-functions/knit.test.template b/arrow-libs/core/arrow-functions/knit.test.template new file mode 100644 index 00000000000..7b3f20935a9 --- /dev/null +++ b/arrow-libs/core/arrow-functions/knit.test.template @@ -0,0 +1,15 @@ +// This file was automatically generated from ${file.name} by Knit tool. Do not edit. +package ${test.package} + +import io.kotest.core.spec.style.StringSpec + +class ${test.name} : StringSpec({ +<#list cases as case> + "${case.name}" { + ${case.knit.package}.${case.knit.name}.test() + } + + +}) { + override fun timeout(): Long = 1000 +} \ No newline at end of file diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/composition.kt b/arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/composition.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/composition.kt rename to arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/composition.kt diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/currying.kt b/arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/currying.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/currying.kt rename to arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/currying.kt diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/memoization.kt b/arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/memoization.kt similarity index 95% rename from arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/memoization.kt rename to arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/memoization.kt index c116096754a..3f56517e2ba 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/memoization.kt +++ b/arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/memoization.kt @@ -2,8 +2,9 @@ package arrow.core -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.loop +import arrow.atomic.Atomic +import arrow.atomic.loop +import arrow.atomic.value import kotlin.jvm.JvmName /** @@ -113,10 +114,10 @@ private data class MemoizeKey5( } private class MemoizedHandler, out R>(val f: F) { - private val cache = AtomicRef(emptyMap()) + private val cache = Atomic(emptyMap()) operator fun invoke(k: K): R = when (k) { - in cache.get() -> cache.get().getValue(k) + in cache.value -> cache.value.getValue(k) else -> { val b = k(f) cache.loop { old -> diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/partials.kt b/arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/partials.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/partials.kt rename to arrow-libs/core/arrow-functions/src/commonMain/kotlin/arrow/core/partials.kt diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/AndThenTests.kt b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/AndThenTests.kt similarity index 69% rename from arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/AndThenTests.kt rename to arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/AndThenTests.kt index 69c5ce0829f..d2c23ef2426 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/AndThenTests.kt +++ b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/AndThenTests.kt @@ -1,18 +1,28 @@ package arrow.core -import arrow.core.test.functionAToB -import arrow.core.test.stackSafeIteration -import io.kotest.core.spec.style.StringSpec +import io.kotest.common.Platform +import io.kotest.common.platform import io.kotest.property.Arb import io.kotest.matchers.shouldBe +import io.kotest.property.arbitrary.arbitrary import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list +import io.kotest.property.arbitrary.next import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class AndThenTests : StringSpec({ - val count = stackSafeIteration() +class AndThenTests { + private val count = when (platform) { + Platform.JVM -> 200_000 + else -> 1000 + } + + private fun Arb.Companion.functionAToB(arb: Arb): Arb<(A) -> B> = arbitrary { random -> + { _: A -> arb.next(random) }.memoize() + } - "AndThen0 - compose a chain of functions with andThen should be same with AndThen" { + @Test fun andThen0ComposeChainWithAndThen() = runTest { checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ i }) { acc, f -> { f(acc()) } @@ -26,7 +36,7 @@ class AndThenTests : StringSpec({ } } - "AndThen0 - andThen is stack safe" { + @Test fun andThen0AndThenStackSafe() = runTest { val result = (0 until count).fold({ 0 }) { acc, _ -> acc.andThen { it + 1 } }.invoke() @@ -34,7 +44,7 @@ class AndThenTests : StringSpec({ result shouldBe count } - "AndThen1 - compose a chain of functions with andThen should be same with AndThen" { + @Test fun andThen1ComposeChainWithAndThen() = runTest { checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ x: Int -> x }) { acc, f -> { x: Int -> f(acc(x)) } @@ -48,7 +58,7 @@ class AndThenTests : StringSpec({ } } - "AndThen1 - compose a chain of function with compose should be same with AndThen" { + @Test fun andThen1ComposeChainWithCompose() = runTest { checkAll(Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, fs -> val result = fs.fold({ x: Int -> x }) { acc, f -> { x: Int -> acc(f(x)) } @@ -62,7 +72,7 @@ class AndThenTests : StringSpec({ } } - "AndThen1 - andThen is stack safe" { + @Test fun andThen1AndThenStackSafe() = runTest { val result = (0 until count).fold({ x: Int -> x }) { acc, _ -> acc.andThen { it + 1 } }.invoke(0) @@ -70,7 +80,7 @@ class AndThenTests : StringSpec({ result shouldBe count } - "AndThen1 - compose is stack safe" { + @Test fun andThen1ComposeStackSafe() = runTest { val result = (0 until count).fold({ x: Int -> x }) { acc, _ -> acc.compose { it + 1 } }.invoke(0) @@ -78,7 +88,7 @@ class AndThenTests : StringSpec({ result shouldBe count } - "AndThen2 - compose a chain of functions with andThen should be same with AndThen" { + @Test fun andThen2ComposeChainWithAndThen() = runTest { checkAll(Arb.int(), Arb.int(), Arb.list(Arb.functionAToB(Arb.int()))) { i, j, fs -> val result = fs.fold({ x: Int, y: Int -> x + y }) { acc, f -> { x: Int, y: Int -> f(acc(x, y)) } @@ -92,11 +102,11 @@ class AndThenTests : StringSpec({ } } - "AndThen2 - andThen is stack safe" { + @Test fun andThen2AndThenStackSafe() = runTest { val result = (0 until count).fold({ x: Int, y: Int -> x + y }) { acc, _ -> acc.andThen { it + 1 } }.invoke(0, 0) result shouldBe count } -}) +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CurryingTest.kt b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/CurryingTest.kt similarity index 86% rename from arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CurryingTest.kt rename to arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/CurryingTest.kt index cec444b9c23..28886cab4bc 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/CurryingTest.kt +++ b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/CurryingTest.kt @@ -1,162 +1,184 @@ package arrow.core -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlin.test.Test +import kotlinx.coroutines.test.runTest -class CurryingTest : StringSpec({ +class CurryingTest { fun arb(): Arb = Arb.string(1) //region curried - "A 2-arity curried function returns the same result as the function before being curried" { + @Test + fun curry2() = runTest { checkAll(arb(), arb()) { a1, a2 -> val add = { p1: String, p2: String -> p1 + p2 } add.curried()(a1)(a2) shouldBe add(a1, a2) } } - "A 3-arity curried function returns the same result as the function before being curried" { + @Test + fun curry3() = runTest { checkAll(arb(), arb(), arb()) { a1, a2, a3 -> val add = { p1: String, p2: String, p3: String -> p1 + p2 + p3 } add.curried()(a1)(a2)(a3) shouldBe add(a1, a2, a3) } } - "A 4-arity curried function returns the same result as the function before being curried" { + @Test + fun curry4() = runTest { checkAll(arb(), arb(), arb(), arb()) { a1, a2, a3, a4 -> val add = { p1: String, p2: String, p3: String, p4: String -> p1 + p2 + p3 + p4 } add.curried()(a1)(a2)(a3)(a4) shouldBe add(a1, a2, a3, a4) } } - "A 5-arity curried function returns the same result as the function before being curried" { + @Test + fun curry5() = runTest { checkAll(arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String -> p1 + p2 + p3 + p4 + p5 } add.curried()(a1)(a2)(a3)(a4)(a5) shouldBe add(a1, a2, a3, a4, a5) } } - "A 6-arity curried function returns the same result as the function before being curried" { + @Test + fun curry6() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String -> p1 + p2 + p3 + p4 + p5 + p6 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6) shouldBe add(a1, a2, a3, a4, a5, a6) } } - "A 7-arity curried function returns the same result as the function before being curried" { + @Test + fun curry7() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7) shouldBe add(a1, a2, a3, a4, a5, a6, a7) } } - "An 8-arity curried function returns the same result as the function before being curried" { + @Test + fun curry8() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8) } } - "A 9-arity curried function returns the same result as the function before being curried" { + @Test + fun curry9() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9) } } - "A 10-arity curried function returns the same result as the function before being curried" { + @Test + fun curry10() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } } - "An 11-arity curried function returns the same result as the function before being curried" { + @Test + fun curry11() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } } - "A 12-arity curried function returns the same result as the function before being curried" { + @Test + fun curry12() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } } - /* Waiting for Kotest 5.6.0 to be released + /* - "A 13-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 -> + @Test + fun curry13() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) } } - "A 14-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 -> + @Test + fun curry14() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) } } - "A 15-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 -> + @Test + fun curry15() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) } } - "A 16-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 -> + @Test + fun curry16() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) } } - "A 17-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 -> + @Test + fun curry17() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) } } - "A 18-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 -> + @Test + fun curry18() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String, p18: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) } } - "A 19-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 -> + @Test + fun curry19() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) } } - "A 20-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 -> + @Test + fun curry20() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19)(a20) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) } } - "A 21-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21 -> + @Test + fun curry21() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20 + p21 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19)(a20)(a21) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21) } } - "A 22-arity curried function returns the same result as the function before being curried" { - checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22 -> + @Test + fun curry22() = runTest { + checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String, p13: String, p14: String, p15: String, p16: String, p17: String, p18: String, p19: String, p20: String, p21: String, p22: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19 + p20 + p21 + p22 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12)(a13)(a14)(a15)(a16)(a17)(a18)(a19)(a20)(a21)(a22) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22) } @@ -168,7 +190,8 @@ class CurryingTest : StringSpec({ // region uncurried - "A 2-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry2() = runTest { checkAll(arb(), arb()) { a1, a2 -> val add = { p1: String, p2: String -> p1 + p2 } val curriedAdd = add.curried() @@ -176,7 +199,8 @@ class CurryingTest : StringSpec({ } } - "A 3-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry3() = runTest { checkAll(arb(), arb(), arb()) { a1, a2, a3 -> val add = { p1: String, p2: String, p3: String -> p1 + p2 + p3 } val curriedAdd = add.curried() @@ -184,7 +208,8 @@ class CurryingTest : StringSpec({ } } - "A 4-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry4() = runTest { checkAll(arb(), arb(), arb(), arb()) { a1, a2, a3, a4 -> val add = { p1: String, p2: String, p3: String, p4: String -> p1 + p2 + p3 + p4 } val curriedAdd = add.curried() @@ -192,7 +217,8 @@ class CurryingTest : StringSpec({ } } - "A 5-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry5() = runTest { checkAll(arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String -> p1 + p2 + p3 + p4 + p5 } val curriedAdd = add.curried() @@ -200,7 +226,8 @@ class CurryingTest : StringSpec({ } } - "A 6-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry6() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String -> p1 + p2 + p3 + p4 + p5 + p6 } val curriedAdd = add.curried() @@ -208,7 +235,8 @@ class CurryingTest : StringSpec({ } } - "A 7-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry7() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 } val curriedAdd = add.curried() @@ -216,7 +244,8 @@ class CurryingTest : StringSpec({ } } - "A 8-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry8() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 } val curriedAdd = add.curried() @@ -224,7 +253,8 @@ class CurryingTest : StringSpec({ } } - "A 9-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry9() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 } val curriedAdd = add.curried() @@ -232,7 +262,8 @@ class CurryingTest : StringSpec({ } } - "A 10-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry10() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 } val curriedAdd = add.curried() @@ -240,7 +271,8 @@ class CurryingTest : StringSpec({ } } - "A 11-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry11() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 } val curriedAdd = add.curried() @@ -248,7 +280,8 @@ class CurryingTest : StringSpec({ } } - "A 12-arity curried function returns the same result as the function after being uncurried" { + @Test + fun uncurry12() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -> val add = { p1: String, p2: String, p3: String, p4: String, p5: String, p6: String, p7: String, p8: String, p9: String, p10: String, p11: String, p12: String-> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 } val curriedAdd = add.curried() @@ -256,7 +289,7 @@ class CurryingTest : StringSpec({ } } - /* Waiting for Kotest 5.6.0 to be released + /* "A 13-arity curried function returns the same result as the function after being uncurried" { checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 -> @@ -344,84 +377,95 @@ class CurryingTest : StringSpec({ // region curried effect - "A 2-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect2() = runTest { checkAll(arb(), arb()) { a1, a2 -> val add: suspend (String, String) -> String = { p1, p2 -> p1 + p2 } add.curried()(a1)(a2) shouldBe add(a1, a2) } } - "A 3-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect3() = runTest { checkAll(arb(), arb(), arb()) { a1, a2, a3 -> val add: suspend (String, String, String) -> String = { p1, p2, p3 -> p1 + p2 + p3 } add.curried()(a1)(a2)(a3) shouldBe add(a1, a2, a3) } } - "A 4-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect4() = runTest { checkAll(arb(), arb(), arb(), arb()) { a1, a2, a3, a4 -> val add: suspend (String, String, String, String) -> String = { p1, p2, p3, p4 -> p1 + p2 + p3 + p4 } add.curried()(a1)(a2)(a3)(a4) shouldBe add(a1, a2, a3, a4) } } -// - "A 5-arity curried effect returns the same result as the effect before being curried" { + + @Test + fun curryEffect5() = runTest { checkAll(arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5 -> val add: suspend (String, String, String, String, String) -> String = { p1, p2, p3, p4, p5 -> p1 + p2 + p3 + p4 + p5 } add.curried()(a1)(a2)(a3)(a4)(a5) shouldBe add(a1, a2, a3, a4, a5) } } - "A 6-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect6() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6 -> val add: suspend (String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6 -> p1 + p2 + p3 + p4 + p5 + p6 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6) shouldBe add(a1, a2, a3, a4, a5, a6) } } - "A 7-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect7() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7 -> val add: suspend (String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7) shouldBe add(a1, a2, a3, a4, a5, a6, a7) } } - "An 8-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect8() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8 -> val add: suspend (String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8) } } - "A 9-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect9() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9 -> val add: suspend (String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9) } } - "A 10-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect10() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 -> val add: suspend (String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) } } - "An 11-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect11() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 -> val add: suspend (String, String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) } } - "A 12-arity curried effect returns the same result as the effect before being curried" { + @Test + fun curryEffect12() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -> val add: suspend (String, String, String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 } add.curried()(a1)(a2)(a3)(a4)(a5)(a6)(a7)(a8)(a9)(a10)(a11)(a12) shouldBe add(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) } } - /* Waiting for Kotest 5.6.0 to be released + /* "A 13-arity curried effect returns the same result as the effect before being curried" { checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 -> @@ -499,7 +543,8 @@ class CurryingTest : StringSpec({ // region uncurried effect - "A 2-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect2() = runTest { checkAll(arb(), arb()) { a1, a2 -> val add: suspend (String, String) -> String = { p1, p2 -> p1 + p2 } val curriedAdd = add.curried() @@ -507,7 +552,8 @@ class CurryingTest : StringSpec({ } } - "A 3-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect3() = runTest { checkAll(arb(), arb(), arb()) { a1, a2, a3 -> val add: suspend (String, String, String) -> String = { p1, p2, p3 -> p1 + p2 + p3 } val curriedAdd = add.curried() @@ -515,15 +561,17 @@ class CurryingTest : StringSpec({ } } - "A 4-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect4() = runTest { checkAll(arb(), arb(), arb(), arb()) { a1, a2, a3, a4 -> val add: suspend (String, String, String, String) -> String = { p1, p2, p3, p4 -> p1 + p2 + p3 + p4 } val curriedAdd = add.curried() curriedAdd(a1)(a2)(a3)(a4) shouldBe curriedAdd.uncurried()(a1, a2, a3, a4) } } -// - "A 5-arity curried effect returns the same result as the effect after being uncurried" { + + @Test + fun curryUncurryEffect5() = runTest { checkAll(arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5 -> val add: suspend (String, String, String, String, String) -> String = { p1, p2, p3, p4, p5 -> p1 + p2 + p3 + p4 + p5 } val curriedAdd = add.curried() @@ -531,7 +579,8 @@ class CurryingTest : StringSpec({ } } - "A 6-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect6() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6 -> val add: suspend (String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6 -> p1 + p2 + p3 + p4 + p5 + p6 } val curriedAdd = add.curried() @@ -539,7 +588,8 @@ class CurryingTest : StringSpec({ } } - "A 7-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect7() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7 -> val add: suspend (String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 } val curriedAdd = add.curried() @@ -547,7 +597,8 @@ class CurryingTest : StringSpec({ } } - "An 8-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect8() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8 -> val add: suspend (String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 } val curriedAdd = add.curried() @@ -555,7 +606,8 @@ class CurryingTest : StringSpec({ } } - "A 9-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect9() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9 -> val add: suspend (String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 } val curriedAdd = add.curried() @@ -563,7 +615,8 @@ class CurryingTest : StringSpec({ } } - "A 10-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect10() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 -> val add: suspend (String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 } val curriedAdd = add.curried() @@ -571,7 +624,8 @@ class CurryingTest : StringSpec({ } } - "An 11-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect11() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11 -> val add: suspend (String, String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 } val curriedAdd = add.curried() @@ -579,7 +633,8 @@ class CurryingTest : StringSpec({ } } - "A 12-arity curried effect returns the same result as the effect after being uncurried" { + @Test + fun curryUncurryEffect12() = runTest { checkAll(arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12 -> val add: suspend (String, String, String, String, String, String, String, String, String, String, String, String) -> String = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12 -> p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10 + p11 + p12 } val curriedAdd = add.curried() @@ -587,7 +642,7 @@ class CurryingTest : StringSpec({ } } - /* Waiting for Kotest 5.6.0 to be released + /* "A 13-arity curried effect returns the same result as the effect after being uncurried" { checkAll(PropTestConfig(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb(), arb()) { a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13 -> @@ -672,4 +727,4 @@ class CurryingTest : StringSpec({ */ // endregion -}) +} diff --git a/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt new file mode 100644 index 00000000000..6ceca3327bc --- /dev/null +++ b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/FunctionSyntaxTest.kt @@ -0,0 +1,158 @@ +package arrow.core + +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import kotlin.test.Test + +class FunctionSyntaxTest { + + val sum = { i1: Int, i2: Int -> i1 + i2 } + val add5 = { i: Int -> i + 5 } + val multiplyBy2 = { i: Int -> i * 2 } + + @Test fun andThenComposesCorrectly() = runTest { + val potato = "potato" + val ninja = "ninja" + val get = { potato } + val map = { word: String -> ninja + word } + (get andThen map)() + (ninja + potato) shouldBe (get andThen map)() + } + + @Test fun andThen1() = runTest { + val add5andMultiplyBy2 = add5 andThen multiplyBy2 + add5andMultiplyBy2(2) shouldBe 14 + } + + @Test fun andThen2() = runTest { + val sumAndMultiplyBy2 = sum andThen multiplyBy2 + sumAndMultiplyBy2(5, 2) shouldBe 14 + } + + @Test fun compose() = runTest { + val multiplyBy2andAdd5 = add5 compose multiplyBy2 + multiplyBy2andAdd5(2) shouldBe 9 + } + + @Test fun currying() = runTest { + val sum2ints = { x: Int, y: Int -> x + y } + val curried = sum2ints.curried() + curried(2)(4) shouldBe 6 + val addFive = curried(5) + addFive(7) shouldBe 12 + } + + @Test fun uncurrying() = runTest { + val sum2ints: (Int, Int) -> Int = { x, y -> x + y } + val curried: (Int) -> (Int) -> Int = sum2ints.curried() + curried(2)(4) shouldBe 6 + // same type as sum2ints, + curried.uncurried()(2, 4) shouldBe 6 + sum2ints(2, 4) shouldBe 6 + } + + @Test fun curryingEffect() = runTest { + val sum2ints: suspend (Int, Int) -> Int = { x: Int, y: Int -> x + y } + val curried: (Int) -> suspend (Int) -> Int = sum2ints.curried() + curried(2)(4) shouldBe 6 + val addFive: suspend (Int) -> Int = curried(5) + addFive(7) shouldBe 12 + } + + @Test fun uncurryingEffect() = runTest { + val sum2ints: suspend (Int, Int) -> Int = { x, y -> x + y } + val curried: (Int) -> suspend (Int) -> Int = sum2ints.curried() + curried(2)(4) shouldBe 6 + // same type as sum2ints, + curried.uncurried()(2, 4) shouldBe 6 + sum2ints(2, 4) shouldBe 6 + } + + @Test fun memoize() = runTest { + var counterA = 0 + var counterB = 0 + + val a = { _: Int -> counterA++ } + val b = { _: Int -> counterB++ }.memoize() + + repeat(5) { a(1) } + repeat(5) { b(1) } + + counterA shouldBe 5 + counterB shouldBe 1 // calling several times a memoized function with the same parameter is computed just once + } + + @Test fun memoizeEmpty() = runTest { + var counterA = 0 + var counterB = 0 + + val a = { counterA++ } + val b = { counterB++ }.memoize() + + repeat(5) { a() } + repeat(5) { b() } + + counterA shouldBe 5 + counterB shouldBe 1 // calling several times a memoized function with the same parameter is computed just once + } + + @Test fun partially() = runTest { + val sum5ints = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } + val sum4intsTo10 = sum5ints.partially5(10) + val sum3intsTo15 = sum4intsTo10.partially4(5) + val sum2intsTo17 = sum3intsTo15.partially3(2) + sum2intsTo17(1, 2) shouldBe 20 + + val prefixAndPostfix = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } + + val helloX = prefixAndPostfix.partially1("Hello, ").partially2("!") + helloX("Arrow") shouldBe "Hello, Arrow!" + } + + @Test fun suspendPartially() = runTest { + val sum5ints: suspend (Int, Int, Int, Int, Int) -> Int = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } + val sum4intsTo10 = sum5ints.partially5(10) + val sum3intsTo15 = sum4intsTo10.partially4(5) + val sum2intsTo17 = sum3intsTo15.partially3(2) + sum2intsTo17(1, 2) shouldBe 20 + + val prefixAndPostfix: suspend (String, String, String) -> String = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } + + val helloX = prefixAndPostfix.partially1("Hello, ").partially2("!") + helloX("Arrow") shouldBe "Hello, Arrow!" + } + + @Test fun partials() = runTest { + val sum5ints = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } + val sum4intsTo10: (Int, Int, Int, Int) -> Int = sum5ints.partially5(10) + val sum3intsTo15: (Int, Int, Int) -> Int = sum4intsTo10.partially4(5) + val sum2intsTo17: (Int, Int) -> Int = sum3intsTo15.partially3(2) + sum2intsTo17(1, 2) shouldBe 20 + val prefixAndPostfix = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } + val helloX: (String) -> String = prefixAndPostfix.partially1("Hello, ").partially2("!") + helloX("Arrow") shouldBe "Hello, Arrow!" + } + + @Test fun suspendPartials() = runTest { + val sum5ints: suspend (Int, Int, Int, Int, Int) -> Int = { a: Int, b: Int, c: Int, d: Int, e: Int -> a + b + c + d + e } + val sum4intsTo10: suspend (Int, Int, Int, Int) -> Int = sum5ints.partially5(10) + val sum3intsTo15: suspend (Int, Int, Int) -> Int = sum4intsTo10.partially4(5) + val sum2intsTo17: suspend (Int, Int) -> Int = sum3intsTo15.partially3(2) + sum2intsTo17(1, 2) shouldBe 20 + val prefixAndPostfix: suspend (String, String, String) -> String = { prefix: String, x: String, postfix: String -> "$prefix$x$postfix" } + val helloX: suspend (String) -> String = prefixAndPostfix.partially1("Hello, ").partially2("!") + helloX("Arrow") shouldBe "Hello, Arrow!" + } + + @Test fun bind() = runTest { + var i = 0 + fun inc(a: Int) { + i += a + } + + val binded = ::inc.partially1(5) + i shouldBe 0 + binded() + i shouldBe 5 + } +} diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MemoizationTest.kt b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/MemoizationTest.kt similarity index 73% rename from arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MemoizationTest.kt rename to arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/MemoizationTest.kt index b3a5c484bdb..ffbd512fc05 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/MemoizationTest.kt +++ b/arrow-libs/core/arrow-functions/src/commonTest/kotlin/arrow/core/MemoizationTest.kt @@ -1,14 +1,17 @@ +@file:Suppress("UNUSED_PARAMETER") + package arrow.core -import io.kotest.core.spec.style.StringSpec import io.kotest.property.checkAll import io.kotest.matchers.shouldBe import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlin.random.Random +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class MemoizationTest : StringSpec({ - "Memoize races" { +class MemoizationTest { + @Test fun memoizeRaces() = runTest { checkAll { fun sum(): Int = Random.nextInt(Int.MAX_VALUE) @@ -24,7 +27,7 @@ class MemoizationTest : StringSpec({ } } - "Memoize P0 only first execution runs" { + @Test fun memoize0OnlyFirst() = runTest { var runs = 0 fun sum(): Int { runs++ @@ -38,7 +41,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P0 nullable" { + @Test fun memoize0Nullable() = runTest { var runs = 0 fun sum(): Int? { runs++ @@ -52,7 +55,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P1 only first execution runs" { + @Test fun memoize1OnlyFirst() = runTest { var runs = 0 fun sum(n: Int): Int { runs++ @@ -70,7 +73,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 3 } - "Memoize P1 nullable" { + @Test fun memoize1Nullable() = runTest { var runs = 0 fun sum(n: Int): Int? { runs++ @@ -84,7 +87,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P2 only first execution runs" { + @Test fun memoize2OnlyFirst() = runTest { var runs = 0 fun sum(n1: Int, n2: Int): Int { runs++ @@ -103,7 +106,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 3 } - "Memoize P2 nullable" { + @Test fun memoize2Nullable() = runTest { var runs = 0 fun sum(n: Int, m: Int): Int? { runs++ @@ -117,7 +120,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P3 only first execution runs" { + @Test fun memoize3OnlyFirst() = runTest { var runs = 0 fun sum(n1: Int, n2: Int, n3: Int): Int { runs++ @@ -136,7 +139,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 3 } - "Memoize P3 nullable" { + @Test fun memoize3Nullable() = runTest { var runs = 0 fun sum(a: Int, b: Int, c: Int): Int? { runs++ @@ -150,7 +153,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P4 only first execution runs" { + @Test fun memoize4OnlyFirst() = runTest { var runs = 0 fun sum(n1: Int, n2: Int, n3: Int, n4: Int): Int { runs++ @@ -169,7 +172,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 3 } - "Memoize P4 nullable" { + @Test fun memoize4Nullable() = runTest { var runs = 0 fun sum(a: Int, b: Int, c: Int, d: Int): Int? { runs++ @@ -183,7 +186,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 1 } - "Memoize P5 only first execution runs" { + @Test fun memoize5OnlyFirst() = runTest { var runs = 0 fun sum(n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Int { runs++ @@ -202,7 +205,7 @@ class MemoizationTest : StringSpec({ runs shouldBe 3 } - "Memoize P5 nullable" { + @Test fun memoize5Nullable() = runTest { var runs = 0 fun sum(a: Int, b: Int, c: Int, d: Int, e: Int): Int? { runs++ @@ -215,37 +218,6 @@ class MemoizationTest : StringSpec({ memoized(1, 2, 3, 4, 5) shouldBe null runs shouldBe 1 } - - "Recursive memoization" { - var runs = 0 - val memoizedDeepRecursiveFibonacci: DeepRecursiveFunction = - MemoizedDeepRecursiveFunction { n -> - when (n) { - 0 -> 0.also { runs++ } - 1 -> 1 - else -> callRecursive(n - 1) + callRecursive(n - 2) - } - } - val result = memoizedDeepRecursiveFibonacci(5) - result shouldBe 5 - runs shouldBe 1 - } - - "Recursive memoization, run twice should be memoized" { - var runs = 0 - val memoizedDeepRecursiveFibonacci: DeepRecursiveFunction = - MemoizedDeepRecursiveFunction { n -> - when (n) { - 0 -> 0.also { runs++ } - 1 -> 1 - else -> callRecursive(n - 1) + callRecursive(n - 2) - } - } - val result1 = memoizedDeepRecursiveFibonacci(5) - val result2 = memoizedDeepRecursiveFibonacci(5) - result1 shouldBe result2 - runs shouldBe 1 - } -}) +} private fun consecSumResult(n: Int): Int = (n * (n + 1)) / 2 diff --git a/arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/composition-jvm.kt b/arrow-libs/core/arrow-functions/src/jvmMain/kotlin/arrow/core/composition-jvm.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/jvmMain/kotlin/arrow/core/composition-jvm.kt rename to arrow-libs/core/arrow-functions/src/jvmMain/kotlin/arrow/core/composition-jvm.kt diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-memoization-01.kt b/arrow-libs/core/arrow-functions/src/jvmTest/kotlin/examples/example-memoization-01.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-memoization-01.kt rename to arrow-libs/core/arrow-functions/src/jvmTest/kotlin/examples/example-memoization-01.kt diff --git a/arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/composition-js.kt b/arrow-libs/core/arrow-functions/src/nonJvmMain/kotlin/arrow/core/composition-js.kt similarity index 100% rename from arrow-libs/core/arrow-core/src/nonJvmMain/kotlin/arrow/core/composition-js.kt rename to arrow-libs/core/arrow-functions/src/nonJvmMain/kotlin/arrow/core/composition-js.kt diff --git a/arrow-libs/fx/arrow-collectors/build.gradle.kts b/arrow-libs/fx/arrow-collectors/build.gradle.kts index e671eb61701..98bd245dbbe 100644 --- a/arrow-libs/fx/arrow-collectors/build.gradle.kts +++ b/arrow-libs/fx/arrow-collectors/build.gradle.kts @@ -27,7 +27,6 @@ kotlin { dependencies { implementation(libs.kotlin.test) implementation(libs.coroutines.test) - implementation(libs.kotest.frameworkEngine) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } diff --git a/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api b/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api index 48fb6fcfc4e..f02721af9ec 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api +++ b/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api @@ -1,27 +1,5 @@ -public abstract interface class arrow/fx/coroutines/Atomic { - public static final field Companion Larrow/fx/coroutines/Atomic$Companion; - public abstract fun access (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun get (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun getAndSet (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun getAndUpdate (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun lens (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Atomic; - public abstract fun modify (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun modifyGet (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun set (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun setAndGet (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun tryModify (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun tryUpdate (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun update (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun updateAndGet (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/fx/coroutines/Atomic$Companion { - public final fun invoke (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun unsafe (Ljava/lang/Object;)Larrow/fx/coroutines/Atomic; -} - -public final class arrow/fx/coroutines/Atomic$DefaultImpls { - public static fun lens (Larrow/fx/coroutines/Atomic;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Atomic; +public final class arrow/fx/coroutines/AcquireStep { + public static final field INSTANCE Larrow/fx/coroutines/AcquireStep; } public final class arrow/fx/coroutines/BracketKt { @@ -33,70 +11,6 @@ public final class arrow/fx/coroutines/BracketKt { public static final fun runReleaseAndRethrow (Ljava/lang/Throwable;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/BuildersKt { - public static final fun never (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun unit (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/fx/coroutines/CircuitBreaker { - public static final field Companion Larrow/fx/coroutines/CircuitBreaker$Companion; - public synthetic fun (Ljava/util/concurrent/atomic/AtomicReference;IDDDLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun awaitClose (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun doOnClosed (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/CircuitBreaker; - public final fun doOnHalfOpen (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/CircuitBreaker; - public final fun doOnOpen (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/CircuitBreaker; - public final fun doOnRejectedTask (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/CircuitBreaker; - public final fun protectEither (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun protectOrThrow (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun state (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/fx/coroutines/CircuitBreaker$Companion { - public final fun of (IDDDLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun of$default (Larrow/fx/coroutines/CircuitBreaker$Companion;IDDDLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public final fun of-3c68mSE (IJDJLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun of-3c68mSE$default (Larrow/fx/coroutines/CircuitBreaker$Companion;IJDJLkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/fx/coroutines/CircuitBreaker$ExecutionRejected : java/lang/Throwable { - public fun (Ljava/lang/String;Larrow/fx/coroutines/CircuitBreaker$State;)V - public final fun getReason ()Ljava/lang/String; - public final fun getState ()Larrow/fx/coroutines/CircuitBreaker$State; -} - -public abstract class arrow/fx/coroutines/CircuitBreaker$State { -} - -public final class arrow/fx/coroutines/CircuitBreaker$State$Closed : arrow/fx/coroutines/CircuitBreaker$State { - public fun (I)V - public fun equals (Ljava/lang/Object;)Z - public final fun getFailures ()I - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/fx/coroutines/CircuitBreaker$State$HalfOpen : arrow/fx/coroutines/CircuitBreaker$State { - public fun (D)V - public synthetic fun (JLkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun equals (Ljava/lang/Object;)Z - public final fun getResetTimeout-UwyO8pc ()J - public final fun getResetTimeoutNanos ()D - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class arrow/fx/coroutines/CircuitBreaker$State$Open : arrow/fx/coroutines/CircuitBreaker$State { - public fun (JD)V - public synthetic fun (JJLkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun equals (Ljava/lang/Object;)Z - public final fun getExpiresAt ()J - public final fun getResetTimeout-UwyO8pc ()J - public final fun getResetTimeoutNanos ()D - public final fun getStartedAt ()J - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - public final class arrow/fx/coroutines/CountDownLatch { public fun (J)V public final fun await (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -166,7 +80,6 @@ public final class arrow/fx/coroutines/FlowExtensions { public static final fun parMapUnordered (Lkotlinx/coroutines/flow/Flow;ILkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; public static synthetic fun parMapUnordered$default (Lkotlinx/coroutines/flow/Flow;ILkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; public static final fun repeat (Lkotlinx/coroutines/flow/Flow;)Lkotlinx/coroutines/flow/Flow; - public static final fun retry (Lkotlinx/coroutines/flow/Flow;Larrow/fx/coroutines/Schedule;)Lkotlinx/coroutines/flow/Flow; } public final class arrow/fx/coroutines/ParMapKt { @@ -188,79 +101,6 @@ public final class arrow/fx/coroutines/ParMapKt { public static synthetic fun parMapOrAccumulate$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/ParTraverse { - public static final fun parSequence (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequence (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequence$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceEither (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceEither (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceEither$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceEitherN (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceEitherN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceEitherN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceEitherNScoped (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceEitherNScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceEitherNScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceEitherScoped (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceEitherScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceEitherScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceN (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceNScoped (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceNScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceNScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceResult (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceResult$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceResultN (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceResultN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceResultN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceResultNScoped (Ljava/lang/Iterable;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceResultNScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceResultNScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceResultScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceResultScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceScoped (Ljava/lang/Iterable;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceValidated (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceValidated (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceValidated$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceValidatedN (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceValidatedN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceValidatedN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceValidatedNScoped (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceValidatedNScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceValidatedNScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parSequenceValidatedScoped (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parSequenceValidatedScoped (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parSequenceValidatedScoped$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverse (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverse$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseEither (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseEither (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseEither$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseEitherN (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseEitherN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseEitherN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseN (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseResult (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseResult (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseResult$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseResultN (Ljava/lang/Iterable;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseResultN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseResultN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseValidated (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseValidated (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseValidated$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun parTraverseValidatedN (Ljava/lang/Iterable;Larrow/typeclasses/Semigroup;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun parTraverseValidatedN (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun parTraverseValidatedN$default (Ljava/lang/Iterable;Lkotlin/coroutines/CoroutineContext;Larrow/typeclasses/Semigroup;ILkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; -} - public final class arrow/fx/coroutines/ParZipKt { public static final fun parZip (Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function10;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun parZip (Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function11;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -323,21 +163,6 @@ public final class arrow/fx/coroutines/ParZipOrAccumulateKt { public static final fun parZipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/Platform { - public static final field INSTANCE Larrow/fx/coroutines/Platform; - public final fun composeErrors (Larrow/core/NonEmptyList;)Ljava/lang/Throwable; - public final fun composeErrors (Ljava/lang/Throwable;Ljava/lang/Object;)Ljava/lang/Throwable; - public final fun composeErrors (Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable; - public final fun composeErrors (Ljava/lang/Throwable;Ljava/util/List;)Ljava/lang/Throwable; - public final fun composeErrors (Ljava/lang/Throwable;[Ljava/lang/Throwable;)Ljava/lang/Throwable; - public final fun composeErrors (Ljava/util/List;)Ljava/lang/Throwable; - public final fun composeErrorsNullable (Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable; -} - -public final class arrow/fx/coroutines/PredefKt { - public static final fun timeInMillis ()J -} - public final class arrow/fx/coroutines/Race2Kt { public static final fun raceN (Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun raceN (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -388,223 +213,53 @@ public final class arrow/fx/coroutines/Race3Kt { public static synthetic fun raceN$default (Lkotlin/coroutines/CoroutineContext;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; } -public abstract class arrow/fx/coroutines/Resource { - public static final field Companion Larrow/fx/coroutines/Resource$Companion; - public final fun allocate (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun allocated (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun ap (Larrow/fx/coroutines/Resource;)Larrow/fx/coroutines/Resource; - public final fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public final fun map (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; - public final fun parZip (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public final fun parZip (Lkotlin/coroutines/CoroutineContext;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public static synthetic fun parZip$default (Larrow/fx/coroutines/Resource;Lkotlin/coroutines/CoroutineContext;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Larrow/fx/coroutines/Resource; - public final fun tap (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; - public final fun use (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun zip (Larrow/fx/coroutines/Resource;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function10;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function9;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function8;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function7;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function6;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function5;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function4;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public final fun zip (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; -} - -public final class arrow/fx/coroutines/Resource$Allocate : arrow/fx/coroutines/Resource { - public fun (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)V - public final fun getAcquire ()Lkotlin/jvm/functions/Function1; - public final fun getRelease ()Lkotlin/jvm/functions/Function3; -} - -public final class arrow/fx/coroutines/Resource$Bind : arrow/fx/coroutines/Resource { - public fun (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function1;)V - public final fun getF ()Lkotlin/jvm/functions/Function1; - public final fun getSource ()Larrow/fx/coroutines/Resource; -} - -public final class arrow/fx/coroutines/Resource$Companion { - public final fun defer (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public final fun getUnit ()Larrow/fx/coroutines/Resource; - public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public final fun just (Ljava/lang/Object;)Larrow/fx/coroutines/Resource; -} - -public final class arrow/fx/coroutines/Resource$Defer : arrow/fx/coroutines/Resource { - public fun (Lkotlin/jvm/functions/Function1;)V - public final fun getResource ()Lkotlin/jvm/functions/Function1; -} - -public final class arrow/fx/coroutines/Resource$Dsl : arrow/fx/coroutines/Resource { - public fun (Lkotlin/jvm/functions/Function2;)V - public final fun component1 ()Lkotlin/jvm/functions/Function2; - public final fun copy (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource$Dsl; - public static synthetic fun copy$default (Larrow/fx/coroutines/Resource$Dsl;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Larrow/fx/coroutines/Resource$Dsl; - public fun equals (Ljava/lang/Object;)Z - public final fun getDsl ()Lkotlin/jvm/functions/Function2; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public abstract interface annotation class arrow/fx/coroutines/ResourceDSL : java/lang/annotation/Annotation { } public final class arrow/fx/coroutines/ResourceExtensionsKt { - public static final fun autoCloseable (Larrow/fx/coroutines/continuations/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun autoCloseable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static synthetic fun autoCloseable$default (Larrow/fx/coroutines/continuations/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun autoCloseable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Larrow/fx/coroutines/Resource; - public static final fun closeable (Larrow/fx/coroutines/continuations/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun closeable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static synthetic fun closeable$default (Larrow/fx/coroutines/continuations/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun closeable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Larrow/fx/coroutines/Resource; - public static final fun executor-KLykuaI (JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static synthetic fun executor-KLykuaI$default (JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Larrow/fx/coroutines/Resource; - public static final fun executor-WPwdCS8 (Larrow/fx/coroutines/continuations/ResourceScope;JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static synthetic fun executor-WPwdCS8$default (Larrow/fx/coroutines/continuations/ResourceScope;JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static final fun fixedThreadPoolContext (ILjava/lang/String;)Larrow/fx/coroutines/Resource; - public static final fun fixedThreadPoolContext (Larrow/fx/coroutines/continuations/ResourceScope;ILjava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun fromAutoCloseable (Larrow/fx/coroutines/Resource$Companion;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static final fun fromCloseable (Larrow/fx/coroutines/Resource$Companion;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static final fun fromExecutor (Larrow/fx/coroutines/Resource$Companion;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static final fun singleThreadContext (Larrow/fx/coroutines/Resource$Companion;Ljava/lang/String;)Larrow/fx/coroutines/Resource; - public static final fun singleThreadContext (Larrow/fx/coroutines/continuations/ResourceScope;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun singleThreadContext (Ljava/lang/String;)Larrow/fx/coroutines/Resource; + public static final fun autoCloseable (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun autoCloseable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; + public static synthetic fun autoCloseable$default (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun autoCloseable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun closeable (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun closeable (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; + public static synthetic fun closeable$default (Larrow/fx/coroutines/ResourceScope;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static synthetic fun closeable$default (Lkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun executor-KLykuaI (JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function2; + public static synthetic fun executor-KLykuaI$default (JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/jvm/functions/Function2; + public static final fun executor-WPwdCS8 (Larrow/fx/coroutines/ResourceScope;JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun executor-WPwdCS8$default (Larrow/fx/coroutines/ResourceScope;JLkotlinx/coroutines/CoroutineDispatcher;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; + public static final fun fixedThreadPoolContext (ILjava/lang/String;)Lkotlin/jvm/functions/Function2; + public static final fun fixedThreadPoolContext (Larrow/fx/coroutines/ResourceScope;ILjava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun singleThreadContext (Larrow/fx/coroutines/ResourceScope;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun singleThreadContext (Ljava/lang/String;)Lkotlin/jvm/functions/Function2; } public final class arrow/fx/coroutines/ResourceKt { - public static final field nextVersionRemoved Ljava/lang/String; - public static final fun asFlow (Larrow/fx/coroutines/Resource;)Lkotlinx/coroutines/flow/Flow; - public static final fun release (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; - public static final fun release-zgiIeyo (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; - public static final fun releaseCase (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public static final fun releaseCase-zgiIeyo (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public static final synthetic fun resource (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static final fun resource (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Resource; - public static final fun resource (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; + public static final fun allocated (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static final fun asFlow (Lkotlin/jvm/functions/Function2;)Lkotlinx/coroutines/flow/Flow; + public static final fun resource (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2; + public static final fun resource (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; public static final fun resourceScope (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun sequence (Ljava/lang/Iterable;)Larrow/fx/coroutines/Resource; - public static final fun traverse (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; - public static final fun traverseResource (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Resource; + public static final fun use (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public abstract class arrow/fx/coroutines/Schedule { - public static final field Companion Larrow/fx/coroutines/Schedule$Companion; - public final fun and (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public abstract fun andThen (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public abstract fun check (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun choose (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun collect ()Larrow/fx/coroutines/Schedule; - public final fun combine (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public abstract fun combineNanos (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun compose (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun const (Ljava/lang/Object;)Larrow/fx/coroutines/Schedule; - public abstract fun contramap (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun delay (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun delayed (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public final fun delayedNanos (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun dimap (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule; - public final fun doUntil (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public final fun doWhile (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public final fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun foldLazy (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun forever ()Larrow/fx/coroutines/Schedule; - public final fun jittered (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule; - public final fun jittered (Lkotlin/random/Random;)Larrow/fx/coroutines/Schedule; - public static synthetic fun jittered$default (Larrow/fx/coroutines/Schedule;Lkotlin/random/Random;ILjava/lang/Object;)Larrow/fx/coroutines/Schedule; - public final fun jitteredDuration (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule; - public abstract fun log (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun logInput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public abstract fun logOutput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public abstract fun map (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule; - public final fun modify (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun modifyNanos (Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public abstract fun not ()Larrow/fx/coroutines/Schedule; - public final fun or (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public abstract fun pipe (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun repeat (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun repeatAsFlow (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun repeatOrElse (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun repeatOrElseAsFlow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun repeatOrElseEither (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun repeatOrElseEitherAsFlow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public final fun untilInput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun untilOutput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun void ()Larrow/fx/coroutines/Schedule; - public final fun whileInput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun whileOutput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun zip (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public abstract fun zip (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun zipLeft (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun zipRight (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; -} - -public final class arrow/fx/coroutines/Schedule$Companion { - public final fun collect ()Larrow/fx/coroutines/Schedule; - public final fun decision ()Larrow/fx/coroutines/Schedule; - public final fun delayInNanos ()Larrow/fx/coroutines/Schedule; - public final fun delayedDuration (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun delayedNanos (Larrow/fx/coroutines/Schedule;)Larrow/fx/coroutines/Schedule; - public final fun doUntil (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun doWhile (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun duration ()Larrow/fx/coroutines/Schedule; - public final fun exponential (DD)Larrow/fx/coroutines/Schedule; - public static synthetic fun exponential$default (Larrow/fx/coroutines/Schedule$Companion;DDILjava/lang/Object;)Larrow/fx/coroutines/Schedule; - public final fun exponential-VtjQ1oo (JD)Larrow/fx/coroutines/Schedule; - public static synthetic fun exponential-VtjQ1oo$default (Larrow/fx/coroutines/Schedule$Companion;JDILjava/lang/Object;)Larrow/fx/coroutines/Schedule; - public final fun fibonacci (D)Larrow/fx/coroutines/Schedule; - public final fun fibonacci-LRDsOJo (J)Larrow/fx/coroutines/Schedule; - public final fun forever ()Larrow/fx/coroutines/Schedule; - public final fun identity ()Larrow/fx/coroutines/Schedule; - public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Larrow/fx/coroutines/Schedule; - public final fun linear (D)Larrow/fx/coroutines/Schedule; - public final fun linear-LRDsOJo (J)Larrow/fx/coroutines/Schedule; - public final fun logInput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun logOutput (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun never ()Larrow/fx/coroutines/Schedule; - public final fun once ()Larrow/fx/coroutines/Schedule; - public final fun recurs (I)Larrow/fx/coroutines/Schedule; - public final fun spaced (D)Larrow/fx/coroutines/Schedule; - public final fun spaced-LRDsOJo (J)Larrow/fx/coroutines/Schedule; - public final fun unfold (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule; - public final fun unfoldLazy (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule; - public final fun unit ()Larrow/fx/coroutines/Schedule; -} - -public final class arrow/fx/coroutines/Schedule$Decision { - public static final field Companion Larrow/fx/coroutines/Schedule$Decision$Companion; - public fun (ZDLjava/lang/Object;Larrow/core/Eval;)V - public final fun bimap (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule$Decision; - public final fun combine (Larrow/fx/coroutines/Schedule$Decision;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule$Decision; - public final fun combineNanos (Larrow/fx/coroutines/Schedule$Decision;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Schedule$Decision; - public final fun component1 ()Z - public final fun component2 ()D - public final fun component3 ()Ljava/lang/Object; - public final fun component4 ()Larrow/core/Eval; - public final fun copy (ZDLjava/lang/Object;Larrow/core/Eval;)Larrow/fx/coroutines/Schedule$Decision; - public static synthetic fun copy$default (Larrow/fx/coroutines/Schedule$Decision;ZDLjava/lang/Object;Larrow/core/Eval;ILjava/lang/Object;)Larrow/fx/coroutines/Schedule$Decision; - public fun equals (Ljava/lang/Object;)Z - public final fun getCont ()Z - public final fun getDelayInNanos ()D - public final fun getDuration-UwyO8pc ()J - public final fun getFinish ()Larrow/core/Eval; - public final fun getState ()Ljava/lang/Object; - public fun hashCode ()I - public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule$Decision; - public final fun mapLeft (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Schedule$Decision; - public final fun not ()Larrow/fx/coroutines/Schedule$Decision; - public fun toString ()Ljava/lang/String; +public abstract interface class arrow/fx/coroutines/ResourceScope : arrow/AutoCloseScope { + public abstract fun bind (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun install (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun onRelease (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun release (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun releaseCase (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/Schedule$Decision$Companion { - public final fun cont (DLjava/lang/Object;Larrow/core/Eval;)Larrow/fx/coroutines/Schedule$Decision; - public final fun cont-KLykuaI (JLjava/lang/Object;Larrow/core/Eval;)Larrow/fx/coroutines/Schedule$Decision; - public final fun done (DLjava/lang/Object;Larrow/core/Eval;)Larrow/fx/coroutines/Schedule$Decision; - public final fun done-KLykuaI (JLjava/lang/Object;Larrow/core/Eval;)Larrow/fx/coroutines/Schedule$Decision; +public final class arrow/fx/coroutines/ResourceScope$DefaultImpls { + public static fun install (Larrow/fx/coroutines/ResourceScope;Ljava/lang/AutoCloseable;)Ljava/lang/AutoCloseable; + public static fun onRelease (Larrow/fx/coroutines/ResourceScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun release (Larrow/fx/coroutines/ResourceScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static fun releaseCase (Larrow/fx/coroutines/ResourceScope;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/ScheduleKt { - public static final fun retry (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun retryOrElse (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun retryOrElseEither (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; +public abstract interface annotation class arrow/fx/coroutines/ScopeDSL : java/lang/annotation/Annotation { } public final class arrow/fx/coroutines/ScopedRaiseAccumulate : arrow/core/raise/RaiseAccumulate, kotlinx/coroutines/CoroutineScope { @@ -612,45 +267,3 @@ public final class arrow/fx/coroutines/ScopedRaiseAccumulate : arrow/core/raise/ public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; } -public final class arrow/fx/coroutines/Use { - public static final synthetic fun box-impl (Lkotlin/jvm/functions/Function1;)Larrow/fx/coroutines/Use; - public static fun constructor-impl (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public fun equals (Ljava/lang/Object;)Z - public static fun equals-impl (Lkotlin/jvm/functions/Function1;Ljava/lang/Object;)Z - public static final fun equals-impl0 (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Z - public fun hashCode ()I - public static fun hashCode-impl (Lkotlin/jvm/functions/Function1;)I - public fun toString ()Ljava/lang/String; - public static fun toString-impl (Lkotlin/jvm/functions/Function1;)Ljava/lang/String; - public final synthetic fun unbox-impl ()Lkotlin/jvm/functions/Function1; -} - -public final class arrow/fx/coroutines/continuations/AcquireStep { - public static final field INSTANCE Larrow/fx/coroutines/continuations/AcquireStep; -} - -public abstract interface annotation class arrow/fx/coroutines/continuations/ResourceDSL : java/lang/annotation/Annotation { -} - -public final class arrow/fx/coroutines/continuations/ResourceKt { - public static final fun resource (Lkotlin/jvm/functions/Function2;)Larrow/fx/coroutines/Resource; -} - -public abstract interface class arrow/fx/coroutines/continuations/ResourceScope : arrow/AutoCloseScope { - public abstract fun bind (Larrow/fx/coroutines/Resource;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun install (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun onRelease (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun release (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public abstract fun releaseCase (Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public final class arrow/fx/coroutines/continuations/ResourceScope$DefaultImpls { - public static fun install (Larrow/fx/coroutines/continuations/ResourceScope;Ljava/lang/AutoCloseable;)Ljava/lang/AutoCloseable; - public static fun onRelease (Larrow/fx/coroutines/continuations/ResourceScope;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun release (Larrow/fx/coroutines/continuations/ResourceScope;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun releaseCase (Larrow/fx/coroutines/continuations/ResourceScope;Larrow/fx/coroutines/Resource;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; -} - -public abstract interface annotation class arrow/fx/coroutines/continuations/ScopeDSL : java/lang/annotation/Annotation { -} - diff --git a/arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts b/arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts index 027d928401e..07841a4ff60 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts +++ b/arrow-libs/fx/arrow-fx-coroutines/build.gradle.kts @@ -1,5 +1,8 @@ @file:Suppress("DSL_SCOPE_VIOLATION") +import java.time.Duration + + plugins { id(libs.plugins.kotlin.multiplatform.get().pluginId) alias(libs.plugins.arrowGradleConfig.kotlin) @@ -14,8 +17,6 @@ spotless { } } -apply(plugin = "io.kotest.multiplatform") - kotlin { sourceSets { commonMain { @@ -29,18 +30,11 @@ kotlin { commonTest { dependencies { + implementation(projects.arrowCore) implementation(libs.kotlin.test) - implementation(libs.kotest.frameworkEngine) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) - implementation(libs.coroutines.test) - implementation(projects.arrowAtomic) - } - } - - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) } } } @@ -52,4 +46,26 @@ kotlin { } } } + + js { + nodejs { + testTask { + useMocha { + timeout = "60s" + } + } + } + browser { + testTask { + useKarma { + useChromeHeadless() + timeout.set(Duration.ofMinutes(1)) + } + } + } + } +} + +tasks.withType().configureEach { + useJUnitPlatform() } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Atomic.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Atomic.kt deleted file mode 100644 index e8b16b27798..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Atomic.kt +++ /dev/null @@ -1,367 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.continuations.AtomicRef - -/** - * An [Atomic] with an initial value of [A]. - * - * [Atomic] wraps `atomic`, so that you can also use it on a top-level function or pass it around. - * In other languages this data type is also known as `Ref`, `IORef` or Concurrent safe Reference. - * So in case you don't need to pass around an atomic reference, or use it in top-level functions - * it's advised to use `atomic` from Atomic Fu directly. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main() { - * val count = Atomic(0) - * - * (0 until 20_000).parTraverse { - * count.update(Int::inc) - * } - * println(count.get()) - * } - * ``` - * - * - * [Atomic] also offers some other interesting operators such as [modify], [tryUpdate], [access] & [lens]. - */ -public interface Atomic { - - /** - * Obtains the current value. - * Since [AtomicRef] is always guaranteed to have a value, the returned action completes immediately after being bound. - */ - public suspend fun get(): A - - /** - * Sets the current value to [a]. - * The returned action completes after the reference has been successfully set. - */ - public suspend fun set(a: A): Unit - - /** - * Replaces the current value with [a], returning the *old* value. - */ - public suspend fun getAndSet(a: A): A - - /** - * Replaces the current value with [a], returning the *new* value. - */ - public suspend fun setAndGet(a: A): A - - /** - * Updates the current value using the supplied function [f]. - * - * If another modification occurs between the time the current value is read and subsequently updated, - * the modification is retried using the new value. Hence, [f] may be invoked multiple times. - */ - public suspend fun update(f: (A) -> A): Unit - - /** - * Modifies the current value using the supplied update function and returns the *old* value. - * - * @see [update], [f] may be invoked multiple times. - */ - public suspend fun getAndUpdate(f: (A) -> A): A - - /** - * Modifies the current value using the supplied update function and returns the *new* value. - * - * @see [update], [f] may be invoked multiple times. - */ - public suspend fun updateAndGet(f: (A) -> A): A - - /** - * Modify allows to inspect the state [A] of the [AtomicRef], update it and extract a different state [B]. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * typealias Id = Int - * data class Job(val description: String) - * - * val initialState = (0 until 10).map { i -> Pair(i, Job("Task #$i")) } - * - * suspend fun main(): Unit { - * val jobs = Atomic(initialState) - * - * val batch = jobs.modify { j -> - * val batch = j.take(5) - * Pair(j.drop(5), batch) - * } - * - * batch.forEach { (id, job) -> - * println("Going to work on $job with id $id\n") - * } - * - * println("Remaining: ${jobs.get()}") - * } - * ``` - * - */ - public suspend fun modify(f: (A) -> Pair): B - - /** - * ModifyGet allows to inspect state [A], update it and extract a different state [B]. - * In contrast to [modify], it returns a [Pair] of the updated state [A] and the extracted state [B]. - * - * @see [modify] for an example - */ - public suspend fun modifyGet(f: (A) -> Pair): Pair - - /** - * Attempts to modify the current value once, in contrast to [update] which calls [f] until it succeeds. - * - * @returns `false` if concurrent modification completes between the time the variable is read and the time it is set. - */ - public suspend fun tryUpdate(f: (A) -> A): Boolean - - /** - * Attempts to inspect the state, uptade it, and extract a different state. - * - * [tryModify] behaves as [tryUpdate] but allows the update function to return an output value of type [B]. - * - * @returns `null` if the update fails and [B] otherwise. - */ - public suspend fun tryModify(f: (A) -> Pair): B? - - /** - * Obtains a snapshot of the current value, and a setter for updating it. - * - * This is useful when you need to execute effects with the original result while still ensuring an atomic update. - * - * The setter will return `false` if another concurrent call invalidated the snapshot (modified the value). - * It will return `true` if setting the value was successful. - * - * Once it has returned `false` or been used once, a setter never succeeds again. - */ - public suspend fun access(): Pair Boolean> - - /** - * Creates an [AtomicRef] for [B] based on provided a [get] and [set] operation. - * - * This is useful when you have an [AtomicRef] of a `data class` - * and need to work with with certain properties individually, - * or want to hide parts of your domain from a dependency. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * data class Preference(val isEnabled: Boolean) - * data class User(val name: String, val age: Int, val preference: Preference) - * data class ViewState(val user: User) - * - * suspend fun main(): Unit { - * //sampleStart - * val state: Atomic = Atomic(ViewState(User("Simon", 27, Preference(false)))) - * val isEnabled: Atomic = - * state.lens( - * { it.user.preference.isEnabled }, - * { state, isEnabled -> - * state.copy( - * user = - * state.user.copy( - * preference = - * state.user.preference.copy(isEnabled = isEnabled) - * ) - * ) - * } - * ) - * isEnabled.set(true) - * println(state.get()) - * } - * ``` - * - */ - public fun lens(get: (A) -> B, set: (A, B) -> A): arrow.fx.coroutines.Atomic = - LensAtomic(this, get, set) - - public companion object { - - /** - * Creates an [AtomicRef] with an initial value of [A]. - * - * Data type on top of [atomic] to use in parallel functions. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main() { - * val count = Atomic(0) - * (0 until 20_000).parTraverse { - * count.update(Int::inc) - * } - * println(count.get()) - * } - * ``` - * - */ - public suspend operator fun invoke(a: A): arrow.fx.coroutines.Atomic = unsafe(a) - public fun unsafe(a: A): arrow.fx.coroutines.Atomic = DefaultAtomic(a) - } -} - -private class DefaultAtomic(a: A) : arrow.fx.coroutines.Atomic { - - private val ar = AtomicRef(a) - - public override suspend fun get(): A = - ar.get() - - public override suspend fun set(a: A): Unit { - ar.set(a) - } - - public override suspend fun getAndSet(a: A): A = - ar.getAndSet(a) - - public override suspend fun setAndGet(a: A): A { - ar.set(a) - return a - } - - public override suspend fun getAndUpdate(f: (A) -> A): A { - while (true) { - val cur = get() - val upd = f(cur) - if (ar.compareAndSet(cur, upd)) return cur - } - } - - public override suspend fun updateAndGet(f: (A) -> A): A { - while (true) { - val cur = ar.get() - val upd = f(cur) - if (ar.compareAndSet(cur, upd)) return upd - } - } - - public override suspend fun access(): Pair Boolean> { - val snapshot = ar.get() - val hasBeenCalled = AtomicRef(false) - val setter: suspend (A) -> Boolean = { a: A -> - hasBeenCalled.compareAndSet(false, true) && ar.compareAndSet(snapshot, a) - } - - return Pair(snapshot, setter) - } - - public override suspend fun tryUpdate(f: (A) -> A): Boolean = - tryModify { a -> Pair(f(a), Unit) } != null - - public override suspend fun tryModify(f: (A) -> Pair): B? { - val a = ar.get() - val (u, b) = f(a) - return if (ar.compareAndSet(a, u)) b - else null - } - - public override suspend fun update(f: (A) -> A): Unit = - modify { a -> Pair(f(a), Unit) } - - public override suspend fun modify(f: (A) -> Pair): B { - tailrec fun go(): B { - val a = ar.get() - val (u, b) = f(a) - return if (!ar.compareAndSet(a, u)) go() else b - } - - return go() - } - - public override suspend fun modifyGet(f: (A) -> Pair): Pair { - tailrec fun go(): Pair { - val a = ar.get() - val res = f(a) - return if (!ar.compareAndSet(a, res.first)) go() else res - } - - return go() - } -} - -private class LensAtomic( - private val underlying: arrow.fx.coroutines.Atomic, - private val lensGet: (A) -> B, - private val lensSet: (A, B) -> A -) : arrow.fx.coroutines.Atomic { - - public override suspend fun setAndGet(a: B): B = - underlying.modify { old -> - Pair(lensModify(old) { a }, a) - } - - public override suspend fun getAndUpdate(f: (B) -> B): B = - underlying.modify { old -> - Pair(lensModify(old, f), lensGet(old)) - } - - public override suspend fun updateAndGet(f: (B) -> B): B = - underlying.modify { old -> - val new = lensModify(old, f) - Pair(new, lensGet(new)) - } - - public override suspend fun get(): B = - lensGet(underlying.get()) - - public override suspend fun set(a: B) { - underlying.update { old -> lensModify(old) { a } } - } - - public override suspend fun getAndSet(a: B): B = - underlying.modify { old -> - Pair(lensModify(old) { a }, lensGet(old)) - } - - public override suspend fun update(f: (B) -> B) = - underlying.update { old -> lensModify(old, f) } - - public override suspend fun modify(f: (B) -> Pair): C = - underlying.modify { old -> - val oldB = lensGet(old) - val (b, c) = f(oldB) - Pair(lensSet(old, b), c) - } - - public override suspend fun modifyGet(f: (B) -> Pair): Pair = - underlying.modifyGet { old -> - val oldB = lensGet(old) - val (b, c) = f(oldB) - Pair(lensSet(old, b), c) - }.let { (a, c) -> Pair(lensGet(a), c) } - - public override suspend fun tryUpdate(f: (B) -> B): Boolean = - tryModify { b -> Pair(f(b), Unit) } != null - - public override suspend fun tryModify(f: (B) -> Pair): C? = - underlying.tryModify { a -> - val oldB = lensGet(a) - val (b, result) = f(oldB) - Pair(lensSet(a, b), result) - } - - public override suspend fun access(): Pair Boolean> { - val snapshotA = underlying.get() - val snapshotB = lensGet(snapshotA) - - val setter: suspend (B) -> Boolean = { b: B -> - val hasBeenCalled = AtomicRef(false) - - suspend { - val called = hasBeenCalled.compareAndSet(false, true) - - underlying.tryModify { a -> - if (called && lensGet(a) == snapshotA) Pair(lensSet(a, b), true) - else Pair(a, false) - } ?: false - }.invoke() - } - - return Pair(snapshotB, setter) - } - - private fun lensModify(s: A, f: (B) -> B): A = - lensSet(s, f(lensGet(s))) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Bracket.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Bracket.kt index 3ad336a3b8a..983dc48e558 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Bracket.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Bracket.kt @@ -31,6 +31,7 @@ public sealed class ExitCase { * @see guarantee for registering a handler that is guaranteed to always run. * @see guaranteeCase for registering a handler that executes for any [ExitCase]. */ +@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") public suspend inline fun onCancel( fa: suspend () -> A, crossinline onCancel: suspend () -> Unit @@ -54,6 +55,7 @@ public suspend inline fun onCancel( * @param finalizer handler to run after [fa]. * @see guaranteeCase for registering a handler that tracks the [ExitCase] of [fa]. */ +@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") public suspend inline fun guarantee( fa: suspend () -> A, crossinline finalizer: suspend () -> Unit @@ -83,6 +85,7 @@ public suspend inline fun guarantee( * @param finalizer handler to run after [fa]. * @see guarantee for registering a handler that ignores the [ExitCase] of [fa]. */ +@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") public suspend inline fun guaranteeCase( fa: suspend () -> A, crossinline finalizer: suspend (ExitCase) -> Unit @@ -115,10 +118,10 @@ public suspend inline fun guaranteeCase( * ```kotlin * import arrow.fx.coroutines.* * - * class File(url: String) { + * class File(val url: String) { * fun open(): File = this * fun close(): Unit {} - * override fun toString(): String = "This file contains some interesting content!" + * override fun toString(): String = "This file contains some interesting content from $url!" * } * * suspend fun openFile(uri: String): File = File(uri).open() @@ -138,6 +141,7 @@ public suspend inline fun guaranteeCase( * ``` * */ +@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") public suspend inline fun bracket( crossinline acquire: suspend () -> A, use: suspend (A) -> B, @@ -191,13 +195,13 @@ public suspend inline fun bracket( * ```kotlin * import arrow.fx.coroutines.* * - * class File(url: String) { + * class File(val url: String) { * fun open(): File = this * fun close(): Unit {} * } * * suspend fun File.content(): String = - * "This file contains some interesting content!" + * "This file contains some interesting content from $url!" * suspend fun openFile(uri: String): File = File(uri).open() * suspend fun closeFile(file: File): Unit = file.close() * @@ -221,6 +225,7 @@ public suspend inline fun bracket( * ``` * */ +@Suppress("REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE") public suspend inline fun bracketCase( crossinline acquire: suspend () -> A, use: suspend (A) -> B, diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CircuitBreaker.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CircuitBreaker.kt deleted file mode 100644 index ec07859b4a4..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CircuitBreaker.kt +++ /dev/null @@ -1,700 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.Either -import arrow.core.continuations.AtomicRef -import arrow.core.identity -import arrow.fx.coroutines.CircuitBreaker.State.Closed -import arrow.fx.coroutines.CircuitBreaker.State.HalfOpen -import arrow.fx.coroutines.CircuitBreaker.State.Open -import kotlinx.coroutines.CompletableDeferred -import kotlin.time.Duration -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.DurationUnit - -/** - * A [CircuitBreaker] is used to `protect` resources or services from being overloaded - * When a service is being overloaded, interacting with it more will only worsen its overloaded state. - * Especially when combined with retry mechanisms such as [Schedule], - * in some cases simply using a back-off retry policy might not be sufficient during peak traffics. - * - * To allow such overloaded resources from overloading, [CircuitBreaker] can help you `protect` the service by failing-fast. - * Thus [CircuitBreaker] helps us to achieve stability and prevent cascading failures in distributed systems. - * - * [CircuitBreaker] has three [CircuitBreaker.State]: - * 1. [Closed]: This is its normal state, where requests are being made. The state in which [CircuitBreaker] starts. - * - When an exception occurs it increments the failure counter - * - A successful request will reset the failure counter to zero - * - When the failure counter reaches the [maxFailures] threshold, the breaker is tripped into the [Open] state - * - * 2. [Open]: The [CircuitBreaker] will short-circuit/fail-fast all requests - * - All requests short-circuit/fail-fast with `ExecutionRejected` - * - If a request is made after the configured [resetTimeout] passes, the [CircuitBreaker] is tripped into the a [HalfOpen] state, allowing one request to go through as a test. - * - * 3. [HalfOpen]: The [CircuitBreaker] is in this state while it's allowing a request to go through, as a `test request` - * - All other requests made while `test request` is still running will short-circuit/fail-fast. - * - If the `test request` succeeds then the [CircuitBreaker] is tripped back into [Closed], with the resetTimeout and the failures count also reset to initial values. - * - If the `test request` fails, then the [CircuitBreaker] is tripped back into [Open], the [resetTimeout] is multiplied by the [exponentialBackoffFactor], up to the configured [maxResetTimeout]. - * - * Let's say we'd want to create a [CircuitBreaker] that only allows us to call a remote service twice, - * and then whenever more than two requests fail with an exception, the circuit breaker starts short-circuiting failing-fast. - * - * ```kotlin - * import arrow.core.Either - * import arrow.fx.coroutines.CircuitBreaker - * import kotlin.time.Duration.Companion.seconds - * import kotlin.time.ExperimentalTime - * import kotlinx.coroutines.delay - * - * @ExperimentalTime - * suspend fun main(): Unit { - * //sampleStart - * val circuitBreaker = CircuitBreaker.of( - * maxFailures = 2, - * resetTimeout = 2.seconds, - * exponentialBackoffFactor = 1.2, - * maxResetTimeout = 60.seconds, - * ) - * circuitBreaker.protectOrThrow { "I am in Closed: ${circuitBreaker.state()}" }.also(::println) - * - * println("Service getting overloaded . . .") - * - * Either.catch { circuitBreaker.protectOrThrow { throw RuntimeException("Service overloaded") } }.also(::println) - * Either.catch { circuitBreaker.protectOrThrow { throw RuntimeException("Service overloaded") } }.also(::println) - * circuitBreaker.protectEither { }.also { println("I am Open and short-circuit with ${it}. ${circuitBreaker.state()}") } - * - * println("Service recovering . . .").also { delay(2000) } - * - * circuitBreaker.protectOrThrow { "I am running test-request in HalfOpen: ${circuitBreaker.state()}" }.also(::println) - * println("I am back to normal state closed ${circuitBreaker.state()}") - * //sampleEnd - * } - * ``` - * - * - * A common pattern to make fault-tolerant/resilient systems is to compose a [CircuitBreaker] with a backing-off policy retry Schedule to guarantee not overloading the resource and the client interacting with it. - * but also not the client that is interacting with the resource. - * Below you can see how the simple `retry` function will result in `Either.Left`, - * but when we combine it with another schedule, it will always call the `CircuitBreaker` on times that it could've entered the [HalfOpen] state. - * The reason why [Schedule] is not sufficient to make your system resilient is because you also have to take into account parallel calls to your functions, - *; In contrast, a [CircuitBreaker] can track failures of every function call or even different functions to the same resource or service. - * - * ```kotlin - * import arrow.core.Either - * import arrow.fx.coroutines.CircuitBreaker - * import arrow.fx.coroutines.Schedule - * import arrow.fx.coroutines.retry - * import kotlin.time.Duration.Companion.seconds - * import kotlin.time.ExperimentalTime - * import kotlinx.coroutines.delay - * - * @ExperimentalTime - * suspend fun main(): Unit { - * suspend fun apiCall(): Unit { - * println("apiCall . . .") - * throw RuntimeException("Overloaded service") - * } - * - * //sampleStart - * val circuitBreaker = CircuitBreaker.of( - * maxFailures = 2, - * resetTimeout = 2.seconds, - * exponentialBackoffFactor = 2.0, // enable exponentialBackoffFactor - * maxResetTimeout = 60.seconds, // limit exponential back-off time - * ) - * - * suspend fun resilient(schedule: Schedule, f: suspend () -> A): A = - * schedule.retry { circuitBreaker.protectOrThrow(f) } - * - * Either.catch { - * resilient(Schedule.recurs(5), ::apiCall) - * }.let { println("recurs(5) apiCall twice and 4x short-circuit result from CircuitBreaker: $it") } - * - * delay(2000) - * println("CircuitBreaker ready to half-open") - * - * // Retry once and when the CircuitBreaker opens after 2 failures then retry with exponential back-off with same time as CircuitBreaker's resetTimeout - * val fiveTimesWithBackOff = Schedule.recurs(1) andThen - * Schedule.exponential(2.seconds) and Schedule.recurs(5) - * - * Either.catch { - * resilient(fiveTimesWithBackOff, ::apiCall) - * }.let { println("exponential(2.seconds) and recurs(5) always retries with actual apiCall: $it") } - * //sampleEnd - * } - * ``` - * - */ -@Deprecated(deprecatedInFavorOfArrowFxResilience, ReplaceWith("CircuitBreaker", "arrow.fx.resilience.CircuitBreaker")) -public class CircuitBreaker -private constructor( - private val state: AtomicRef, - private val maxFailures: Int, - private val resetTimeoutNanos: Double, - private val exponentialBackoffFactor: Double, - private val maxResetTimeoutNanos: Double, - private val onRejected: suspend () -> Unit, - private val onClosed: suspend () -> Unit, - private val onHalfOpen: suspend () -> Unit, - private val onOpen: suspend () -> Unit -) { - - private val resetTimeout: Duration = resetTimeoutNanos.nanoseconds - private val maxResetTimeout: Duration = maxResetTimeoutNanos.nanoseconds - - /** Returns the current [CircuitBreaker.State], meant for debugging purposes. - */ - public suspend fun state(): State = state.get() - - /** - * Awaits for this `CircuitBreaker` to be [CircuitBreaker.State.Closed]. - * - * If this `CircuitBreaker` is already in a closed state, then - * it returns immediately, otherwise it will wait (asynchronously) until - * the `CircuitBreaker` switches to the [CircuitBreaker.Closed] - * state again. - */ - public suspend fun awaitClose(): Unit = - when (val curr = state.get()) { - is Closed -> Unit - is Open -> curr.awaitClose.await() - is State.HalfOpen -> curr.awaitClose.await() - } - - /** - * Returns a new task that upon execution will execute the given - * task, but with the protection of this circuit breaker. - * If an exception in [fa] occurs, other than an [ExecutionRejected] exception, it will be rethrown. - */ - public suspend fun protectEither(fa: suspend () -> A): Either = - try { - Either.Right(protectOrThrow(fa)) - } catch (e: ExecutionRejected) { - Either.Left(e) - } - - /** - * Returns a new task that upon execution will execute the given - * task, but with the protection of this circuit breaker. - * If an exception in [fa] occurs it will be rethrown - */ - public tailrec suspend fun protectOrThrow(fa: suspend () -> A): A = - when (val curr = state.get()) { - is Closed -> { - val attempt = try { - Either.Right(fa.invoke()) - } catch (e: Throwable) { - Either.Left(e) - } - markOrResetFailures(attempt) - } - is Open -> { - val now = timeInMillis() - if (now >= curr.expiresAt) { - // The Open state has expired, so we are letting just one - // task to execute, while transitioning into HalfOpen - if (!state.compareAndSet( - curr, - HalfOpen(curr.resetTimeout, curr.awaitClose) - ) - ) protectOrThrow(fa) // retry! - else attemptReset(fa, curr.resetTimeout, curr.awaitClose, curr.startedAt) - } else { - // Open isn't expired, so we need to fail - val expiresInMillis = curr.expiresAt - now - onRejected.invoke() - throw ExecutionRejected( - "Rejected because the CircuitBreaker is in the Open state, attempting to close in $expiresInMillis millis", - curr - ) - } - } - is State.HalfOpen -> { - // CircuitBreaker is in HalfOpen state, which means we still reject all - // tasks, while waiting to see if our reset attempt succeeds or fails - onRejected.invoke() - throw ExecutionRejected("Rejected because the CircuitBreaker is in the HalfOpen state", curr) - } - } - - /** Function for counting failures in the `Closed` state, - * triggering the `Open` state if necessary. - */ - private tailrec suspend fun markOrResetFailures(result: Either): A = - when (val curr = state.get()) { - is Closed -> { - when (result) { - is Either.Right -> { - if (curr.failures == 0) result.value - else { // In case of success, must reset the failures counter! - val update = Closed(0) - if (!state.compareAndSet(curr, update)) markOrResetFailures(result) // retry? - else result.value - } - } - is Either.Left -> { - // In case of failure, we either increment the failures counter, - // or we transition in the `Open` state. - if (curr.failures + 1 < maxFailures) { - // It's fine, just increment the failures count - val update = Closed(curr.failures + 1) - if (!state.compareAndSet(curr, update)) markOrResetFailures(result) // retry? - else throw result.value - } else { - // N.B. this could be canceled, however we don't care - val now = timeInMillis() - // We've gone over the permitted failures threshold, - // so we need to open the circuit breaker - val update = Open(now, resetTimeout, CompletableDeferred()) - if (!state.compareAndSet(curr, update)) markOrResetFailures(result) // retry - else { - onOpen.invoke() - throw result.value - } - } - } - } - } - else -> result.fold({ throw it }, ::identity) - } - - /** Internal function that is the handler for the reset attempt when - * the circuit breaker is in `HalfOpen`. In this state we can - * either transition to `Closed` in case the attempt was - * successful, or to `Open` again, in case the attempt failed. - * - * @param task is the task to execute, along with the attempt - * handler attached - * @param resetTimeout is the last timeout applied to the previous - * `Open` state, to be multiplied by the backoff factor in - * case the attempt fails and it needs to transition to - * `Open` again - */ - private suspend fun attemptReset( - task: suspend () -> A, - resetTimeout: Duration, - awaitClose: CompletableDeferred, - lastStartedAt: Long - ): A = - bracketCase( - acquire = onHalfOpen, - use = { task.invoke() }, - release = { _, exit -> - when (exit) { - is ExitCase.Cancelled -> { - // We need to return to Open state - // otherwise we get stuck in Half-Open (see https://github.com/monix/monix/issues/1080 ) - state.set(Open(lastStartedAt, resetTimeout, awaitClose)) - onOpen.invoke() - } - ExitCase.Completed -> { - // While in HalfOpen only a reset attempt is allowed to update - // the state, so setting this directly is safe - state.set(Closed(0)) - awaitClose.complete(Unit) - onClosed.invoke() - } - is ExitCase.Failure -> { - // Failed reset, which means we go back in the Open state with new expiry val nextTimeout - val value: Duration = (resetTimeout * exponentialBackoffFactor) - val nextTimeout: Duration = - if (maxResetTimeout.isFinite() && value > maxResetTimeout) maxResetTimeout - else value - val ts = timeInMillis() - state.set(Open(ts, nextTimeout, awaitClose)) - onOpen.invoke() - } - } - } - ) - - /** Returns a new circuit breaker that wraps the state of the source - * and that upon a task being rejected will execute the given - * `callback`. - * - * This is useful for gathering stats. - * - * NOTE: calling this method multiple times will create a circuit - * breaker that will call multiple callbacks, thus the callback - * given is cumulative with other specified callbacks. - * - * @param callback will be executed when tasks get rejected. - * @return a new circuit breaker wrapping the state of the source. - */ - public fun doOnRejectedTask(callback: suspend () -> Unit): CircuitBreaker = - CircuitBreaker( - state = state, - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeout.toDouble(DurationUnit.NANOSECONDS), - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeout.toDouble(DurationUnit.NANOSECONDS), - onRejected = suspend { onRejected.invoke(); callback.invoke() }, - onClosed = onClosed, - onHalfOpen = onHalfOpen, - onOpen = onOpen - ) - - /** Returns a new circuit breaker that wraps the state of the source - * and that will fire the given callback upon the circuit breaker - * transitioning to the [CircuitBreaker.Closed] state. - * - * It is useful for gathering stats. - * - * NOTE: calling this method multiple times will create a circuit - * breaker that will call multiple callbacks, thus the callback - * given is cumulative with other specified callbacks. - * - * @param callback will be executed when the state evolves into [CircuitBreaker.Closed]. - * @return a new circuit breaker wrapping the state of the source. - */ - public fun doOnClosed(callback: suspend () -> Unit): CircuitBreaker = - CircuitBreaker( - state = state, - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeout.toDouble(DurationUnit.NANOSECONDS), - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeout.toDouble(DurationUnit.NANOSECONDS), - onRejected = onRejected, - onClosed = suspend { onClosed.invoke(); callback.invoke(); }, - onHalfOpen = onHalfOpen, - onOpen = onOpen - ) - - /** Returns a new circuit breaker that wraps the state of the source - * and that will fire the given callback upon the circuit breaker - * transitioning to the [CircuitBreaker.HalfOpen] state. - * - * It is useful for gathering stats. - * - * NOTE: calling this method multiple times will create a circuit - * breaker that will call multiple callbacks, thus the callback - * given is cumulative with other specified callbacks. - * - * @param callback is to be executed when the state evolves into [CircuitBreaker.HalfOpen] - * @return a new circuit breaker wrapping the state of the source - */ - public fun doOnHalfOpen(callback: suspend () -> Unit): CircuitBreaker = - CircuitBreaker( - state = state, - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeout.toDouble(DurationUnit.NANOSECONDS), - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeout.toDouble(DurationUnit.NANOSECONDS), - onRejected = onRejected, - onClosed = onClosed, - onHalfOpen = suspend { onHalfOpen.invoke(); callback.invoke() }, - onOpen = onOpen - ) - - /** Returns a new circuit breaker that wraps the state of the source - * and that will fire the given callback upon the circuit breaker - * transitioning to the [CircuitBreaker.Open] state. - * - * It is useful for gathering stats. - * - * NOTE: calling this method multiple times will create a circuit - * breaker that will call multiple callbacks, thus the callback - * given is cumulative with other specified callbacks. - * - * @param callback will be executed when the state evolves into [CircuitBreaker.Open] - * @return a new circuit breaker wrapping the state of the source - */ - public fun doOnOpen(callback: suspend () -> Unit): CircuitBreaker = - CircuitBreaker( - state = state, - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeout.toDouble(DurationUnit.NANOSECONDS), - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeout.toDouble(DurationUnit.NANOSECONDS), - onRejected = onRejected, - onClosed = onClosed, - onHalfOpen = onHalfOpen, - onOpen = suspend { onOpen.invoke(); callback.invoke() } - ) - - /** - * The initial state when initializing a [CircuitBreaker] is [Closed]. - * - * The available states are: - * - [Closed] in case tasks are allowed to go through - * - [Open] in case the circuit breaker is active and rejects incoming tasks - * - [HalfOpen] in case a reset attempt was triggered and it is waiting for - * the result in order to evolve in [Closed], or back to [Open] - */ - public sealed class State { - - /** - * [Closed] is the normal state of the [CircuitBreaker], where requests are being made. The state in which [CircuitBreaker] starts. - * - When an exceptions occurs it increments the failure counter - * - A successful request will reset the failure counter to zero - * - When the failure counter reaches the [maxFailures] threshold, the breaker is tripped into the [Open] state - * - * @param failures is the current failures count - */ - public class Closed(public val failures: Int) : State() { - override fun hashCode(): Int = - failures.hashCode() - - override fun equals(other: Any?): Boolean = - if (other is Closed) failures == other.failures - else false - - override fun toString(): String = - "Closed(failures=$failures)" - } - - /** - * When the [CircuitBreaker] is in the [Open] state it will short-circuit/fail-fast all requests - * - All requests short-circuit/fail-fast with `ExecutionRejected` - * - If a request is made after the configured [resetTimeout] passes, the [CircuitBreaker] is tripped into the a [HalfOpen] state, allowing one request to go through as a test. - * - * @param startedAt is the timestamp in milliseconds since the - * epoch when the transition to [Open] happened. - * - * @param resetTimeout is the current `resetTimeout` that is - * applied to this `Open` state, to be multiplied by the - * exponential backoff factor for the next transition from - * `HalfOpen` to `Open`. - */ - public class Open internal constructor( - public val startedAt: Long, - public val resetTimeout: Duration, - internal val awaitClose: CompletableDeferred, - ) : State() { - - @Deprecated( - "Prefer to use resetTimeout with kotlin.time.Duration", - ReplaceWith( - "resetTimeout.toDouble(DurationUnit.NANOSECONDS)", - "kotlin.time.DurationUnit" - ) - ) - public val resetTimeoutNanos: Double - get() = resetTimeout.toDouble(DurationUnit.NANOSECONDS) - - public constructor(startedAt: Long, resetTimeout: Duration) : this( - startedAt, - resetTimeout, - CompletableDeferred() - ) - - @Deprecated( - "This constructor will be removed in Arrow 2.0", - level = DeprecationLevel.WARNING - ) - internal constructor( - startedAt: Long, - resetTimeoutNanos: Double, - awaitClose: CompletableDeferred, - ) : this(startedAt, resetTimeoutNanos.nanoseconds, awaitClose) - - @Deprecated( - "This constructor will be removed in Arrow 2.0", - level = DeprecationLevel.WARNING - ) - public constructor(startedAt: Long, resetTimeoutNanos: Double) : this( - startedAt, - resetTimeoutNanos.nanoseconds, - CompletableDeferred() - ) - - /** The timestamp in milliseconds since the epoch, specifying - * when the `Open` state is to transition to [HalfOpen]. - * - * It is calculated as: - * `startedAt + resetTimeout` - */ - public val expiresAt: Long = resetTimeout.plus(startedAt.milliseconds).toLong(DurationUnit.MILLISECONDS) - - override fun equals(other: Any?): Boolean = - if (other is Open) this.startedAt == startedAt && - this.resetTimeout == resetTimeout && - this.expiresAt == expiresAt - else false - - override fun toString(): String = - "CircuitBreaker.State.Open(startedAt=$startedAt, resetTimeoutNanos=$resetTimeout, expiresAt=$expiresAt)" - - override fun hashCode(): Int { - var result = startedAt.hashCode() - result = 31 * result + resetTimeout.hashCode() - result = 31 * result + expiresAt.hashCode() - return result - } - } - - /** - * The [CircuitBreaker] is in [HalfOpen] state while it's allowing a test request to go through. - * - All other requests made while the test request is still running will short-circuit/fail-fast. - * - If the `test request` succeeds, then the [CircuitBreaker] is tripped back into [Closed], with the reset timeout, and the failures count also reset to their initial values. - * - If the `test request` fails, then the [CircuitBreaker] is tripped back into [Open], the [resetTimeout] is multiplied by the [exponentialBackoffFactor], up to the configured [maxResetTimeout]. - * - * @param resetTimeout is the current `reset timeout` that the [CircuitBreaker] has to stay in [Open] state. - * When the `reset timeout` lapsed, than the [CircuitBreaker] will allow a test request to go through in [HalfOpen]. - * If the test request failed, the [CircuitBreaker] will go back into [Open] and it'll multiply the [resetTimeout] with the the exponential backoff factor. - */ - public class HalfOpen internal constructor( - public val resetTimeout: Duration, - internal val awaitClose: CompletableDeferred - ) : State() { - - @Deprecated( - "Prefer to use resetTimeout with kotlin.time.Duration", - ReplaceWith( - "resetTimeout.toDouble(DurationUnit.NANOSECONDS)", - "kotlin.time.DurationUnit" - ) - ) - public val resetTimeoutNanos: Double - get() = resetTimeout.toDouble(DurationUnit.NANOSECONDS) - - public constructor(resetTimeout: Duration) : this(resetTimeout, CompletableDeferred()) - - @Deprecated( - "This constructor will be removed in Arrow 2.0", - level = DeprecationLevel.WARNING - ) - internal constructor( - resetTimeoutNanos: Double, - awaitClose: CompletableDeferred, - ) : this(resetTimeoutNanos.nanoseconds, awaitClose) - - public constructor(resetTimeoutNanos: Double) : this(resetTimeoutNanos.nanoseconds, CompletableDeferred()) - - override fun hashCode(): Int = - resetTimeout.hashCode() - - override fun equals(other: Any?): Boolean = - if (other is HalfOpen) resetTimeout == other.resetTimeout - else false - - override fun toString(): String = - "HalfOpen(resetTimeoutNanos=$resetTimeout)" - } - } - - public class ExecutionRejected(public val reason: String, public val state: State) : Throwable() - - public companion object { - /** - * Attempts to create a [CircuitBreaker]. - * - * @param maxFailures is the maximum count for failures before - * opening the circuit breaker. - * - * @param resetTimeoutNanos is the timeout to wait in the `Open` state - * before attempting a close of the circuit breaker (but without - * the backoff factor applied) in nanoseconds. - * - * @param exponentialBackoffFactor is a factor to use for resetting - * the `resetTimeout` when in the `HalfOpen` state, in case - * the attempt to `Close` fails. - * - * @param maxResetTimeoutNanos is the maximum timeout the circuit breaker - * is allowed to use when applying the `exponentialBackoffFactor`. - * - * @param onRejected is a callback for signaling rejected tasks, so - * every time a task execution is attempted and rejected in - * [CircuitBreaker.Open] or [CircuitBreaker.HalfOpen] - * states. - * - * @param onClosed is a callback for signaling transitions to the [CircuitBreaker.State.Closed] state. - * - * @param onHalfOpen is a callback for signaling transitions to [CircuitBreaker.State.HalfOpen]. - * - * @param onOpen is a callback for signaling transitions to [CircuitBreaker.State.Open]. - * - */ - @Deprecated( - "Prefer the kotlin.time.Duration constructor instead", - ReplaceWith( - "of(maxFailures, resetTimeoutNanos.nanoseconds, exponentialBackoffFactor, maxResetTimeout, onRejected, onClosed, onHalfOpen, onOpen)", - "import kotlin.time.Duration.Companion.nanoseconds" - ) - ) - public suspend fun of( - maxFailures: Int, - resetTimeoutNanos: Double, - exponentialBackoffFactor: Double = 1.0, - maxResetTimeoutNanos: Double = Double.POSITIVE_INFINITY, - onRejected: suspend () -> Unit = { }, - onClosed: suspend () -> Unit = { }, - onHalfOpen: suspend () -> Unit = { }, - onOpen: suspend () -> Unit = { }, - ): CircuitBreaker { - require(maxFailures >= 0) { - "maxFailures expected to be greater than or equal to 0, but was $maxFailures" - } - require(resetTimeoutNanos > 0) { - "resetTimeout expected to be greater than 0, but was $resetTimeoutNanos" - } - require(exponentialBackoffFactor > 0) { - "exponentialBackoffFactor expected to be greater than 0, but was $exponentialBackoffFactor" - } - require(maxResetTimeoutNanos > 0) { - "maxResetTimeout expected to be greater than 0, but was $maxResetTimeoutNanos" - } - return CircuitBreaker( - state = AtomicRef(Closed(0)), - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeoutNanos, - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeoutNanos, - onRejected = onRejected, - onClosed = onClosed, - onHalfOpen = onHalfOpen, - onOpen = onOpen - ) - } - - /** - * Attempts to create a [CircuitBreaker]. - * - * @param maxFailures is the maximum count for failures before - * opening the circuit breaker. - * - * @param resetTimeout is the timeout to wait in the `Open` state - * before attempting a close of the circuit breaker (but without - * the backoff factor applied). - * - * @param exponentialBackoffFactor is a factor to use for resetting - * the `resetTimeout` when in the `HalfOpen` state, in case - * the attempt to `Close` fails. - * - * @param maxResetTimeout is the maximum timeout the circuit breaker - * is allowed to use when applying the `exponentialBackoffFactor`. - * - * @param onRejected is a callback for signaling rejected tasks, so - * every time a task execution is attempted and rejected in - * [CircuitBreaker.Open] or [CircuitBreaker.HalfOpen] - * states. - * - * @param onClosed is a callback for signaling transitions to the [CircuitBreaker.State.Closed] state. - * - * @param onHalfOpen is a callback for signaling transitions to [CircuitBreaker.State.HalfOpen]. - * - * @param onOpen is a callback for signaling transitions to [CircuitBreaker.State.Open]. - * - */ - public suspend fun of( - maxFailures: Int, - resetTimeout: Duration, - exponentialBackoffFactor: Double = 1.0, - maxResetTimeout: Duration = Duration.INFINITE, - onRejected: suspend () -> Unit = suspend { }, - onClosed: suspend () -> Unit = suspend { }, - onHalfOpen: suspend () -> Unit = suspend { }, - onOpen: suspend () -> Unit = suspend { }, - ): CircuitBreaker = - of( - maxFailures = maxFailures, - resetTimeoutNanos = resetTimeout.toDouble(DurationUnit.NANOSECONDS), - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeoutNanos = maxResetTimeout.toDouble(DurationUnit.NANOSECONDS), - onRejected = onRejected, - onClosed = onClosed, - onHalfOpen = onHalfOpen, - onOpen = onOpen - ) - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CountDownLatch.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CountDownLatch.kt index 4781299361e..ed672e71024 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CountDownLatch.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CountDownLatch.kt @@ -1,7 +1,8 @@ package arrow.fx.coroutines -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.loop +import arrow.atomic.Atomic +import arrow.atomic.loop +import arrow.atomic.value import kotlinx.coroutines.CompletableDeferred /** @@ -13,7 +14,7 @@ import kotlinx.coroutines.CompletableDeferred */ public class CountDownLatch(private val initial: Long) { private val signal = CompletableDeferred() - private val count = AtomicRef(initial) + private val count = Atomic(initial) init { require(initial > 0) { @@ -22,14 +23,12 @@ public class CountDownLatch(private val initial: Long) { } /** Remaining count */ - public fun count(): Long = count.get() + public fun count(): Long = count.value /** Await [count] to reach zero */ - public suspend fun await(): Unit = - when (count.get()) { - 0L -> { } - else -> signal.await() - } + public suspend fun await() { + if (count.value > 0L) signal.await() + } /** Decrement [count] by one */ @Suppress("ReturnCount") diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CyclicBarrier.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CyclicBarrier.kt index 55bfca29242..29e241330b1 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CyclicBarrier.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/CyclicBarrier.kt @@ -1,8 +1,8 @@ package arrow.fx.coroutines -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.loop -import arrow.core.continuations.update +import arrow.atomic.Atomic +import arrow.atomic.loop +import arrow.atomic.update import arrow.core.nonFatalOrThrow import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableDeferred @@ -46,7 +46,7 @@ public class CyclicBarrier(public val capacity: Int, private val barrierAction: val unblock: CompletableDeferred ) : State - private val state: AtomicRef = AtomicRef(Awaiting(capacity, 0, CompletableDeferred())) + private val state: Atomic = Atomic(Awaiting(capacity, 0, CompletableDeferred())) /** * When called, all waiting coroutines will be cancelled with [CancellationException]. @@ -78,7 +78,6 @@ public class CyclicBarrier(public val capacity: Int, private val barrierAction: throw cancellationException } } - /** * When [await] is called the function will suspend until the required number of coroutines have called [await]. * Once the [capacity] of the barrier has been reached, the coroutine will be released and continue execution. diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/DeprecationWarnings.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/DeprecationWarnings.kt deleted file mode 100644 index 562367c2cd6..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/DeprecationWarnings.kt +++ /dev/null @@ -1,4 +0,0 @@ -package arrow.fx.coroutines - -internal const val deprecatedInFavorOfArrowFxResilience = - "This is now part of the arrow-fx-resilience module, and will be removed from arrow-fx-coroutines in version 2.0. Please update your project dependencies." diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParMap.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParMap.kt index 3238337d69e..b9511ad96c6 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParMap.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParMap.kt @@ -3,9 +3,9 @@ package arrow.fx.coroutines import arrow.core.raise.RaiseAccumulate import arrow.core.Either import arrow.core.NonEmptyList -import arrow.core.flattenOrAccumulate import arrow.core.raise.Raise import arrow.core.raise.either +import arrow.core.flattenOrAccumulate import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverse.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverse.kt deleted file mode 100644 index a9d64acc7f6..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverse.kt +++ /dev/null @@ -1,277 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("ParTraverse") - -package arrow.fx.coroutines - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlin.coroutines.ContinuationInterceptor -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName - -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default, n) { it() }", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable A>.parSequenceN(n: Int): List = - parMap(Dispatchers.Default, n) { it() } - -/** - * Sequences all tasks in [n] parallel processes on [Dispatchers.Default] and return the result. - * - * Cancelling this operation cancels all running tasks - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default, n) { it() }", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -@JvmName("parSequenceNScoped") -public suspend fun Iterable A>.parSequenceN(n: Int): List = - parMap(Dispatchers.Default, n) { it() } - -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(ctx, n) { it() }", - "arrow.fx.coroutines.parMap" - ) -) -public suspend fun Iterable A>.parSequenceN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): List = parMap(ctx, n) { it() } - -/** - * Sequences all tasks in [n] parallel processes and return the result. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(ctx, n) { it() }", - "arrow.fx.coroutines.parMap" - ) -) -@JvmName("parSequenceNScoped") -public suspend fun Iterable A>.parSequenceN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): List = parMap(ctx, n) { it() } -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default) { it() }", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable A>.parSequence(): List = - parMap(Dispatchers.Default) { it() } - -/** - * Sequences all tasks in parallel on [Dispatchers.Default] and return the result - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * typealias Task = suspend () -> Unit - * - * suspend fun main(): Unit { - * //sampleStart - * fun getTask(id: Int): Task = - * suspend { println("Working on task $id on ${Thread.currentThread().name}") } - * - * val res = listOf(1, 2, 3) - * .map(::getTask) - * .parSequence() - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default) { it() }", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -@JvmName("parSequenceScoped") -public suspend fun Iterable A>.parSequence(): List = - parMap(Dispatchers.Default) { it() } - -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(ctx) { it() }", - "arrow.fx.coroutines.parMap" - ) -) -public suspend fun Iterable A>.parSequence(ctx: CoroutineContext = EmptyCoroutineContext): List = - parMap(ctx) { it() } - -/** - * Sequences all tasks in parallel and return the result - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * typealias Task = suspend () -> Unit - * - * suspend fun main(): Unit { - * //sampleStart - * fun getTask(id: Int): Task = - * suspend { println("Working on task $id on ${Thread.currentThread().name}") } - * - * val res = listOf(1, 2, 3) - * .map(::getTask) - * .parSequence(Dispatchers.IO) - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(ctx) { it() }", - "arrow.fx.coroutines.parMap" - ) -) -@JvmName("parSequenceScoped") -public suspend fun Iterable A>.parSequence(ctx: CoroutineContext = EmptyCoroutineContext): List = - parMap(ctx) { it() } - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [Dispatchers.Default]. - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default, n, f)", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverseN(n: Int, f: suspend CoroutineScope.(A) -> B): List = - parMap(Dispatchers.Default, n, f) - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [ctx]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(ctx, n, f)", - "arrow.fx.coroutines.parMap" - ) -) -public suspend fun Iterable.parTraverseN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int, - f: suspend CoroutineScope.(A) -> B -): List = parMap(ctx, n, f) - -/** - * Traverses this [Iterable] and runs all mappers [f] on [Dispatchers.Default]. - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * data class User(val id: Int, val createdOn: String) - * - * suspend fun main(): Unit { - * //sampleStart - * suspend fun getUserById(id: Int): User = - * User(id, Thread.currentThread().name) - * - * val res = listOf(1, 2, 3) - * .parTraverse { getUserById(it) } - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith( - "parMap(Dispatchers.Default, f)", - "arrow.fx.coroutines.parMap", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverse(f: suspend CoroutineScope.(A) -> B): List = - parMap(Dispatchers.Default, f) - -/** - * Traverses this [Iterable] and runs all mappers [f] on [CoroutineContext]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * data class User(val id: Int, val createdOn: String) - * - * suspend fun main(): Unit { - * //sampleStart - * suspend fun getUserById(id: Int): User = - * User(id, Thread.currentThread().name) - * - * val res = listOf(1, 2, 3) - * .parTraverse(Dispatchers.IO) { getUserById(it) } - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Function is being renamed to parMap in 2.x.x", - ReplaceWith("parMap(ctx, f)", "arrow.fx.coroutines.parMap") -) -public suspend fun Iterable.parTraverse( - ctx: CoroutineContext = EmptyCoroutineContext, - f: suspend CoroutineScope.(A) -> B -): List = parMap(ctx, f) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseEither.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseEither.kt deleted file mode 100644 index bee0e11f721..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseEither.kt +++ /dev/null @@ -1,290 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("ParTraverse") - -package arrow.fx.coroutines - -import arrow.core.Either -import arrow.core.continuations.either -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlin.coroutines.ContinuationInterceptor -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName - -/** - * Sequences all tasks in [n] parallel processes on [Dispatchers.Default] and return the result. - * - * Cancelling this operation cancels all running tasks - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable Either>.parSequenceEitherN(n: Int): Either> = - either { parMap(Dispatchers.Default, n) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -@JvmName("parSequenceEitherNScoped") -public suspend fun Iterable Either>.parSequenceEitherN(n: Int): Either> = - either { parMap(Dispatchers.Default, n) { it().bind() } } - -/** - * Sequences all tasks in [n] parallel processes on [ctx] and return the result. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -@JvmName("parSequenceEitherNScoped") -public suspend fun Iterable Either>.parSequenceEitherN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): Either> = - either { parMap(ctx, n) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -public suspend fun Iterable Either>.parSequenceEitherN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): Either> = - either { parMap(ctx, n) { it().bind() } } - -/** - * Sequences all tasks in parallel on [Dispatchers.Default] and return the result. - * If one of the tasks returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running tasks, and returning the first encountered [Either.Left]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable Either>.parSequenceEither(): Either> = - either { parMap(Dispatchers.Default) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -@JvmName("parSequenceEitherScoped") -public suspend fun Iterable Either>.parSequenceEither(): Either> = - either { parMap(Dispatchers.Default) { it().bind() } } - -/** - * Sequences all tasks in parallel on [ctx] and return the result. - * If one of the tasks returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running tasks, and returning the first encountered [Either.Left]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.core.* - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * object Error - * typealias Task = suspend () -> Either - * - * suspend fun main(): Unit { - * //sampleStart - * fun getTask(id: Int): Task = - * suspend { Either.catch { println("Working on task $id on ${Thread.currentThread().name}") } } - * - * val res = listOf(1, 2, 3) - * .map(::getTask) - * .parSequenceEither(Dispatchers.IO) - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -@JvmName("parSequenceEitherScoped") -public suspend fun Iterable Either>.parSequenceEither( - ctx: CoroutineContext = EmptyCoroutineContext -): Either> = either { parMap(ctx) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -public suspend fun Iterable Either>.parSequenceEither( - ctx: CoroutineContext = EmptyCoroutineContext -): Either> = either { parMap(ctx) { it().bind() } } - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [Dispatchers.Default]. - * If one of the [f] returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running [f], and returning the first encountered [Either.Left]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default, n) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverseEitherN( - n: Int, - f: suspend CoroutineScope.(A) -> Either -): Either> = either { parMap(Dispatchers.Default, n) { f(it).bind() } } - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [Dispatchers.Default]. - * If one of the [f] returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running [f], and returning the first encountered [Either.Left]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx, n) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -public suspend fun Iterable.parTraverseEitherN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int, - f: suspend CoroutineScope.(A) -> Either -): Either> = either { parMap(ctx, n) { f(it).bind() } } - -/** - * Traverses this [Iterable] and runs all mappers [f] on [Dispatchers.Default]. - * If one of the [f] returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running [f], and returning the first encountered [Either.Left]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(Dispatchers.Default) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverseEither( - f: suspend CoroutineScope.(A) -> Either -): Either> = - either { parMap(Dispatchers.Default) { f(it).bind() } } - -/** - * Traverses this [Iterable] and runs all mappers [f] on [CoroutineContext]. - * If one of the [f] returns [Either.Left], then it will short-circuit the operation and - * cancelling all this running [f], and returning the first encountered [Either.Left]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.core.* - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * object Error - * data class User(val id: Int, val createdOn: String) - * - * suspend fun main(): Unit { - * //sampleStart - * suspend fun getUserById(id: Int): Either = - * if(id == 4) Error.left() - * else User(id, Thread.currentThread().name).right() - * - * val res = listOf(1, 2, 3) - * .parTraverseEither(Dispatchers.IO) { getUserById(it) } - * - * val res2 = listOf(1, 4, 2, 3) - * .parTraverseEither(Dispatchers.IO) { getUserById(it) } - * //sampleEnd - * println(res) - * println(res2) - * } - * ``` - * - */ -@Deprecated( - "Prefer composing parMap with either DSL", - ReplaceWith( - "either> { this.parMap(ctx) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.either" - ) -) -public suspend fun Iterable.parTraverseEither( - ctx: CoroutineContext = EmptyCoroutineContext, - f: suspend CoroutineScope.(A) -> Either -): Either> = - either { parMap(ctx) { f(it).bind() } } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseResult.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseResult.kt deleted file mode 100644 index 8b175f66274..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseResult.kt +++ /dev/null @@ -1,209 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("ParTraverse") - -package arrow.fx.coroutines - -import arrow.core.continuations.result -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlin.coroutines.ContinuationInterceptor -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName - -/** - * Traverses this [Iterable] and runs `suspend CoroutineScope.() -> Result` in [n] parallel operations on [CoroutineContext]. - * If one or more of the tasks returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(Dispatchers.Default, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result", - "kotlinx.coroutines.Dispatchers" - ) -) -@JvmName("parSequenceResultNScoped") -public suspend fun Iterable Result>.parSequenceResultN(n: Int): Result> = - result { parMap(Dispatchers.Default, n) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(Dispatchers.Default, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable Result>.parSequenceResultN(n: Int): Result> = - result { parMap(Dispatchers.Default, n) { it().bind() } } - -/** - * Traverses this [Iterable] and runs `suspend CoroutineScope.() -> Result` in [n] parallel operations on [CoroutineContext]. - * If one or more of the tasks returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -@JvmName("parSequenceResultNScoped") -public suspend fun Iterable Result>.parSequenceResultN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): Result> = - result { parMap(ctx, n) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx, n) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -public suspend fun Iterable Result>.parSequenceResultN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int -): Result> = - result { parMap(ctx, n) { it().bind() } } - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [Dispatchers.Default]. - * If one or more of the [f] returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(Dispatchers.Default, n) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverseResultN( - n: Int, - f: suspend CoroutineScope.(A) -> Result -): Result> = - result { parMap(Dispatchers.Default, n) { f(it).bind() } } - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [CoroutineContext]. - * If one or more of the [f] returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx, n) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -public suspend fun Iterable.parTraverseResultN( - ctx: CoroutineContext = EmptyCoroutineContext, - n: Int, - f: suspend CoroutineScope.(A) -> Result -): Result> = result { parMap(ctx, n) { f(it).bind() } } - -/** - * Sequences all tasks in parallel on [ctx] and returns the result. - * If one or more of the tasks returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -@JvmName("parSequenceResultScoped") -public suspend fun Iterable Result>.parSequenceResult( - ctx: CoroutineContext = EmptyCoroutineContext -): Result> = result { parMap(ctx) { it().bind() } } - -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx) { it().bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -public suspend fun Iterable Result>.parSequenceResult( - ctx: CoroutineContext = EmptyCoroutineContext -): Result> = - result { parMap(ctx) { it().bind() } } - -/** - * Traverses this [Iterable] and runs all mappers [f] on [Dispatchers.Default]. - * If one or more of the [f] returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(Dispatchers.Default) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result", - "kotlinx.coroutines.Dispatchers" - ) -) -public suspend fun Iterable.parTraverseResult(f: suspend CoroutineScope.(A) -> Result): Result> = - result { parMap(Dispatchers.Default) { f(it).bind() } } - -/** - * Traverses this [Iterable] and runs all mappers [f] on [CoroutineContext]. - * If one or more of the [f] returns [Result.failure] then all the [Result.failure] results will be combined using [addSuppressed]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - */ -@Deprecated( - "Prefer composing parMap with result DSL", - ReplaceWith( - "result> { this.parMap(ctx) { f(it).bind() } }", - "arrow.fx.coroutines.parMap", - "arrow.core.continuations.result" - ) -) -public suspend fun Iterable.parTraverseResult( - ctx: CoroutineContext = EmptyCoroutineContext, - f: suspend CoroutineScope.(A) -> Result -): Result> = - result { parMap(ctx) { f(it).bind() } } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseValidated.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseValidated.kt deleted file mode 100644 index b90ae70d804..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParTraverseValidated.kt +++ /dev/null @@ -1,320 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("ParTraverse") - -package arrow.fx.coroutines - -import arrow.core.Validated -import arrow.typeclasses.Semigroup -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlin.coroutines.ContinuationInterceptor -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [CoroutineContext]. - * If one or more of the tasks returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -@JvmName("parSequenceValidatedNScoped") -public suspend fun Iterable Validated>.parSequenceValidatedN( - semigroup: Semigroup, - n: Int -): Validated> = with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -public suspend fun Iterable Validated>.parSequenceValidatedN( - semigroup: Semigroup, - n: Int -): Validated> = with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [CoroutineContext]. - * If one or more of the tasks returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(ctx, n, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "arrow.core.Validated" - ) -) -@JvmName("parSequenceValidatedNScoped") -public suspend fun Iterable Validated>.parSequenceValidatedN( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup, - n: Int -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, n, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(ctx, n, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated()", - "arrow.fx.coroutines.parMapOrAccumulate", - "arrow.core.Validated" - ) -) -public suspend fun Iterable Validated>.parSequenceValidatedN( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup, - n: Int -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, n, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [Dispatchers.Default]. - * If one or more of the [f] returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -public suspend fun Iterable.parTraverseValidatedN( - semigroup: Semigroup, - n: Int, - f: suspend CoroutineScope.(A) -> Validated -): Validated> = with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() -} - -/** - * Traverses this [Iterable] and runs [f] in [n] parallel operations on [CoroutineContext]. - * If one or more of the [f] returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, n, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -public suspend fun Iterable.parTraverseValidatedN( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup, - n: Int, - f: suspend CoroutineScope.(A) -> Validated -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, n, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() -} - -/** - * Sequences all tasks in parallel on [Dispatchers.Default] and returns the result. - * If one or more of the tasks returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -@JvmName("parSequenceValidatedScoped") -public suspend fun Iterable Validated>.parSequenceValidated(semigroup: Semigroup): Validated> = - with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { it().bind() }.toValidated() - } - -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -public suspend fun Iterable Validated>.parSequenceValidated(semigroup: Semigroup): Validated> = - with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { it().bind() }.toValidated() - } - -/** - * Sequences all tasks in parallel on [ctx] and returns the result. - * If one or more of the tasks returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.core.* - * import arrow.typeclasses.Semigroup - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * typealias Task = suspend () -> ValidatedNel - * - * suspend fun main(): Unit { - * //sampleStart - * fun getTask(id: Int): Task = - * suspend { Validated.catchNel { println("Working on task $id on ${Thread.currentThread().name}") } } - * - * val res = listOf(1, 2, 3) - * .map(::getTask) - * .parSequenceValidated(Dispatchers.IO, Semigroup.nonEmptyList()) - * //sampleEnd - * println(res) - * } - * ``` - * - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "arrow.core.Validated" - ) -) -@JvmName("parSequenceValidatedScoped") -public suspend fun Iterable Validated>.parSequenceValidated( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { it.invoke().bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "arrow.core.Validated" - ) -) -public suspend fun Iterable Validated>.parSequenceValidated( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { it().bind() }.toValidated() -} - -/** - * Traverses this [Iterable] and runs all mappers [f] on [Dispatchers.Default]. - * If one or more of the [f] returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Cancelling this operation cancels all running tasks. - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "kotlinx.coroutines.Dispatchers", - "arrow.core.Validated" - ) -) -public suspend fun Iterable.parTraverseValidated( - semigroup: Semigroup, - f: suspend CoroutineScope.(A) -> Validated -): Validated> = with(semigroup) { - parMapOrAccumulate(Dispatchers.Default, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() -} - -/** - * Traverses this [Iterable] and runs all mappers [f] on [CoroutineContext]. - * If one or more of the [f] returns [Validated.Invalid] then all the [Validated.Invalid] results will be combined using [semigroup]. - * - * Coroutine context is inherited from a [CoroutineScope], additional context elements can be specified with [ctx] argument. - * If the combined context does not have any dispatcher nor any other [ContinuationInterceptor], then [Dispatchers.Default] is used. - * **WARNING** If the combined context has a single threaded [ContinuationInterceptor], this function will not run in parallel. - * - * Cancelling this operation cancels all running tasks. - * - * ```kotlin - * import arrow.core.* - * import arrow.typeclasses.Semigroup - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.Dispatchers - * - * object Error - * data class User(val id: Int, val createdOn: String) - * - * suspend fun main(): Unit { - * //sampleStart - * suspend fun getUserById(id: Int): ValidatedNel = - * if(id % 2 == 0) Error.invalidNel() - * else User(id, Thread.currentThread().name).validNel() - * - * val res = listOf(1, 3, 5) - * .parTraverseValidated(Dispatchers.IO, Semigroup.nonEmptyList()) { getUserById(it) } - * - * val res2 = listOf(1, 2, 3, 4, 5) - * .parTraverseValidated(Dispatchers.IO, Semigroup.nonEmptyList()) { getUserById(it) } - * //sampleEnd - * println(res) - * println(res2) - * } - * ``` - * - */ -@Deprecated( - "Prefer using more generic parMapOrAccumulate. Remove the semigroup parameter if using NonEmptyList, or concrete combine function otherwise.", - ReplaceWith( - "with, Validated>>(semigroup) { this.parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() }", - "arrow.fx.coroutines.parMapOrAccumulate", - "arrow.core.Validated" - ) -) -public suspend fun Iterable.parTraverseValidated( - ctx: CoroutineContext = EmptyCoroutineContext, - semigroup: Semigroup, - f: suspend CoroutineScope.(A) -> Validated -): Validated> = with(semigroup) { - parMapOrAccumulate(ctx, { a, b -> a.combine(b) }) { f(it).bind() }.toValidated() -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZip.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZip.kt index aef614128b9..46a86a257bc 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZip.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZip.kt @@ -1,3 +1,5 @@ +@file:Suppress("UNCHECKED_CAST") + package arrow.fx.coroutines import kotlinx.coroutines.CoroutineScope diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZipOrAccumulate.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZipOrAccumulate.kt index 08e17606308..3a7ea2104b7 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZipOrAccumulate.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/ParZipOrAccumulate.kt @@ -14,44 +14,44 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline combine: (E, E) -> E, crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, - crossinline f: suspend CoroutineScope.(A, B) -> C + crossinline transform: suspend CoroutineScope.(A, B) -> C ): C = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, crossinline combine: (E, E) -> E, crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, - crossinline f: suspend CoroutineScope.(A, B) -> C + crossinline transform: suspend CoroutineScope.(A, B) -> C ): C = parZip( context, { either { fa(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fb(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b -> - Either.zipOrAccumulate(a, b) { aa, bb -> f(aa, bb) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b) { aa, bb -> transform(aa, bb) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, - crossinline f: suspend CoroutineScope.(A, B) -> C + crossinline transform: suspend CoroutineScope.(A, B) -> C ): C = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, - crossinline f: suspend CoroutineScope.(A, B) -> C + crossinline transform: suspend CoroutineScope.(A, B) -> C ): C = parZip( context, { either { fa(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fb(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b -> - Either.zipOrAccumulate(a, b) { aa, bb -> f(aa, bb) }.bind() + Either.zipOrAccumulate(a, b) { aa, bb -> transform(aa, bb) }.bind() } //endregion @@ -61,9 +61,9 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, - crossinline f: suspend CoroutineScope.(A, B, C) -> D + crossinline transform: suspend CoroutineScope.(A, B, C) -> D ): D = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -71,7 +71,7 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, - crossinline f: suspend CoroutineScope.(A, B, C) -> D + crossinline transform: suspend CoroutineScope.(A, B, C) -> D ): D = parZip( context, @@ -79,23 +79,23 @@ public suspend inline fun Raise.parZipOrAccumulate( { either { fb(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fc(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c -> - Either.zipOrAccumulate(a, b, c) { aa, bb, cc -> f(aa, bb, cc) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c) { aa, bb, cc -> transform(aa, bb, cc) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, - crossinline f: suspend CoroutineScope.(A, B, C) -> D + crossinline transform: suspend CoroutineScope.(A, B, C) -> D ): D = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, crossinline fa: suspend ScopedRaiseAccumulate.() -> A, crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, - crossinline f: suspend CoroutineScope.(A, B, C) -> D + crossinline transform: suspend CoroutineScope.(A, B, C) -> D ): D = parZip( context, @@ -103,7 +103,7 @@ public suspend inline fun Raise>.parZipOrAccumul { either { fb(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fc(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c -> - Either.zipOrAccumulate(a, b, c) { aa, bb, cc -> f(aa, bb, cc) }.bind() + Either.zipOrAccumulate(a, b, c) { aa, bb, cc -> transform(aa, bb, cc) }.bind() } //endregion @@ -114,9 +114,9 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, - crossinline f: suspend CoroutineScope.(A, B, C, D) -> F + crossinline transform: suspend CoroutineScope.(A, B, C, D) -> F ): F = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -125,7 +125,7 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, - crossinline f: suspend CoroutineScope.(A, B, C, D) -> F + crossinline transform: suspend CoroutineScope.(A, B, C, D) -> F ): F = parZip( context, @@ -134,7 +134,7 @@ public suspend inline fun Raise.parZipOrAccumulate( { either { fc(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fd(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d -> - Either.zipOrAccumulate(a, b, c, d) { aa, bb, cc, dd -> f(aa, bb, cc, dd) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d) { aa, bb, cc, dd -> transform(aa, bb, cc, dd) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -142,9 +142,9 @@ public suspend inline fun Raise>.parZipOrAccu crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, - crossinline f: suspend CoroutineScope.(A, B, C, D) -> F + crossinline transform: suspend CoroutineScope.(A, B, C, D) -> F ): F = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -152,7 +152,7 @@ public suspend inline fun Raise>.parZipOrAccu crossinline fb: suspend ScopedRaiseAccumulate.() -> B, crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, - crossinline f: suspend CoroutineScope.(A, B, C, D) -> F + crossinline transform: suspend CoroutineScope.(A, B, C, D) -> F ): F = parZip( context, @@ -161,7 +161,7 @@ public suspend inline fun Raise>.parZipOrAccu { either { fc(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fd(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d -> - Either.zipOrAccumulate(a, b, c, d) { aa, bb, cc, dd -> f(aa, bb, cc, dd) }.bind() + Either.zipOrAccumulate(a, b, c, d) { aa, bb, cc, dd -> transform(aa, bb, cc, dd) }.bind() } //endregion @@ -173,9 +173,9 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, - crossinline f: suspend CoroutineScope.(A, B, C, D, F) -> G + crossinline transform: suspend CoroutineScope.(A, B, C, D, F) -> G ): G = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -185,7 +185,7 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, - crossinline f: suspend CoroutineScope.(A, B, C, D, F) -> G + crossinline transform: suspend CoroutineScope.(A, B, C, D, F) -> G ): G = parZip( context, @@ -195,7 +195,7 @@ public suspend inline fun Raise.parZipOrAccumulate( { either { fd(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { ff(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f -> - Either.zipOrAccumulate(a, b, c, d, f) { aa, bb, cc, dd, ff -> f(aa, bb, cc, dd, ff) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d, f) { aa, bb, cc, dd, ff -> transform(aa, bb, cc, dd, ff) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -204,9 +204,9 @@ public suspend inline fun Raise>.parZipOrA crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, - crossinline f: suspend CoroutineScope.(A, B, C, D, F) -> G + crossinline transform: suspend CoroutineScope.(A, B, C, D, F) -> G ): G = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -215,7 +215,7 @@ public suspend inline fun Raise>.parZipOrA crossinline fc: suspend ScopedRaiseAccumulate.() -> C, crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, - crossinline f: suspend CoroutineScope.(A, B, C, D, F) -> G + crossinline transform: suspend CoroutineScope.(A, B, C, D, F) -> G ): G = parZip( context, @@ -225,7 +225,7 @@ public suspend inline fun Raise>.parZipOrA { either { fd(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { ff(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f -> - Either.zipOrAccumulate(a, b, c, d, f) { aa, bb, cc, dd, ff -> f(aa, bb, cc, dd, ff) }.bind() + Either.zipOrAccumulate(a, b, c, d, f) { aa, bb, cc, dd, ff -> transform(aa, bb, cc, dd, ff) }.bind() } //endregion @@ -238,9 +238,9 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G) -> H + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G) -> H ): H = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -251,7 +251,7 @@ public suspend inline fun Raise.parZipOrAccumulate( crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G) -> H + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G) -> H ): H = parZip( context, @@ -262,7 +262,7 @@ public suspend inline fun Raise.parZipOrAccumulate( { either { ff(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fg(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g -> - Either.zipOrAccumulate(a, b, c, d, f, g) { aa, bb, cc, dd, ff, gg -> f(aa, bb, cc, dd, ff, gg) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d, f, g) { aa, bb, cc, dd, ff, gg -> transform(aa, bb, cc, dd, ff, gg) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -272,9 +272,9 @@ public suspend inline fun Raise>.parZip crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G) -> H + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G) -> H ): H = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -284,7 +284,7 @@ public suspend inline fun Raise>.parZip crossinline fd: suspend ScopedRaiseAccumulate.() -> D, crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G) -> H + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G) -> H ): H = parZip( context, @@ -295,7 +295,7 @@ public suspend inline fun Raise>.parZip { either { ff(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fg(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g -> - Either.zipOrAccumulate(a, b, c, d, f, g) { aa, bb, cc, dd, ff, gg -> f(aa, bb, cc, dd, ff, gg) }.bind() + Either.zipOrAccumulate(a, b, c, d, f, g) { aa, bb, cc, dd, ff, gg -> transform(aa, bb, cc, dd, ff, gg) }.bind() } //endregion @@ -309,9 +309,9 @@ public suspend inline fun Raise.parZipOrAccumulat crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I ): I = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -323,7 +323,7 @@ public suspend inline fun Raise.parZipOrAccumulat crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I ): I = parZip( context, @@ -335,7 +335,7 @@ public suspend inline fun Raise.parZipOrAccumulat { either { fg(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fh(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g, h -> - Either.zipOrAccumulate(a, b, c, d, f, g, h) { aa, bb, cc, dd, ff, gg, hh -> f(aa, bb, cc, dd, ff, gg, hh) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d, f, g, h) { aa, bb, cc, dd, ff, gg, hh -> transform(aa, bb, cc, dd, ff, gg, hh) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -346,9 +346,9 @@ public suspend inline fun Raise>.par crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I ): I = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -359,7 +359,7 @@ public suspend inline fun Raise>.par crossinline ff: suspend ScopedRaiseAccumulate.() -> F, crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H) -> I ): I = parZip( context, @@ -371,7 +371,7 @@ public suspend inline fun Raise>.par { either { fg(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fh(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g, h -> - Either.zipOrAccumulate(a, b, c, d, f, g, h) { aa, bb, cc, dd, ff, gg, hh -> f(aa, bb, cc, dd, ff, gg, hh) }.bind() + Either.zipOrAccumulate(a, b, c, d, f, g, h) { aa, bb, cc, dd, ff, gg, hh -> transform(aa, bb, cc, dd, ff, gg, hh) }.bind() } //endregion @@ -386,9 +386,9 @@ public suspend inline fun Raise.parZipOrAccumu crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J ): J = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, fi, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, fi, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -401,7 +401,7 @@ public suspend inline fun Raise.parZipOrAccumu crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J ): J = parZip( context, @@ -414,7 +414,7 @@ public suspend inline fun Raise.parZipOrAccumu { either { fh(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fi(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g, h, i -> - Either.zipOrAccumulate(a, b, c, d, f, g, h, i) { aa, bb, cc, dd, ff, gg, hh, ii -> f(aa, bb, cc, dd, ff, gg, hh, ii) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d, f, g, h, i) { aa, bb, cc, dd, ff, gg, hh, ii -> transform(aa, bb, cc, dd, ff, gg, hh, ii) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -426,9 +426,9 @@ public suspend inline fun Raise>. crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J ): J = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, fi, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, fi, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -440,7 +440,7 @@ public suspend inline fun Raise>. crossinline fg: suspend ScopedRaiseAccumulate.() -> G, crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I) -> J ): J = parZip( context, @@ -453,7 +453,7 @@ public suspend inline fun Raise>. { either { fh(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fi(ScopedRaiseAccumulate(this, this@parZip)) } }, ) { a, b, c, d, f, g, h, i -> - Either.zipOrAccumulate(a, b, c, d, f, g, h, i) { aa, bb, cc, dd, ff, gg, hh, ii -> f(aa, bb, cc, dd, ff, gg, hh, ii) }.bind() + Either.zipOrAccumulate(a, b, c, d, f, g, h, i) { aa, bb, cc, dd, ff, gg, hh, ii -> transform(aa, bb, cc, dd, ff, gg, hh, ii) }.bind() } //endregion @@ -469,9 +469,9 @@ public suspend inline fun Raise.parZipOrAcc crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, crossinline fj: suspend ScopedRaiseAccumulate.() -> J, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K ): K = - parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, fi, fj, f) + parZipOrAccumulate(EmptyCoroutineContext, combine, fa, fb, fc, fd, ff, fg, fh, fi, fj, transform) public suspend inline fun Raise.parZipOrAccumulate( context: CoroutineContext, @@ -485,7 +485,7 @@ public suspend inline fun Raise.parZipOrAcc crossinline fh: suspend ScopedRaiseAccumulate.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, crossinline fj: suspend ScopedRaiseAccumulate.() -> J, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K ): K = parZip( context, @@ -499,7 +499,7 @@ public suspend inline fun Raise.parZipOrAcc { either { fi(ScopedRaiseAccumulate(this, this@parZip)) } }, { either { fj(ScopedRaiseAccumulate(this, this@parZip)) } } ) { a, b, c, d, f, g, h, i, j -> - Either.zipOrAccumulate(a, b, c, d, f, g, h, i, j) { aa, bb, cc, dd, ff, gg, hh, ii, jj -> f(aa, bb, cc, dd, ff, gg, hh, ii, jj) }.getOrElse { raise(it.reduce(combine)) } + Either.zipOrAccumulate(a, b, c, d, f, g, h, i, j) { aa, bb, cc, dd, ff, gg, hh, ii, jj -> transform(aa, bb, cc, dd, ff, gg, hh, ii, jj) }.getOrElse { raise(it.reduce(combine)) } } public suspend inline fun Raise>.parZipOrAccumulate( @@ -512,9 +512,9 @@ public suspend inline fun Raise.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, crossinline fj: suspend ScopedRaiseAccumulate.() -> J, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K ): K = - parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, fi, fj, f) + parZipOrAccumulate(EmptyCoroutineContext, fa, fb, fc, fd, ff, fg, fh, fi, fj, transform) public suspend inline fun Raise>.parZipOrAccumulate( context: CoroutineContext, @@ -527,7 +527,7 @@ public suspend inline fun Raise.() -> H, crossinline fi: suspend ScopedRaiseAccumulate.() -> I, crossinline fj: suspend ScopedRaiseAccumulate.() -> J, - crossinline f: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K + crossinline transform: suspend CoroutineScope.(A, B, C, D, F, G, H, I, J) -> K ): K = parZip( context, @@ -541,6 +541,6 @@ public suspend inline fun Raise - Either.zipOrAccumulate(a, b, c, d, f, g, h, i, j) { aa, bb, cc, dd, ff, gg, hh, ii, jj -> f(aa, bb, cc, dd, ff, gg, hh, ii, jj) }.bind() + Either.zipOrAccumulate(a, b, c, d, f, g, h, i, j) { aa, bb, cc, dd, ff, gg, hh, ii, jj -> transform(aa, bb, cc, dd, ff, gg, hh, ii, jj) }.bind() } //endregion diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Platform.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Platform.kt deleted file mode 100644 index 3509bd6861d..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Platform.kt +++ /dev/null @@ -1,94 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.NonEmptyList -import kotlin.jvm.JvmName - -@Deprecated("Unused, will be removed from binary in 2.x.x") -internal const val ArrowExceptionMessage = - "Arrow-kt internal error. Please let us know and create a ticket at https://github.com/arrow-kt/arrow/issues/new/choose" - -@Deprecated("Unused, will be removed from binary in 2.x.x") -internal class ArrowInternalException(override val message: String = ArrowExceptionMessage) : RuntimeException(message) - -@Deprecated(NicheApi) -public object Platform { - - @Deprecated(NicheApi, ReplaceWith("res.fold({ first }, { e -> first.apply { addSuppressed(e) } })")) - public fun composeErrors(first: Throwable, res: Result): Throwable = - res.fold({ first }, { e -> first.apply { addSuppressed(e) } }) - - /** - * Composes multiple errors together, meant for those cases in which error suppression, due to a second error being - * triggered, is not acceptable. - * - * On top of the JVM this function uses Throwable#addSuppressed, available since Java 7. On top of JavaScript the - * function would return a CompositeException. - */ - @Deprecated(NicheApi, ReplaceWith("first.apply { rest.forEach(::addSuppressed) }")) - public fun composeErrors(first: Throwable, vararg rest: Throwable): Throwable { - rest.forEach { if (it != first) first.addSuppressed(it) } - return first - } - - /** - * Composes multiple errors together, meant for those cases in which error suppression, due to a second error being - * triggered, is not acceptable. - * - * On top of the JVM this function uses Throwable#addSuppressed, available since Java 7. On top of JavaScript the - * function would return a CompositeException. - */ - @Deprecated(NicheApi, ReplaceWith("first.apply { rest.forEach(::addSuppressed) }")) - public fun composeErrors(first: Throwable, rest: List): Throwable { - rest.forEach { if (it != first) first.addSuppressed(it) } - return first - } - - /** - * Composes multiple errors together, meant for those cases in which error suppression, due to a second error being - * triggered, is not acceptable. - * - * On top of the JVM this function uses Throwable#addSuppressed, available since Java 7. On top of JavaScript the - * function would return a CompositeException. - */ - @JvmName("composeErrorsNullable") - @Deprecated(NicheApi, ReplaceWith("first?.apply { other?.let(::addSuppressed) } ?: other")) - public fun composeErrors(first: Throwable?, other: Throwable?): Throwable? = - first?.let { a -> - other?.let { b -> - a.apply { addSuppressed(b) } - } ?: a - } ?: other - - /** - * Composes multiple errors together, meant for those cases in which error suppression, due to a second error being - * triggered, is not acceptable. - * - * On top of the JVM this function uses Throwable#addSuppressed, available since Java 7. On top of JavaScript the - * function would return a CompositeException. - */ - @Deprecated(NicheApi, ReplaceWith("other?.apply { addSuppressed(first) } ?: first")) - public fun composeErrors(first: Throwable, other: Throwable?): Throwable = - other?.let { a -> - a.apply { addSuppressed(first) } - } ?: first - - /** - * Composes multiple errors together, meant for those cases in which error suppression, due to a second error being - * triggered, is not acceptable. - * - * On top of the JVM this function uses Throwable#addSuppressed, available since Java 7. On top of JavaScript the - * function would return a CompositeException. - */ - @Deprecated(NicheApi, ReplaceWith("all.head.apply { all.tail.forEach(::addSuppressed) }")) - public fun composeErrors(all: List): Throwable? = - all.firstOrNull()?.let { first -> - composeErrors(first, all.drop(1)) - } - - @Deprecated(NicheApi, ReplaceWith("all.head.apply { all.tail.forEach(::addSuppressed) }")) - public fun composeErrors(all: NonEmptyList): Throwable = - composeErrors(all.head, all.tail) -} - -private const val NicheApi: String = - "Niche use-case, prefer using higher level operators or addSuppressed from Kotlin Std" diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Race2.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Race2.kt index 49d428462bc..003c405fdb3 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Race2.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Race2.kt @@ -20,11 +20,11 @@ import kotlin.coroutines.EmptyCoroutineContext * ```kotlin * import arrow.core.Either * import arrow.fx.coroutines.* - * import kotlinx.coroutines.suspendCancellableCoroutine + * import kotlinx.coroutines.awaitCancellation * * suspend fun main(): Unit { * suspend fun loser(): Int = - * guaranteeCase({ never() }) { exitCase -> + * guaranteeCase({ awaitCancellation() }) { exitCase -> * println("I can never win the race. Finished with $exitCase.") * } * @@ -62,11 +62,11 @@ public suspend inline fun raceN(crossinline fa: suspend CoroutineScope.() * import arrow.core.Either * import arrow.fx.coroutines.* * import kotlinx.coroutines.Dispatchers - * import kotlinx.coroutines.suspendCancellableCoroutine + * import kotlinx.coroutines.awaitCancellation * * suspend fun main(): Unit { * suspend fun loser(): Int = - * guaranteeCase({ never() }) { exitCase -> + * guaranteeCase({ awaitCancellation() }) { exitCase -> * println("I can never win the race. Finished with $exitCase.") * } * diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Resource.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Resource.kt index 368c0436274..618b06634b8 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Resource.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Resource.kt @@ -1,26 +1,28 @@ package arrow.fx.coroutines +import arrow.AutoCloseScope import arrow.atomic.update import arrow.atomic.Atomic +import arrow.atomic.value import arrow.core.identity import arrow.core.prependTo -import arrow.core.zip import arrow.fx.coroutines.ExitCase.Cancelled import arrow.fx.coroutines.ExitCase.Companion.ExitCase import arrow.fx.coroutines.ExitCase.Completed import arrow.fx.coroutines.ExitCase.Failure -import arrow.fx.coroutines.continuations.AcquireStep -import arrow.fx.coroutines.continuations.ScopeDSL +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.withContext -import kotlin.coroutines.CoroutineContext -import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmInline -public typealias ResourceScope = arrow.fx.coroutines.continuations.ResourceScope +@DslMarker +public annotation class ScopeDSL + +@DslMarker +public annotation class ResourceDSL /** * [Resource] models resource allocation and releasing. It is especially useful when multiple resources that depend on each other need to be acquired and later released in reverse order. @@ -213,6 +215,8 @@ public typealias ResourceScope = arrow.fx.coroutines.continuations.ResourceScope * val userProcessor2: Resource = resource({ * UserProcessor().also { it.start() } * }) { processor, _ -> processor.shutdown() } + * + * val userProcessor3: Resource = ResourceScope::userProcessor * ``` * * @@ -275,871 +279,220 @@ public typealias ResourceScope = arrow.fx.coroutines.continuations.ResourceScope * If you don't need a data-type like [Resource] but want a function alternative to `try/catch/finally` with automatic error composition, * and automatic [NonCancellable] `acquire` and `release` steps use [bracketCase] or [bracket]. **/ -public sealed class Resource { - - /** - * Use the created resource - * When done will run all finalizers - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * class DataSource { - * fun connect(): Unit = println("Connecting dataSource") - * fun users(): List = listOf("User-1", "User-2", "User-3") - * fun close(): Unit = println("Closed dataSource") - * } - * - * suspend fun main(): Unit { - * val dataSource = resource { - * DataSource().also { it.connect() } - * } release DataSource::close - * - * val res = dataSource - * .use { ds -> "Using data source: ${ds.users()}" } - * .also(::println) - * } - * ``` - * - */ - @Suppress("UNCHECKED_CAST") - public tailrec suspend infix fun use(f: suspend (A) -> B): B = - when (this) { - is Dsl -> { - val effect = ResourceScopeImpl() - val b = try { - val a = dsl(effect) - f(a) - } catch (e: Throwable) { - val ee = withContext(NonCancellable) { - effect.finalizers.get().cancelAll(ExitCase(e), e) ?: e - } - throw ee - } - withContext(NonCancellable) { - effect.finalizers.get().cancelAll(ExitCase.Completed)?.let { throw it } - } - b - } - - is Allocate -> bracketCase(acquire, f, release) - is Bind<*, *> -> Dsl { - val any = source.bind() - val ff = this@Resource.f as (Any?) -> Resource - ff(any).bind() - }.use(f) - - is Defer -> resource().use(f) - } - - @Deprecated( - "map $nextVersionRemoved", - ReplaceWith( - "resource { f(bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public fun map(f: suspend (A) -> B): Resource = - resource { f(bind()) } - - /** Useful for setting up/configuring an acquired resource */ - @Deprecated( - "tap $nextVersionRemoved", - ReplaceWith( - "resource { bind().also { f(it) } }", - "arrow.fx.coroutines.resource" - ) - ) - public fun tap(f: suspend (A) -> Unit): Resource = - resource { bind().also { f(it) } } - - @Deprecated( - "ap $nextVersionRemoved", - ReplaceWith( - "resource { bind().let { a -> ff.bind().invoke(a) } }", - "arrow.fx.coroutines.resource" - ) - ) - public fun ap(ff: Resource<(A) -> B>): Resource = - resource { bind().let { a -> ff.bind().invoke(a) } } - - /** - * Create a resource value of [B] from a resource [A] by mapping [f]. - * - * Useful when there is a need to create resources that depend on other resources, - * for combining independent values [zip] provides nicer syntax without the need for callback nesting. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * object Connection - * class DataSource { - * fun connect(): Unit = println("Connecting dataSource") - * fun connection(): Connection = Connection - * fun close(): Unit = println("Closed dataSource") - * } - * - * class Database(private val database: DataSource) { - * fun init(): Unit = println("Database initialising . . .") - * fun shutdown(): Unit = println("Database shutting down . . .") - * } - * - * suspend fun main(): Unit { - * val dataSource = resource { - * DataSource().also { it.connect() } - * } release DataSource::close - * - * fun database(ds: DataSource): Resource = - * resource { - * Database(ds).also(Database::init) - * } release Database::shutdown - * - * dataSource.flatMap(::database) - * .use { println("Using database which uses dataSource") } - * } - * ``` - * - * - * @see zip to combine independent resources together - * @see parZip for combining independent resources in parallel - */ - - @Deprecated( - "flatMap $nextVersionRemoved", - ReplaceWith( - "resource { f(this.bind()).bind() }", - "arrow.fx.coroutines.resource" - ) - ) - public fun flatMap(f: (A) -> Resource): Resource = - resource { f(bind()).bind() } +public typealias Resource = suspend ResourceScope.() -> A - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { combine(this.bind(), other.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip(other: Resource, crossinline combine: (A, B) -> C): Resource = - resource { combine(bind(), other.bind()) } +/** + * This Marker exists to prevent being able to call `bind` from `install`, and its derived methods. + * This is done to ensure correct usage of [ResourceScope]. + */ +@ResourceDSL +public object AcquireStep - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { Pair(this.bind(), other.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public fun zip(other: Resource): Resource> = - zip(other, ::Pair) +@ResourceDSL +public interface ResourceScope : AutoCloseScope { /** - * Combines two independent resource values with the provided [map] function, - * returning the resulting immutable [Resource] value. - * The finalizers run in order of left to right by using [flatMap] under the hood, - * but [zip] provides a nicer syntax for combining values that don't depend on each-other. - * - * Useful to compose up to 9 independent resources, - * see example for more details on how to use in code. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * class UserProcessor { - * fun start(): Unit = println("Creating UserProcessor") - * fun shutdown(): Unit = println("Shutting down UserProcessor") - * fun process(ds: DataSource): List = - * ds.users().map { "Processed $it" } - * } - * - * class DataSource { - * fun connect(): Unit = println("Connecting dataSource") - * fun users(): List = listOf("User-1", "User-2", "User-3") - * fun close(): Unit = println("Closed dataSource") - * } - * - * class Service(val db: DataSource, val userProcessor: UserProcessor) { - * suspend fun processData(): List = userProcessor.process(db) - * } - * - * val userProcessor = resource { - * UserProcessor().also(UserProcessor::start) - * } release UserProcessor::shutdown - * - * val dataSource = resource { - * DataSource().also { it.connect() } - * } release DataSource::close - * - * suspend fun main(): Unit { - * userProcessor.zip(dataSource) { userProcessor, ds -> - * Service(ds, userProcessor) - * }.use { service -> service.processData() } - * } - * ``` - * - * - * @see parZip if you want to combine independent resources in parallel - * @see flatMap to combine resources that rely on each-other. + * Compose another [Resource] program into this [ResourceScope]. + * All [release] functions [install]ed into the [Resource] lambda will be installed in this [ResourceScope] while respecting the FIFO order. */ - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - crossinline map: (A, B, C) -> D, - ): Resource = - resource { map(bind(), b.bind(), c.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - crossinline map: (A, B, C, D) -> E, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind(), e.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - crossinline map: (A, B, C, D, E) -> G, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind()) } - - @Deprecated( - "This method will be removed in Arrow 2.x.x in favor of the DSL", - ReplaceWith( - "zip $nextVersionRemoved", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - f: Resource, - crossinline map: (A, B, C, D, E, F) -> G, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - f: Resource, - g: Resource, - crossinline map: (A, B, C, D, E, F, G) -> H, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - f: Resource, - g: Resource, - h: Resource, - crossinline map: (A, B, C, D, E, F, G, H) -> I, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - f: Resource, - g: Resource, - h: Resource, - i: Resource, - crossinline map: (A, B, C, D, E, F, G, H, I) -> J, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind()) } - - @Deprecated( - "zip $nextVersionRemoved", - ReplaceWith( - "resource { map(this.bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public inline fun zip( - b: Resource, - c: Resource, - d: Resource, - e: Resource, - f: Resource, - g: Resource, - h: Resource, - i: Resource, - j: Resource, - crossinline map: (A, B, C, D, E, F, G, H, I, J) -> K, - ): Resource = - resource { map(bind(), b.bind(), c.bind(), d.bind(), e.bind(), f.bind(), g.bind(), h.bind(), i.bind(), j.bind()) } - - @Deprecated( - "parZip $nextVersionRemoved", - ReplaceWith( - "resource { parZip({ this.bind() }, { fb.bind() }) { a, b -> f(a, b) } }", - "arrow.fx.coroutines.resource" - ) - ) - public fun parZip(fb: Resource, f: suspend (A, B) -> C): Resource = - resource { parZip({ bind() }, { fb.bind() }) { a, b -> f(a, b) } } - + @ResourceDSL + public suspend fun Resource.bind(): A /** - * Composes two [Resource]s together by zipping them in parallel, - * by running both their `acquire` handlers in parallel, and both `release` handlers in parallel. - * - * Useful in the case that starting a resource takes considerable computing resources or time. - * - * ```kotlin - * import arrow.fx.coroutines.* - * import kotlinx.coroutines.delay - * - * class UserProcessor { - * suspend fun start(): Unit { delay(750); println("Creating UserProcessor") } - * fun shutdown(): Unit = println("Shutting down UserProcessor") - * fun process(ds: DataSource): List = - * ds.users().map { "Processed $it" } - * } - * - * class DataSource { - * suspend fun connect(): Unit { delay(1000); println("Connecting dataSource") } - * fun users(): List = listOf("User-1", "User-2", "User-3") - * fun close(): Unit = println("Closed dataSource") - * } - * - * class Service(val db: DataSource, val userProcessor: UserProcessor) { - * suspend fun processData(): List = userProcessor.process(db) - * } - * - * val userProcessor = resource { - * UserProcessor().also { it.start() } - * } release UserProcessor::shutdown - * - * val dataSource = resource { - * DataSource().also { it.connect() } - * } release DataSource::close - * - * suspend fun main(): Unit { - * userProcessor.parZip(dataSource) { userProcessor, ds -> - * Service(ds, userProcessor) - * }.use { service -> service.processData() } - * } - * ``` - * + * Install [A] into the [ResourceScope]. + * It's [release] function will be called with the appropriate [ExitCase] if this [ResourceScope] finishes. + * It results either in [ExitCase.Completed], [ExitCase.Cancelled] or [ExitCase.Failure] depending on the terminal state of [Resource] lambda. */ - @Deprecated( - "parZip $nextVersionRemoved", - ReplaceWith( - "resource { parZip(ctx, { this.bind() }, { fb.bind() }) { a, b -> f(a, b) } }", - "arrow.fx.coroutines.resource" - ) - ) - public fun parZip( - ctx: CoroutineContext = Dispatchers.Default, - fb: Resource, - f: suspend (A, B) -> C, - ): Resource = - resource { - parZip(ctx, { this@Resource.bind() }, { fb.bind() }) { a, b -> f(a, b) } - } - - @Deprecated("Use the safer version allocate instead.") - @DelicateCoroutinesApi - public suspend fun allocated(): Pair A, suspend (@UnsafeVariance A, ExitCase) -> Unit> = - when (this) { - is Bind<*, A> -> - Dsl { - val any = source.bind() - val ff = f as (Any?) -> Resource - ff(any).bind() - }.allocated() - - is Allocate -> acquire to release - is Defer -> resource().allocated() - is Dsl -> { - val effect = ResourceScopeImpl() - val allocated = try { - val allocate: suspend () -> A = suspend { dsl(effect) } - val release: suspend (A, ExitCase) -> Unit = { _, e -> - effect.finalizers.get().cancelAll(e)?.let { throw it } - } - allocate to release - } catch (e: Throwable) { - val ee = withContext(NonCancellable) { - effect.finalizers.get().cancelAll(ExitCase(e), e) ?: e - } - throw ee - } - allocated - } - } - - /** - * Deconstruct [Resource] into an [A] and a `release` handler. - * The `release` action **must** always be called, if never called, then the resource [A] will leak. - * The `release` step is already made `NonCancellable` to guarantee correct invocation like `Resource` or `bracketCase`, - * and it will automatically rethrow, and compose, the exceptions as needed. - * - * ```kotlin - * import arrow.fx.coroutines.* - * import arrow.fx.coroutines.ExitCase.Companion.ExitCase - * - * val resource = - * resource({ "Acquire" }) { _, exitCase -> println("Release $exitCase") } - * - * suspend fun main(): Unit { - * val (acquired: String, release: suspend (ExitCase) -> Unit) = resource.allocate() - * try { - * /** Do something with A */ - * release(ExitCase.Completed) - * } catch(e: Throwable) { - * release(ExitCase(e)) - * } - * } - * ``` - * - * - * This is a **delicate** API. It is easy to accidentally create resource or memory leaks `allocated` is used. - * A `Resource` allocated by `allocate` is not subject to the guarantees that [Resource] makes, - * instead the caller is responsible for correctly invoking the `release` handler at the appropriate time. - * This API is useful for building inter-op APIs between [Resource] and non-suspending code, such as Java libraries. - */ - @DelicateCoroutinesApi - public suspend fun allocate(): Pair Unit> = - when (this) { - is Bind<*, A> -> - Dsl { - val any = source.bind() - val ff = f as (Any?) -> Resource - ff(any).bind() - }.allocate() - - is Allocate -> { - val a = acquire() - Pair(a) { exitCase -> release(a, exitCase) } - } - - is Defer -> resource().allocate() - is Dsl -> { - val effect = ResourceScopeImpl() - val allocated: A = dsl(effect) - val release: suspend (ExitCase) -> Unit = { e -> - val suppressed: Throwable? = effect.finalizers.get().cancelAll(e) - val original: Throwable? = when (e) { - ExitCase.Completed -> null - is ExitCase.Cancelled -> e.exception - is ExitCase.Failure -> e.failure - } - Platform.composeErrors(original, suppressed)?.let { throw it } - } - Pair(allocated, release) - } - } - - @Deprecated( - "Bind $nextVersionRemoved", - ReplaceWith( - "resource { f(source.bind()) }", - "arrow.fx.coroutines.resource" - ) - ) - public class Bind(public val source: Resource, public val f: (A) -> Resource) : Resource() - - @Deprecated( - "Allocate $nextVersionRemoved", - ReplaceWith( - "resource(acquire, release)", - "arrow.fx.coroutines.resource" - ) - ) - public class Allocate( - public val acquire: suspend () -> A, - public val release: suspend (A, ExitCase) -> Unit, - ) : Resource() - - @Deprecated( - "Defer $nextVersionRemoved", - ReplaceWith( - "resource { resource.invoke().bind() }", - "arrow.fx.coroutines.resource" - ) - ) - public class Defer(public val resource: suspend () -> Resource) : Resource() - - @Deprecated( - "Dsl $nextVersionRemoved", - ReplaceWith( - "resource { dsl() }", - "arrow.fx.coroutines.resource" - ) - ) - public data class Dsl(public val dsl: suspend ResourceScope.() -> A) : Resource() - - public companion object { - - @PublishedApi - @Deprecated("This will be removed from the binary in Arrow 2.0", level = DeprecationLevel.ERROR) - internal val unit: Resource = just(Unit) - - /** - * Construct a [Resource] from an allocating function [acquire] and a release function [release]. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun acquireResource(): Int = 42.also { println("Getting expensive resource") } - * suspend fun releaseResource(r: Int, exitCase: ExitCase): Unit = println("Releasing expensive resource: $r, exit: $exitCase") - * - * suspend fun main(): Unit { - * val resource = Resource(::acquireResource, ::releaseResource) - * resource.use { - * println("Expensive resource under use! $it") - * } - * } - * ``` - * - */ - @Deprecated( - "Operator invoke is replaced with top-level function", - ReplaceWith( - "resource(acquire, release)", - "arrow.fx.coroutines.resource" - ) - ) - public operator fun invoke( - acquire: suspend () -> A, - release: suspend (A, ExitCase) -> Unit, - ): Resource = Allocate(acquire, release) - - /** - * Create a [Resource] from a pure value [A]. - */ - @Deprecated( - "Use the resource DSL to create Resource values. Will be removed in Arrow 2.x.x", - ReplaceWith( - "resource { r }", - "arrow.fx.coroutines.resource" - ) - ) - public fun just(r: A): Resource = - Resource({ r }, { _, _ -> Unit }) + @ResourceDSL + public suspend fun install( + acquire: suspend AcquireStep.() -> A, + release: suspend (A, ExitCase) -> Unit, + ): A + + /** Composes a [release] action to a [Resource] value before binding. */ + @ResourceDSL + public suspend infix fun Resource.release(release: suspend (A) -> Unit): A { + val a = bind() + return install({ a }) { aa, _ -> release(aa) } + } - @Deprecated( - "defer is being deprecated. Use resource DSL instead", - ReplaceWith( - "resource { f().bind() }", - "arrow.fx.coroutines.resource" - ) - ) - public fun defer(f: suspend () -> Resource): Resource = - Resource.Defer(f) + /** Composes a [releaseCase] action to a [Resource] value before binding. */ + @ResourceDSL + public suspend infix fun Resource.releaseCase(release: suspend (A, ExitCase) -> Unit): A { + val a = bind() + return install({ a }, release) } -} -public fun resource( - acquire: suspend () -> A, - release: suspend (A, ExitCase) -> Unit, -): Resource = resource { - install({ acquire() }, release) + public suspend infix fun onRelease(release: suspend (ExitCase) -> Unit): Unit = + install({ }) { _, exitCase -> release(exitCase) } } @ScopeDSL -public suspend fun resourceScope(action: suspend ResourceScope.() -> A): A = - resource(action).use(::identity) +public fun resource(block: suspend ResourceScope.() -> A): Resource = block /** - * Marker for `suspend () -> A` to be marked as the [Use] action of a [Resource]. - * Offers a convenient DSL to use [Resource] for simple resources. + * The [resourceScope] function creates the [ResourceScope] instances, + * runs the user [action] while allocating the _installed_ resources. + * upon [ExitCase.Completed], [ExitCase.Cancelled] or [ExitCase.Failure] runs all the `release` finalizers. * - * ```kotlin - * import arrow.fx.coroutines.* + * + * ```kotlin + * suspend fun main(): Unit = resourceScope { + * val dataSource = install({ + * DataSource().also { it.connect() } + * }) { ds, _ -> ds.close() } * - * suspend fun openFile(uri: String): File = File(uri).open() - * suspend fun closeFile(file: File): Unit = file.close() - * suspend fun fileToString(file: File): String = file.toString() - * - * suspend fun main(): Unit { - * val res = resource { - * openFile("data.json") - * } release { file -> - * closeFile(file) - * } use { file -> - * fileToString(file) - * } - * - * println(res) + * println("Using data source: ${dataSource.users()}") * } * ``` - * + * */ -@Deprecated( - "Use the resource computation DSL instead", - ReplaceWith( - "resource { acquire() }", - "arrow.fx.coroutines.resource" - ) -) -public inline class Use(internal val acquire: suspend () -> A) - -/** - * Marks an [acquire] operation as the [Resource.use] step of a [Resource]. - */ -@Deprecated( - "Use the resource computation DSL instead", - ReplaceWith( - "resource { acquire() }", - "arrow.fx.coroutines.resource" - ), - level = DeprecationLevel.HIDDEN -) -public fun resource(acquire: suspend () -> A): Use = Use(acquire) - @ScopeDSL -public fun resource(action: suspend ResourceScope.() -> A): Resource = - arrow.fx.coroutines.continuations.resource(action) - -@Deprecated("Use the resource computation DSL instead") -public infix fun Use.release(release: suspend (A) -> Unit): Resource = - Resource(acquire) { a, _ -> release(a) } - -/** - * Composes a [release] action to a [Resource.use] action creating a [Resource]. - */ -public infix fun Resource.release(release: suspend (A) -> Unit): Resource = - resource { - val a = bind() - Resource({ a }, { _, _ -> release(a) }).bind() +public suspend fun resourceScope(action: suspend ResourceScope.() -> A): A { + val scope = ResourceScopeImpl() + val a: A = try { + action(scope) + } catch (e: Throwable) { + val ex = if (e is CancellationException) ExitCase.Cancelled(e) else ExitCase.Failure(e) + val ee = withContext(NonCancellable) { + scope.cancelAll(ex, e) ?: e + } + throw ee } - -@Deprecated("Use the resource computation DSL instead") -public infix fun Use.releaseCase(release: suspend (A, ExitCase) -> Unit): Resource = - Resource(acquire, release) - -/** - * Composes a [releaseCase] action to a [Resource.use] action creating a [Resource]. - */ -public infix fun Resource.releaseCase(release: suspend (A, ExitCase) -> Unit): Resource = - resource { - val a = bind() - Resource({ a }, { _, ex -> release(a, ex) }).bind() + withContext(NonCancellable) { + scope.cancelAll(ExitCase.Completed)?.let { throw it } } + return a +} -@Deprecated("traverseResource is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(f)")) -public inline fun Iterable.traverseResource(crossinline f: (A) -> Resource): Resource> = - resource { - map { a -> - f(a).bind() - } - } +public suspend infix fun Resource.use(f: suspend (A) -> B): B = + resourceScope { f(bind()) } /** - * Traverse this [Iterable] and collects the resulting `Resource` of [f] into a `Resource>`. + * Construct a [Resource] from an allocating function [acquire] and a release function [release]. * * ```kotlin - * import arrow.fx.coroutines.* - * - * class File(url: String) { - * suspend fun open(): File = this - * suspend fun close(): Unit {} - * override fun toString(): String = "This file contains some interesting content!" - * } - * - * suspend fun openFile(uri: String): File = File(uri).open() - * suspend fun closeFile(file: File): Unit = file.close() - * suspend fun fileToString(file: File): String = file.toString() + * import arrow.fx.coroutines.resource + * import arrow.fx.coroutines.resourceScope * - * suspend fun main(): Unit { - * val res: List = listOf( - * "data.json", - * "user.json", - * "resource.json" - * ).traverse { uri -> - * resource { - * openFile(uri) - * } release { file -> - * closeFile(file) - * } - * }.use { files -> - * files.map { fileToString(it) } + * val resource = resource { + * install({ 42.also { println("Getting expensive resource") } }) { r, exitCase -> + * println("Releasing expensive resource: $r, exit: $exitCase") * } - * res.forEach(::println) * } - * ``` - * - */ -@Deprecated( - "Use the resource computation DSL instead", - ReplaceWith( - "resource { map { a -> f(a).bind() } }", - "arrow.fx.coroutines.resource" - ) -) -@OptIn(ExperimentalTypeInference::class) -@OverloadResolutionByLambdaReturnType -public inline fun Iterable.traverse(crossinline f: (A) -> Resource): Resource> = - resource { map { a -> f(a).bind() } } - -/** - * Sequences this [Iterable] of [Resource]s. - * [Iterable.map] and [sequence] is equivalent to [traverse]. * - * ```kotlin - * import arrow.fx.coroutines.* - * - * class File(url: String) { - * suspend fun open(): File = this - * suspend fun close(): Unit {} - * override fun toString(): String = "This file contains some interesting content!" - * } - * - * suspend fun openFile(uri: String): File = File(uri).open() - * suspend fun closeFile(file: File): Unit = file.close() - * suspend fun fileToString(file: File): String = file.toString() - * - * suspend fun main(): Unit { - * val res: List = listOf( - * "data.json", - * "user.json", - * "resource.json" - * ).map { uri -> - * resource { - * openFile(uri) - * } release { file -> - * closeFile(file) - * } - * }.sequence().use { files -> - * files.map { fileToString(it) } - * } - * res.forEach(::println) + * suspend fun main(): Unit = resourceScope { + * val res = resource.bind() + * println("Expensive resource under use! $res") * } * ``` - * + * */ -@Deprecated( - "Use the resource computation DSL instead", - ReplaceWith( - "resource { map { a -> a.bind() } }", - "arrow.fx.coroutines.resource" - ) -) -@Suppress("NOTHING_TO_INLINE") -public inline fun Iterable>.sequence(): Resource> = - resource { map { a -> a.bind() } } +public fun resource( + acquire: suspend () -> A, + release: suspend (A, ExitCase) -> Unit, +): Resource = resource { + install({ acquire() }, release) +} /** * Runs [Resource.use] and emits [A] of the resource * * ```kotlin * import arrow.fx.coroutines.* + * import kotlinx.coroutines.* + * import kotlinx.coroutines.flow.* + * import java.nio.file.Path + * import kotlin.io.path.* * * fun Flow.writeAll(path: Path): Flow = - * Resource.fromCloseable { path.toFile().outputStream() } + * closeable { path.toFile().outputStream() } * .asFlow() - * .flatMapConcat { writer -> byteFlow.map { writer.write(it) } } + * .flatMapConcat { writer -> map { writer.write(it) } } * .flowOn(Dispatchers.IO) * * fun Path.readAll(): Flow = flow { - * path.useLines { lines -> emitAll(lines) } + * useLines { lines -> emitAll(lines.asFlow()) } * } * - * Path("example.kt") - * .readAll() - * . + * suspend fun main() { + * Path("example.kt") + * .readAll() + * .collect(::println) + * } * ``` + * */ public fun Resource.asFlow(): Flow = flow { - use { - emit(it) + resourceScope { + emit(bind()) } } -private class ResourceScopeImpl : ResourceScope { - val finalizers: Atomic Unit>> = Atomic(emptyList()) - override suspend fun Resource.bind(): A = - when (this) { - is Resource.Dsl -> dsl.invoke(this@ResourceScopeImpl) - is Resource.Allocate -> bracketCase({ - val a = acquire() - val finalizer: suspend (ExitCase) -> Unit = { ex: ExitCase -> release(a, ex) } - finalizers.update(finalizer::prependTo) - a - }, ::identity, { a, ex -> - // Only if ExitCase.Failure, or ExitCase.Cancelled during acquire we cancel - // Otherwise we've saved the finalizer, and it will be called from somewhere else. - if (ex != ExitCase.Completed) { - val e = finalizers.get().cancelAll(ex) - val e2 = runCatching { release(a, ex) }.exceptionOrNull() - (e?.apply { e2?.let(::addSuppressed) } ?: e2)?.let { throw it } - } - }) - - is Resource.Bind<*, *> -> { - val dsl: suspend ResourceScope.() -> A = { - val any = source.bind() - val ff = f as (Any?) -> Resource - ff(any).bind() - } - dsl(this@ResourceScopeImpl) - } - - is Resource.Defer -> resource().bind() +/** + * Deconstruct [Resource] into an [A] and a `release` handler. + * The `release` action **must** always be called, if never called, then the resource [A] will leak. + * The `release` step is already made `NonCancellable` to guarantee correct invocation like `Resource` or `bracketCase`, + * and it will automatically rethrow, and compose, the exceptions as needed. + * + * ```kotlin + * import arrow.fx.coroutines.* + * import arrow.fx.coroutines.ExitCase.Companion.ExitCase + * + * val resource = + * resource({ "Acquire" }) { _, exitCase -> println("Release $exitCase") } + * + * suspend fun main(): Unit { + * val (acquired: String, release: suspend (ExitCase) -> Unit) = resource.allocated() + * try { + * /** Do something with A */ + * release(ExitCase.Completed) + * } catch(e: Throwable) { + * release(ExitCase(e)) + * } + * } + * ``` + * + * + * This is a **delicate** API. It is easy to accidentally create resource or memory leaks `allocated` is used. + * A `Resource` allocated by `allocated` is not subject to the guarantees that [Resource] makes, + * instead the caller is responsible for correctly invoking the `release` handler at the appropriate time. + * This API is useful for building inter-op APIs between [Resource] and non-suspending code, such as Java libraries. + */ +@DelicateCoroutinesApi +public suspend fun Resource.allocated(): Pair Unit> { + val effect = ResourceScopeImpl() + val allocated: A = invoke(effect) + val release: suspend (ExitCase) -> Unit = { e -> + val suppressed: Throwable? = effect.cancelAll(e) + val original: Throwable? = when(e) { + ExitCase.Completed -> null + is ExitCase.Cancelled -> e.exception + is ExitCase.Failure -> e.failure } + original?.apply { + suppressed?.let(::addSuppressed) + }?.let { throw it } + } + return Pair(allocated, release) +} +@JvmInline +private value class ResourceScopeImpl( + private val finalizers: Atomic Unit>> = Atomic(emptyList()), +) : ResourceScope { + override suspend fun Resource.bind(): A = invoke(this@ResourceScopeImpl) + override suspend fun install(acquire: suspend AcquireStep.() -> A, release: suspend (A, ExitCase) -> Unit): A = bracketCase({ val a = acquire(AcquireStep) @@ -1150,9 +503,11 @@ private class ResourceScopeImpl : ResourceScope { // Only if ExitCase.Failure, or ExitCase.Cancelled during acquire we cancel // Otherwise we've saved the finalizer, and it will be called from somewhere else. if (ex != ExitCase.Completed) { - val e = finalizers.get().cancelAll(ex) + val e = cancelAll(ex) val e2 = kotlin.runCatching { release(a, ex) }.exceptionOrNull() - Platform.composeErrors(e, e2)?.let { throw it } + e?.apply { + e2?.let(::addSuppressed) + }?.let { throw it } } }) @@ -1172,18 +527,14 @@ private class ResourceScopeImpl : ResourceScope { } catch (e: Throwable) { throw e } -} -private suspend fun List Unit>.cancelAll( - exitCase: ExitCase, - first: Throwable? = null, -): Throwable? = fold(first) { acc, finalizer -> - val other = kotlin.runCatching { finalizer(exitCase) }.exceptionOrNull() - other?.let { - acc?.apply { addSuppressed(other) } ?: other - } ?: acc + suspend fun cancelAll( + exitCase: ExitCase, + first: Throwable? = null, + ): Throwable? = finalizers.value.fold(first) { acc, finalizer -> + val other = kotlin.runCatching { finalizer(exitCase) }.exceptionOrNull() + other?.let { + acc?.apply { addSuppressed(other) } ?: other + } ?: acc + } } - -@PublishedApi internal const val nextVersionRemoved: String = - "is redundant and will be removed in Arrow 2.x.x in favor of the DSL.\n" + - "In case you think this method should stay, please provide feedback and your use-case on https://github.com/arrow-kt/arrow/issues" diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Schedule.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Schedule.kt deleted file mode 100644 index 4258e466ea4..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/Schedule.kt +++ /dev/null @@ -1,1139 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.Either -import arrow.core.Eval -import arrow.core.NicheAPI -import arrow.core.identity -import arrow.core.left -import arrow.core.merge -import arrow.core.nonFatalOrThrow -import arrow.core.right -import arrow.fx.coroutines.Schedule.ScheduleImpl -import kotlinx.coroutines.delay -import kotlinx.coroutines.ensureActive -import kotlin.coroutines.coroutineContext -import kotlin.jvm.JvmName -import kotlin.math.max -import kotlin.math.min -import kotlin.math.pow -import kotlin.math.roundToInt -import kotlin.random.Random -import kotlin.time.Duration -import kotlin.time.ExperimentalTime -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.retry -import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.DurationUnit.NANOSECONDS - -/** - * # Retrying and repeating effects - * - * A common demand when working with effects is to retry or repeat them when certain circumstances happen. Usually, the retrial or repetition does not happen right away; rather, it is done based on a policy. For instance, when fetching content from a network request, we may want to retry it when it fails, using an exponential backoff algorithm, for a maximum of 15 seconds or 5 attempts, whatever happens first. - * - * [Schedule] allows you to define and compose powerful yet simple policies, which can be used to either repeat or retry computation. - * - * The two core methods of running a schedule are: - * - __retry__: The effect is executed once, and if it fails, it will be reattempted based on the scheduling policy passed as an argument. It will stop if the effect ever succeeds, or the policy determines it should not be reattempted again. - * - __repeat__: The effect is executed once, and if it succeeds, it will be executed again based on the scheduling policy passed as an argument. It will stop if the effect ever fails, or the policy determines it should not be executed again. It will return the last internal state of the scheduling policy, or the error that happened running the effect. - * - * ## Constructing a policy: - * - * Constructing a simple schedule which recurs 10 times until it succeeds: - * ```kotlin - * import arrow.fx.coroutines.* - * - * fun recurTenTimes() = Schedule.recurs(10) - * ``` - * - * - * A more complex schedule - * - * ```kotlin - * import kotlin.time.Duration.Companion.milliseconds - * import kotlin.time.Duration.Companion.seconds - * import kotlin.time.ExperimentalTime - * import arrow.fx.coroutines.* - * - * @ExperimentalTime - * fun complexPolicy(): Schedule> = - * Schedule.exponential(10.milliseconds).whileOutput { it < 60.seconds } - * .andThen(Schedule.spaced(60.seconds) and Schedule.recurs(100)).jittered() - * .zipRight(Schedule.identity().collect()) - * ``` - * - * - * This policy will recur with exponential backoff as long as the delay is less than 60 seconds and then continue with a spaced delay of 60 seconds. - * The delay is also randomized slightly to avoid coordinated backoff from multiple services. - * Finally we also collect every input to the schedule and return it. When used with [retry] this will return a list of exceptions that occured on failed attempts. - * - * ## Common use cases - * - * Common use cases - * Once we have building blocks and ways to combine them, let’s see how we can use them to solve some use cases. - * - * ### Repeating an effect and dealing with its result - * - * When we repeat an effect, we do it as long as it keeps providing successful results and the scheduling policy tells us to keep recursing. But then, there is a question on what to do with the results provided by each iteration of the repetition. - * - * There are at least 3 possible things we would like to do: - * - * - Discard all results; i.e., return `Unit`. - * - Discard all intermediate results and just keep the last produced result. - * - Keep all intermediate results. - * - * Assuming we have a suspend effect in, and we want to repeat it 3 times after its first successful execution, we can do: - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main(): Unit { - * var counter = 0 - * //sampleStart - * val res = Schedule.recurs(3).repeat { - * println("Run: ${counter++}") - * } - * //sampleEnd - * println(res) - * } - * ``` - * - * - * However, when running this new effect, its output will be the number of iterations it has performed, as stated in the documentation of the function. Also notice that we did not handle the error case, there are overloads [repeatOrElse] and [repeatOrElseEither] which offer that capability, [repeat] will just rethrow any error encountered. - * - * If we want to discard the values provided by the repetition of the effect, we can combine our policy with [Schedule.unit], using the [zipLeft] or [zipRight] combinators, which will keep just the output of one of the policies: - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main(): Unit { - * var counter = 0 - * //sampleStart - * val res = (Schedule.unit() zipLeft Schedule.recurs(3)).repeat { - * println("Run: ${counter++}") - * } - * // equal to - * val res2 = (Schedule.recurs(3) zipRight Schedule.unit()).repeat { - * println("Run: ${counter++}") - * } - * //sampleEnd - * println(res) - * println(res2) - * } - * ``` - * - * - * Following the same strategy, we can zip it with the [Schedule.identity] policy to keep only the last provided result by the effect. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main(): Unit { - * var counter = 0 - * //sampleStart - * val res = (Schedule.identity() zipLeft Schedule.recurs(3)).repeat { - * println("Run: ${counter++}"); counter - * } - * // equal to - * val res2 = (Schedule.recurs(3) zipRight Schedule.identity()).repeat { - * println("Run: ${counter++}"); counter - * } - * //sampleEnd - * println(res) - * println(res2) - * } - * ``` - * - * - * Finally, if we want to keep all intermediate results, we can zip the policy with [Schedule.collect]: - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main(): Unit { - * var counter = 0 - * //sampleStart - * val res = (Schedule.collect() zipLeft Schedule.recurs(3)).repeat { - * println("Run: ${counter++}") - * counter - * } - * // equal to - * val res2 = (Schedule.recurs(3) zipRight Schedule.collect()).repeat { - * println("Run: ${counter++}") - * counter - * } - * //sampleEnd - * println(res) - * println(res2) - * } - * ``` - * - * - * ## Repeating an effect until/while it produces a certain value - * - * We can make use of the policies doWhile or doUntil to repeat an effect while or until its produced result matches a given predicate. - * - * ```kotlin - * import arrow.fx.coroutines.* - * - * suspend fun main(): Unit { - * var counter = 0 - * //sampleStart - * val res = Schedule.doWhile{ it <= 3 }.repeat { - * println("Run: ${counter++}"); counter - * } - * //sampleEnd - * println(res) - * } - * ``` - * - * - * ## Exponential backoff retries - * - * A common algorithm to retry effectful operations, as network requests, is the exponential backoff algorithm. There is a scheduling policy that implements this algorithm and can be used as: - * - * ```kotlin - * import kotlin.time.Duration.Companion.milliseconds - * import kotlin.time.ExperimentalTime - * import arrow.fx.coroutines.* - * - * @ExperimentalTime - * val exponential = Schedule.exponential(250.milliseconds) - * ``` - * - */ -@Deprecated(deprecatedInFavorOfArrowFxResilience, ReplaceWith("Schedule", "arrow.fx.resilience.Schedule")) -public sealed class Schedule { - - public abstract suspend fun repeatOrElseEither( - fa: suspend () -> Input, - orElse: suspend (Throwable, Output?) -> C - ): Either - - /** - * Runs this effect once and, if it succeeded, decide using the provided policy if the effect should be repeated and if so, with how much delay. - * Returns the last output from the policy or raises an error if a repeat failed. - */ - public suspend fun repeat(fa: suspend () -> Input): Output = - repeatOrElse(fa) { e, _ -> throw e } - - /** - * Runs this effect once and, if it succeeded, decide using the provided policy if the effect should be repeated and if so, with how much delay. - * Also offers a function to handle errors if they are encountered during repetition. - */ - public suspend fun repeatOrElse(fa: suspend () -> Input, orElse: suspend (Throwable, Output?) -> Output): Output = - repeatOrElseEither(fa, orElse).fold(::identity, ::identity) - - @Deprecated( - NicheAPI, - ReplaceWith( - "flow> { this.log { _, output -> emit(output.right()) }.repeatOrElseEither(fa) { e, output -> emit(orElse(e, output).left()) } }", - "kotlinx.coroutines.flow.flow", "arrow.core.left", "arrow.core.right" - ) - ) - public abstract suspend fun repeatOrElseEitherAsFlow( - fa: suspend () -> Input, - orElse: suspend (Throwable, Output?) -> C - ): Flow> - - /** - * Runs this effect and emits the output, if it succeeded, decide using the provided policy if the effect should be repeated and emitted, if so, with how much delay. - * This will raise an error if a repeat failed. - */ - @Deprecated( - NicheAPI, - ReplaceWith( - "flow { this.log { _, output -> emit(output) }.repeat(fa) }", - "kotlinx.coroutines.flow.flow" - ) - ) - public suspend fun repeatAsFlow(fa: suspend () -> Input): Flow = - flow { this@Schedule.log { _, output -> emit(output) }.repeat(fa) } - - /** - * Runs this effect and emits the output, if it succeeded, decide using the provided policy if the effect should be repeated and emitted, if so, with how much delay. - * Also offers a function to handle errors if they are encountered during repetition. - */ - @Deprecated( - NicheAPI, - ReplaceWith( - "flow { this.log { _, output -> emit(output) }.repeatOrElseEither(fa) { e, output -> emit(orElse(e, output)) } }", - "kotlinx.coroutines.flow.flow" - ) - ) - public suspend fun repeatOrElseAsFlow( - fa: suspend () -> Input, - orElse: suspend (Throwable, Output?) -> Output - ): Flow = flow { - log { _, output -> emit(output) } - .repeatOrElseEither(fa) { e, output -> emit(orElse(e, output)) } - } - - /** - * Changes the output of a schedule. Does not alter the decision of the schedule. - */ - public abstract fun map(f: (output: Output) -> B): Schedule - - /** - * Changes the input of the schedule. May alter a schedule's decision if it is based on input. - */ - public abstract fun contramap(f: suspend (B) -> Input): Schedule - - /** - * Conditionally checks on both the input and the output whether or not to continue. - */ - @Deprecated( - "Check is being renamed to doWhile in Arrow Resilience", - ReplaceWith("doWhile(pred)") - ) - public abstract fun check(pred: suspend (input: A, output: Output) -> Boolean): Schedule - - public fun doWhile(predicate: suspend (@UnsafeVariance Input, Output) -> Boolean): Schedule = - check(predicate) - - public fun doUntil(predicate: suspend (input: @UnsafeVariance Input, output: Output) -> Boolean): Schedule = - doWhile { input, output -> !predicate(input, output) } - - /** - * Inverts the decision of a schedule. - */ - @Deprecated(NicheAPI) - public abstract operator fun not(): Schedule - - /** - * Combines with another schedule by combining the result and the delay of the [Decision] with the [zipContinue], [zipDuration] and a [zip] functions - */ - @ExperimentalTime - @Deprecated("combine are being deprecated in favor of and & or APIs in Arrow Resilience. $NicheAPI") - public fun combine( - other: Schedule, - zipContinue: (cont: Boolean, otherCont: Boolean) -> Boolean, - zipDuration: (duration: Duration, otherDuration: Duration) -> Duration, - zip: (Output, B) -> C - ): Schedule = - combineNanos(other, zipContinue, { a, b -> zipDuration(a.nanoseconds, b.nanoseconds).toDouble(NANOSECONDS) }, zip) - - /** - * Combines with another schedule by combining the result and the delay of the [Decision] with the functions [zipContinue], [zipDuration] and a [zip] function - */ - @Deprecated("Nano based APIs are being deprecated, and removed in Arrow Resilience. $NicheAPI") - public abstract fun combineNanos( - other: Schedule, - zipContinue: (cont: Boolean, otherCont: Boolean) -> Boolean, - zipDuration: (duration: Double, otherDuration: Double) -> Double, - zip: (Output, B) -> C - ): Schedule - - /** - * Always retries a schedule regardless of the decision made prior to invoking this method. - */ - @Deprecated(NicheAPI) - public abstract fun forever(): Schedule - - /** - * Executes one schedule after the other. When the first schedule ends, it continues with the second. - */ - public abstract infix fun andThen(other: Schedule): Schedule> - - /** - * Changes the delay of a resulting [Decision] based on the [Output] and the produced delay. - * - */ - @ExperimentalTime - @Deprecated( - "modify is being renamed to delayed in Arrow Resilience", - ReplaceWith("delayed(f)") - ) - public fun modify(f: suspend (Output, Duration) -> Duration): Schedule = - modifyNanos { output, d -> f(output, d.nanoseconds).toDouble(NANOSECONDS) } - - @ExperimentalTime - public fun delayed(transform: suspend (Output, Duration) -> Duration): Schedule = - modify(transform) - - @Deprecated( - "Nano based APIs are being deprecated, and removed in Arrow Resilience. Use delayed instead $NicheAPI", - ReplaceWith( - "delayed { output, nanos -> f(output, nanos.nanoseconds) }", - "kotlin.time.Companion.Duration.nanoseconds" - ) - ) - public abstract fun modifyNanos(f: suspend (Output, Double) -> Double): Schedule - - public abstract fun log(action: suspend (input: @UnsafeVariance Input, output: Output) -> Unit): Schedule - - /** - * Runs an effectful handler on every input. Does not alter the decision. - */ - @Deprecated( - "logInput is being replaced to log in Arrow Resilience", - ReplaceWith("log { input, _ -> f(input) }") - ) - public abstract fun logInput(f: suspend (input: Input) -> Unit): Schedule - - /** - * Runs an effectful handler on every output. Does not alter the decision. - */ - @Deprecated( - "logOutput is being replaced to log in Arrow Resilience", - ReplaceWith(" log { _, output -> f(output) }") - ) - public abstract fun logOutput(f: suspend (output: Output) -> Unit): Schedule - - /** - * Accumulates the results of a schedule by folding over them effectfully. - */ - @Deprecated(NicheAPI) - public abstract fun foldLazy( - initial: suspend () -> C, - f: suspend (acc: C, output: Output) -> C - ): Schedule - - /** - * Composes this schedule with the other schedule by piping the output of this schedule - * into the input of the other. - */ - @Deprecated(NicheAPI) - public abstract infix fun pipe(other: Schedule): Schedule - - /** - * Combines two with different input and output using and. Continues when both continue and uses the maximum delay. - */ - @Deprecated(NicheAPI) - public infix fun zip(other: Schedule): Schedule, Pair> = - zip(other, ::Pair) - - /** - * Combines two with different input and output using and. Continues when both continue and uses the maximum delay. - */ - @Deprecated(NicheAPI) - public abstract fun zip(other: Schedule, f: (Output, B) -> C): Schedule, C> - - /** - * Combines two schedules with different input and output and conditionally choose between the two. - * Continues when the chosen schedule continues and uses the chosen schedules delay. - */ - @Deprecated(NicheAPI) - public abstract infix fun choose(other: Schedule): Schedule, Either> - - @Deprecated( - "Use map instead of void. Being removed in Arrow Resilience. $NicheAPI", - ReplaceWith("map { }") - ) - public fun void(): Schedule = - map { Unit } - - /** - * Changes the result of a [Schedule] to always be [b]. - */ - @Deprecated( - "Use const instead of void. Being removed in Arrow Resilience. $NicheAPI", - ReplaceWith("map { b }") - ) - public fun const(b: B): Schedule = - map { b } - - /** - * Continues or stops the schedule based on the output. - */ - @Deprecated( - "whileOutput is being replaced with doWhile in Arrow Resilience.", - ReplaceWith("doWhile { _, output -> f(output) }") - ) - public fun whileOutput(f: suspend (Output) -> Boolean): Schedule = - doWhile { _, output -> f(output) } - - /** - * Continues or stops the schedule based on the input. - */ - @Deprecated( - "whileInput is being replaced with doWhile in Arrow Resilience.", - ReplaceWith("doWhile { input, _ -> f(input) }") - ) - public fun whileInput(f: suspend (A) -> Boolean): Schedule = - check { input, _ -> f(input) } - - /** - * `untilOutput(f) = whileOutput(f).not()` - */ - @Deprecated( - "untilOutput is being replaced with doUntil in Arrow Resilience.", - ReplaceWith("doUntil { _, output -> f(output) }") - ) - public fun untilOutput(f: suspend (Output) -> Boolean): Schedule = - doUntil { _, output -> f(output) } - - /** - * `untilInput(f) = whileInput(f).not()` - */ - @Deprecated( - "untilOutput is being replaced with doUntil in Arrow Resilience.", - ReplaceWith("doUntil { input, _ -> f(input) }") - ) - public fun untilInput(f: suspend (A) -> Boolean): Schedule = - !whileInput(f) - - @Deprecated(NicheAPI) - public fun dimap(f: suspend (B) -> Input, g: (Output) -> C): Schedule = - contramap(f).map(g) - - /** - * Combines two schedules. Continues only when both continue and chooses the maximum delay. - */ - public infix fun and(other: Schedule): Schedule> = - combineNanos(other, { a, b -> a && b }, { a, b -> max(a, b) }, ::Pair) - - /** - * Combines two schedules. Continues if one continues and chooses the minimum delay. - */ - public infix fun or(other: Schedule): Schedule> = - combineNanos(other, { a, b -> a || b }, { a, b -> min(a, b) }, ::Pair) - - /** - * Combines two schedules with [and] but throws away the left schedule's result. - */ - public infix fun zipRight(other: Schedule): Schedule = - (this and other).map(Pair::second) - - /** - * Combines two schedules with [and] but throws away the right schedule's result. - */ - public infix fun zipLeft(other: Schedule): Schedule = - (this and other).map(Pair::first) - - @ExperimentalTime - @Deprecated( - "delay is being replaced with delayed in Arrow Resilience.", - ReplaceWith("delayed { _, duration -> f(duration) }") - ) - public fun delay(f: suspend (duration: Duration) -> Duration): Schedule = - delayed { _, duration -> f(duration) } - - @Deprecated( - "Nano based APIs are being deprecated, and removed in Arrow Resilience. Use delayed instead $NicheAPI", - ReplaceWith("delayed { _, nanos -> f(nanos.nanoseconds) }", "kotlin.time.Companion.Duration.nanoseconds") - ) - public fun delayedNanos(f: suspend (duration: Double) -> Double): Schedule = - modifyNanos { _, duration -> f(duration) } - - @Deprecated( - "Nano based APIs are being deprecated, and removed in Arrow Resilience. $NicheAPI" - ) - public fun jittered(genRand: suspend () -> Double): Schedule = - modifyNanos { _, duration -> - val n = genRand.invoke() - (duration * n) - } - - @JvmName("jitteredDuration") - @ExperimentalTime - @Deprecated("Use jittered with Kotlin's Random instead. This API will be removed in Arrow Resilience $NicheAPI") - public fun jittered(genRand: suspend () -> Duration): Schedule = - modify { _, duration -> - val n = genRand.invoke() - duration.times(n.toDouble(NANOSECONDS)) - } - - /** - * Add random jitter to a schedule. - * - * By requiring Kotlin's [Random] as a parameter, this function is deterministic and testable. - * The result returned by [Random.nextDouble] between 0.0 and 1.0 is multiplied with the current duration. - */ - public fun jittered(random: Random = Random.Default): Schedule = - jittered(suspend { random.nextDouble(0.0, 1.0) }) - - /** - * Non-effectful version of [foldM]. - */ - public fun fold(initial: C, f: suspend (acc: C, output: Output) -> C): Schedule = - foldLazy(suspend { initial }) { acc, o -> f(acc, o) } - - /** - * Accumulates the results of every execution into a list. - */ - public fun collect(): Schedule> = - fold(emptyList()) { acc, o -> acc + listOf(o) } - - /** - * Infix variant of pipe with reversed order. - */ - @Deprecated(NicheAPI) - public infix fun compose(other: Schedule): Schedule = - (other pipe this) - - // Dependent type emulation - @Suppress("UNCHECKED_CAST") - internal class ScheduleImpl( - val initialState: suspend () -> State, - val update: suspend (a: Input, s: State) -> Decision - ) : Schedule() { - - public override suspend fun repeatOrElseEither( - fa: suspend () -> Input, - orElse: suspend (Throwable, Output?) -> C - ): Either { - var last: (() -> Output)? = null // We haven't seen any input yet - var state: State = initialState.invoke() - - while (true) { - coroutineContext.ensureActive() - try { - val a = fa.invoke() - val step = update(a, state) - if (!step.cont) return Either.Right(step.finish.value()) - else { - delay((step.delayInNanos / 1_000_000).toLong()) - - // Set state before looping again - last = { step.finish.value() } - state = step.state - } - } catch (e: Throwable) { - return Either.Left(orElse(e.nonFatalOrThrow(), last?.invoke())) - } - } - } - - override suspend fun repeatOrElseEitherAsFlow( - fa: suspend () -> Input, - orElse: suspend (Throwable, Output?) -> C - ): Flow> = flow { - log { _, output -> emit(output.right()) } - .repeatOrElseEither(fa) { e, output -> emit(orElse(e, output).left()) } - } - - override fun map(f: (output: Output) -> B): Schedule = - ScheduleImpl(initialState) { i, s -> update(i, s).map(f) } - - override fun contramap(f: suspend (B) -> Input): Schedule = - ScheduleImpl(initialState) { i, s -> update(f(i), s) } - - override fun check(pred: suspend (input: A, output: Output) -> Boolean): Schedule = - updated { f -> - { a: A, s: State -> - val dec = f(a, s) - if (dec.cont) pred(a, dec.finish.value()).let { dec.copy(cont = it) } - else dec - } - } - - override fun combineNanos( - other: Schedule, - zipContinue: (cont: Boolean, otherCont: Boolean) -> Boolean, - zipDuration: (duration: Double, otherDuration: Double) -> Double, - zip: (Output, B) -> C - ): Schedule = (other as ScheduleImpl).let { other -> - ScheduleImpl(suspend { Pair(initialState.invoke(), other.initialState.invoke()) }) { i, s: Pair -> - update(i, s.first).combineNanos(other.update(i, s.second), zipContinue, zipDuration, zip) - } - } - - override fun forever(): Schedule = updated { f -> - { a: Input, s: State -> - val dec = f(a, s) - if (dec.cont) dec - else { - val state = this@ScheduleImpl.initialState.invoke() - dec.copy(cont = true, state = state) - } - } - } - - override operator fun not(): Schedule = - updated { f -> - { a: Input, s: State -> - !f(a, s) - } - } - - override fun andThen(other: Schedule): Schedule> = - ScheduleImpl, A, Either>(suspend { Either.Left(initialState.invoke()) }) { i, s -> - (other as ScheduleImpl) - s.fold( - { state -> - val dec = this@ScheduleImpl.update(i, state) - if (dec.cont) dec.bimap({ it.left() }, { it.left() }) - else { - val newState = other.initialState.invoke() - val newDec = other.update(i, newState) - newDec.bimap({ it.right() }, { it.right() }) - } - }, - { state -> - other.update(i, state).bimap({ it.right() }, { it.right() }) - } - ) - } - - override fun modifyNanos(f: suspend (output: Output, duration: Double) -> Double): Schedule = - updated { update -> - { a: Input, s: State -> - val step = update(a, s) - val d = f(step.finish.value(), step.delayInNanos) - step.copy(delayInNanos = d) - } - } - - override fun log(action: suspend (Input, output: Output) -> Unit): Schedule = - updated { update -> - { a: Input, s: State -> - update(a, s).also { action(a, it.finish.value()) } - } - } - - override fun logInput(f: suspend (input: Input) -> Unit): Schedule = - log { input, _ -> f(input) } - - override fun logOutput(f: suspend (output: Output) -> Unit): Schedule = - log { _, output -> f(output) } - - override fun foldLazy(initial: suspend () -> C, f: suspend (acc: C, output: Output) -> C): Schedule = - ScheduleImpl(suspend { Pair(initialState.invoke(), initial.invoke()) }) { i, s -> - val dec = update(i, s.first) - val c = if (dec.cont) f(s.second, dec.finish.value()) else s.second - dec.bimap({ state -> Pair(state, c) }, { c }) - } - - @Suppress("NAME_SHADOWING") - override infix fun pipe(other: Schedule): Schedule = - (other as ScheduleImpl).let { other -> - ScheduleImpl(suspend { Pair(initialState.invoke(), other.initialState.invoke()) }) { i, s -> - val dec1 = update(i, s.first) - val dec2 = other.update(dec1.finish.value(), s.second) - dec1.combineNanos(dec2, { a, b -> a && b }, { a, b -> a + b }, { _, b -> b }) - } - } - - @Suppress("NAME_SHADOWING") - override fun zip(other: Schedule, f: (Output, B) -> C): Schedule, C> = - (other as ScheduleImpl).let { other -> - ScheduleImpl(suspend { Pair(initialState.invoke(), other.initialState.invoke()) }) { i, s -> - val dec1 = update(i.first, s.first) - val dec2 = other.update(i.second, s.second) - dec1.combineNanos(dec2, { a, b -> a && b }, { a, b -> max(a, b) }, f) - } - } - - @Suppress("NAME_SHADOWING") - override infix fun choose(other: Schedule): Schedule, Either> = - (other as ScheduleImpl).let { other -> - ScheduleImpl(suspend { Pair(initialState.invoke(), other.initialState.invoke()) }) { i, s -> - i.fold( - { - update(it, s.first).mapLeft { state -> Pair(state, s.second) }.map { output -> output.left() } - }, - { - other.update(it, s.second).mapLeft { otherState -> Pair(s.first, otherState) } - .map { otherOutput -> otherOutput.right() } - } - ) - } - } - - /** - * Schedule state machine update function - */ - fun updated( - f: (suspend (input: A, state: State) -> Decision) -> (suspend (input: A, state: State) -> Decision) - ): Schedule = ScheduleImpl(initialState) { a, s -> - f { input, state -> update(input, state) }(a, s) - } - - /** - * Inspect and change the [Decision] of a [Schedule]. Also given access to the input. - */ - fun reconsider(f: suspend (input: A, desision: Decision) -> Decision): Schedule = - updated { update -> - { a: A, s: State -> - val dec = update(a, s) - f(a, dec) - } - } - - /** - * Run an effect with a [Decision]. Does not alter the decision. - */ - fun onDecision(fa: suspend (input: A, decision: Decision) -> Unit): Schedule = - updated { f -> - { a: A, s: State -> - f(a, s).also { fa(a, it) } - } - } - } - - /** - * A single decision. Contains the decision to continue, the delay, the new state and the (lazy) result of a Schedule. - */ - public data class Decision( - val cont: Boolean, - val delayInNanos: Double, - val state: A, - val finish: Eval - ) { - - @ExperimentalTime - val duration: Duration - get() = delayInNanos.nanoseconds - - public operator fun not(): Decision = - copy(cont = !cont) - - public fun bimap(f: (A) -> C, g: (B) -> D): Decision = - Decision(cont, delayInNanos, f(state), finish.map(g)) - - public fun mapLeft(f: (A) -> C): Decision = - bimap(f, ::identity) - - public fun map(g: (B) -> D): Decision = - bimap(::identity, g) - - public fun combineNanos( - other: Decision, - f: (Boolean, Boolean) -> Boolean, - g: (Double, Double) -> Double, - zip: (B, D) -> E - ): Decision, E> = Decision( - f(cont, other.cont), - g(delayInNanos, other.delayInNanos), - Pair(state, other.state), - finish.flatMap { first -> other.finish.map { second -> zip(first, second) } } - ) - - @ExperimentalTime - public fun combine( - other: Decision, - f: (Boolean, Boolean) -> Boolean, - g: (Duration, Duration) -> Duration, - zip: (B, D) -> E - ): Decision, E> = Decision( - f(cont, other.cont), - g(delayInNanos.nanoseconds, other.delayInNanos.nanoseconds).toDouble(NANOSECONDS), - Pair(state, other.state), - finish.flatMap { first -> other.finish.map { second -> zip(first, second) } } - ) - - override fun equals(other: Any?): Boolean = - if (other !is Decision<*, *>) false - else cont == other.cont && - state == other.state && - delayInNanos == other.delayInNanos && - finish.value() == other.finish.value() - - public companion object { - public fun cont(d: Double, a: A, b: Eval): Decision = - Decision(true, d, a, b) - - public fun done(d: Double, a: A, b: Eval): Decision = - Decision(false, d, a, b) - - @ExperimentalTime - public fun cont(d: Duration, a: A, b: Eval): Decision = - cont(d.toDouble(NANOSECONDS), a, b) - - @ExperimentalTime - public fun done(d: Duration, a: A, b: Eval): Decision = - done(d.toDouble(NANOSECONDS), a, b) - } - } - - public companion object { - - /** - * Invoke constructor to manually define a schedule. If you need this, please consider adding it to Arrow or suggest - * a change to avoid using this manual method. - */ - @Deprecated("The Schedule encoding in Arrow Resilience is simpler, and doesn't require this method anymore.") - public operator fun invoke( - initial: suspend () -> S, - update: suspend (input: A, state: S) -> Decision - ): Schedule = ScheduleImpl(initial, update) - - /** - * Creates a Schedule that continues without delay and just returns its input. - */ - public fun identity(): Schedule = - Schedule({ Unit }) { a, s -> - Decision.cont(0.0, s, Eval.now(a)) - } - - /** - * Creates a Schedule that continues without delay and always returns Unit. - */ - @Deprecated( - "Use identity and map instead. $NicheAPI", - ReplaceWith("identity().map { }") - ) - public fun unit(): Schedule = - identity().map { } - - /** - * Creates a schedule that unfolds effectfully using a seed value [c] and a unfold function [f]. - * This keeps the current state (the current seed) as [State] and runs the unfold function on every - * call to update. This schedule always continues without delay and returns the current state. - */ - @Deprecated("Use unfold instead. $NicheAPI") - public fun unfoldLazy(c: suspend () -> A, f: suspend (A) -> A): Schedule = - Schedule(c) { _: I, acc -> - val a = f(acc) - Decision.cont(0.0, a, Eval.now(a)) - } - - /** - * Non-effectful variant of [unfoldLazy] - */ - public fun unfold(c: A, f: (A) -> A): Schedule = - unfoldLazy(suspend { c }) { f(it) } - - /** - * Creates a Schedule that continues forever and returns the number of iterations. - */ - public fun forever(): Schedule = - unfold(0) { it + 1 } - - /** - * Creates a Schedule that continues [n] times and returns the number of iterations. - */ - public fun recurs(n: Int): Schedule = - Schedule(suspend { 0 }) { _: A, acc -> - if (acc < n) Decision.cont(0.0, acc + 1, Eval.now(acc + 1)) - else Decision.done(0.0, acc, Eval.now(acc)) - } - - /** - * Creates a Schedule that only retries once. - */ - @Deprecated( - "Use recurs(1) instead. This API will be removed in Arrow Resilience $NicheAPI", - ReplaceWith("recurs(1)") - ) - public fun once(): Schedule = - recurs(1).void() - - /** - * Creates a schedule that never retries. - * - * Note that this will hang a program if used as a repeat/retry schedule unless cancelled. - */ - @Deprecated("This API will be removed in Arrow Resilience $NicheAPI") - public fun never(): Schedule = - Schedule(suspend { arrow.fx.coroutines.never() }) { _, _ -> - Decision(false, 0.0, Unit, Eval.later { throw IllegalArgumentException("Impossible") }) - } - - /** - * Creates a Schedule that uses another Schedule to generate the delay of this schedule. - * Continues for as long as [delaySchedule] continues and adds the output of [delaySchedule] to - * the delay that [delaySchedule] produced. Also returns the full delay as output. - * - * The Schedule [delaySchedule] is should specify the delay in nanoseconds. - * - * A common use case is to define a unfolding schedule and use the result to change the delay. - * For an example see the implementation of [spaced], [linear], [fibonacci] or [exponential] - */ - @Suppress("UNCHECKED_CAST") - @JvmName("delayedNanos") - @Deprecated("This API will be removed in Arrow Resilience $NicheAPI") - public fun delayed(delaySchedule: Schedule): Schedule = - (delaySchedule.modifyNanos { a, b -> a + b } as ScheduleImpl) - .reconsider { _, dec -> dec.copy(finish = Eval.now(dec.delayInNanos)) } - - /** - * Creates a Schedule that uses another Schedule to generate the delay of this schedule. - * Continues for as long as [delaySchedule] continues and adds the output of [delaySchedule] to - * the delay that [delaySchedule] produced. Also returns the full delay as output. - * - * A common use case is to define a unfolding schedule and use the result to change the delay. - * For an example see the implementation of [spaced], [linear], [fibonacci] or [exponential] - */ - @ExperimentalTime - @JvmName("delayedDuration") - @Deprecated("This API will be removed in Arrow Resilience $NicheAPI") - public fun delayed(delaySchedule: Schedule): Schedule = - (delaySchedule.modify { a, b -> a + b } as ScheduleImpl) - .reconsider { _, dec -> dec.copy(finish = Eval.now(dec.delayInNanos.nanoseconds)) } - - /** - * Creates a Schedule which collects all its inputs in a list. - */ - public fun collect(): Schedule> = - identity().collect() - - /** - * Creates a Schedule that continues as long as [f] returns true. - */ - public fun doWhile(f: suspend (A) -> Boolean): Schedule = - identity().whileInput(f) - - /** - * Creates a Schedule that continues until [f] returns true. - */ - public fun doUntil(f: suspend (A) -> Boolean): Schedule = - identity().untilInput(f) - - /** - * Creates a Schedule with an effectful handler on the input. - */ - public fun logInput(f: suspend (A) -> Unit): Schedule = - identity().logInput(f) - - /** - * Creates a Schedule with an effectful handler on the output. - */ - public fun logOutput(f: suspend (A) -> Unit): Schedule = - identity().logOutput(f) - - public fun delayInNanos(): Schedule = - (forever() as ScheduleImpl).reconsider { _: A, decision -> - Decision( - cont = decision.cont, - delayInNanos = decision.delayInNanos, - state = decision.state, - finish = Eval.now(decision.delayInNanos) - ) - } - - @ExperimentalTime - public fun duration(): Schedule = - (forever() as ScheduleImpl).reconsider { _: A, decision -> - Decision( - cont = decision.cont, - delayInNanos = decision.delayInNanos, - state = decision.state, - finish = Eval.now(decision.delayInNanos.nanoseconds) - ) - } - - /** - * Creates a Schedule that returns its decisions. - */ - @Suppress("UNCHECKED_CAST") - public fun decision(): Schedule = - (forever() as ScheduleImpl).reconsider { _: A, decision -> - Decision( - cont = decision.cont, - delayInNanos = decision.delayInNanos, - state = decision.state, - finish = Eval.now(decision.cont) - ) - } - - /** - * Creates a Schedule that continues with a fixed delay. - * - * @param interval fixed delay in nanoseconds - */ - public fun spaced(interval: Double): Schedule = - forever().delayedNanos { d -> d + interval } - - /** - * Creates a Schedule that continues with a fixed delay. - * - * @param interval fixed delay in [Duration] - */ - @ExperimentalTime - public fun spaced(interval: Duration): Schedule = - forever().delayedNanos { d -> d + interval.toDouble(NANOSECONDS) } - - /** - * Creates a Schedule that continues with increasing delay by adding the last two delays. - * - * @param one initial delay in nanoseconds - */ - public fun fibonacci(one: Double): Schedule = - delayed( - unfold>(Pair(0.0, one)) { (del, acc) -> - Pair(acc, del + acc) - }.map { it.first } - ) - - /** - * Creates a Schedule that continues with increasing delay by adding the last two delays. - */ - @ExperimentalTime - public fun fibonacci(one: Duration): Schedule = - delayed( - unfold>(Pair(0.nanoseconds, one)) { (del, acc) -> - Pair(acc, del + acc) - }.map { it.first } - ) - - /** - * Creates a Schedule which increases its delay linearly, by n * base where n is the number of executions. - * - * @param base the base delay in nanoseconds - */ - public fun linear(base: Double): Schedule = - delayed(forever().map { base * it }) - - /** - * Creates a Schedule which increases its delay linearly, by n * base where n is the number of executions. - */ - @ExperimentalTime - public fun linear(base: Duration): Schedule = - delayed(forever().map { base * it }) - - /** - * Creates a Schedule that increases its delay exponentially with a given factor and base. - * Delays can be calculated as [base] * factor ^ n where n is the number of executions. - * - * @param base the base delay in nanoseconds - */ - public fun exponential(base: Double, factor: Double = 2.0): Schedule = - delayed(forever().map { base * factor.pow(it).roundToInt() }) - - /** - * Creates a Schedule that increases its delay exponentially with a given factor and base. - * Delays can be calculated as [base] * factor ^ n where n is the number of executions. - */ - @ExperimentalTime - public fun exponential(base: Duration, factor: Double = 2.0): Schedule = - delayed(forever().map { base * factor.pow(it).roundToInt() }) - } -} - -/** - * Runs an effect and, if it fails, decide using the provided policy if the effect should be retried and if so, with how much delay. - * Returns the result of the effect if if it was successful or re-raises the last error encountered when the schedule ends. - */ -public suspend fun Schedule.retry(fa: suspend () -> A): A = - retryOrElse(fa) { e, _ -> throw e } - -/** - * Runs an effect and, if it fails, decide using the provided policy if the effect should be retried and if so, with how much delay. - * Also offers a function to handle errors if they are encountered during retrial. - */ -public suspend fun Schedule.retryOrElse( - fa: suspend () -> A, - orElse: suspend (Throwable, B) -> A -): A = - retryOrElseEither(fa, orElse).fold(::identity, ::identity) - -/** - * Runs an effect and, if it fails, decide using the provided policy if the effect should be retried and if so, with how much delay. - * Also offers a function to handle errors if they are encountered during retrial. - */ -@Suppress("UNCHECKED_CAST") -public suspend fun Schedule.retryOrElseEither( - fa: suspend () -> A, - orElse: suspend (Throwable, B) -> C -): Either { - (this as ScheduleImpl) - - var dec: Schedule.Decision - var state: Any? = initialState.invoke() - - while (true) { - coroutineContext.ensureActive() - try { - return Either.Right(fa.invoke()) - } catch (e: Throwable) { - dec = update(e, state) - state = dec.state - - if (dec.cont) delay((dec.delayInNanos / 1_000_000).toLong()) - else return Either.Left(orElse(e.nonFatalOrThrow(), dec.finish.value())) - } - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/builders.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/builders.kt deleted file mode 100644 index 18781ca74c0..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/builders.kt +++ /dev/null @@ -1,16 +0,0 @@ -package arrow.fx.coroutines - -import kotlinx.coroutines.awaitCancellation - -@Deprecated( - "Prefer using awaitCancellation from KotlinX", - ReplaceWith("awaitCancellation()", "kotlinx.coroutines.awaitCancellation") -) -public suspend fun never(): A = - awaitCancellation() - -@Deprecated( - "Prefer simply using Unit, or empty lambda when needed", - ReplaceWith("Unit") -) -public suspend fun unit(): Unit = Unit diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/continuations/resource.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/continuations/resource.kt deleted file mode 100644 index 74788a8d223..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/continuations/resource.kt +++ /dev/null @@ -1,106 +0,0 @@ -package arrow.fx.coroutines.continuations - -import arrow.AutoCloseScope -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.ExitCase.Companion.ExitCase -import arrow.fx.coroutines.Resource -import arrow.fx.coroutines.releaseCase - -@DslMarker -public annotation class ScopeDSL - -@DslMarker -public annotation class ResourceDSL - -/** - * This Marker exists to prevent being able to call `bind` from `install`, and its derived methods. - * This is done to ensure correct usage of [ResourceScope]. - */ -@ResourceDSL -public object AcquireStep - -/** - * Computation block for the [Resource] type. - * The [Resource] allows us to describe resources as immutable values, - * and compose them together in simple ways. - * This way you can split the logic of what a `Resource` is and how it should be closed from how you use them. - * - * * # Using and composing Resource - * - * ```kotlin - * import arrow.fx.coroutines.continuations.resource - * import arrow.fx.coroutines.release - * - * class UserProcessor { - * fun start(): Unit = println("Creating UserProcessor") - * fun shutdown(): Unit = println("Shutting down UserProcessor") - * fun process(ds: DataSource): List = - * ds.users().map { "Processed $it" } - * } - * - * class DataSource { - * fun connect(): Unit = println("Connecting dataSource") - * fun users(): List = listOf("User-1", "User-2", "User-3") - * fun close(): Unit = println("Closed dataSource") - * } - * - * class Service(val db: DataSource, val userProcessor: UserProcessor) { - * suspend fun processData(): List = userProcessor.process(db) - * } - * - * //sampleStart - * val userProcessor = resource { - * UserProcessor().also(UserProcessor::start) - * } release UserProcessor::shutdown - * - * val dataSource = resource { - * DataSource().also { it.connect() } - * } release DataSource::close - * - * suspend fun main(): Unit { - * resource { - * Service(dataSource.bind(), userProcessor.bind()) - * }.use { service -> service.processData() } - * } - * //sampleEnd - * ``` - * - */ -@ResourceDSL -public interface ResourceScope : AutoCloseScope { - - @ResourceDSL - public suspend fun Resource.bind(): A - - /** - * Install [A] into the [ResourceScope]. - * It's [release] function will be called with the appropriate [ExitCase] if this [ResourceScope] finishes. - * It results either in [ExitCase.Completed], [ExitCase.Cancelled] or [ExitCase.Failure] depending on the terminal state of [Resource] lambda. - */ - @ResourceDSL - public suspend fun install( - acquire: suspend AcquireStep.() -> A, - release: suspend (A, ExitCase) -> Unit, - ): A - - /** Composes a [release] action to a [Resource] value before binding. */ - @ResourceDSL - public suspend infix fun Resource.release(release: suspend (A) -> Unit): A { - val a = bind() - return install({ a }) { a, _ -> release(a) } - } - - /** Composes a [releaseCase] action to a [Resource] value before binding. */ - @ResourceDSL - public suspend infix fun Resource.releaseCase(release: suspend (A, ExitCase) -> Unit): A { - val a = bind() - return install({ a }, release) - } - - public suspend infix fun onRelease(release: suspend (ExitCase) -> Unit): Unit = - install({ }) { _, exitCase -> release(exitCase) } -} - -@ScopeDSL -public fun resource(f: suspend ResourceScope.() -> A): Resource = - Resource.Dsl(f) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/flow.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/flow.kt index 52ec81e3bd8..f0fbac3fa8a 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/flow.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/flow.kt @@ -19,64 +19,17 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.retryWhen import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.produceIn import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.zip +import kotlin.time.ComparableTimeMark import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds import kotlin.time.ExperimentalTime - -/** - * Retries collection of the given flow when an exception occurs in the upstream flow based on a decision by the [schedule]. - * This operator is *transparent* to exceptions that occur in downstream flow and does not retry on exceptions that are thrown - * to cancel the flow. - * - * @see [Schedule] for how to build a schedule. - * - * ```kotlin - * import kotlinx.coroutines.flow.* - * import arrow.fx.coroutines.* - * suspend fun main(): Unit { - * var counter = 0 - * val flow = flow { - * emit(counter) - * if (++counter <= 5) throw RuntimeException("Bang!") - * } - * //sampleStart - * val sum = flow.retry(Schedule.recurs(5)) - * .reduce(Int::plus) - * //sampleEnd - * println(sum) - * } - * ``` - * - * - * @param schedule - the [Schedule] used for retrying the collection of the flow - */ -@Deprecated(deprecatedInFavorOfArrowFxResilience, ReplaceWith("retry", "arrow.fx.resilience.retry")) -public fun Flow.retry(schedule: Schedule): Flow = flow { - (schedule as Schedule.ScheduleImpl) - var dec: Schedule.Decision - var state: Any? = schedule.initialState() - - val retryWhen = retryWhen { cause, _ -> - dec = schedule.update(cause, state) - state = dec.state - - if (dec.cont) { - delay((dec.delayInNanos / 1_000_000).toLong()) - true - } else { - false - } - } - retryWhen.collect { - emit(it) - } -} +import kotlin.time.TimeSource /** * Like [map], but will evaluate [transform] in parallel, emitting the results @@ -107,7 +60,7 @@ public fun Flow.retry(schedule: Schedule): Flow = flo * } * //sampleEnd * ``` - * + * * The upstream `source` runs concurrently with downstream `parMap`, and thus the upstream * concurrently runs, "prefetching", the next element. i.e. * @@ -124,7 +77,7 @@ public fun Flow.retry(schedule: Schedule): Flow = flo * //sampleEnd * } * ``` - * + * * * `1, 2, 3` will be emitted from `source` but only "Processing 1" & "Processing 2" will get printed. */ @@ -180,7 +133,7 @@ public inline fun Flow.parMap( * } * //sampleEnd * ``` - * + * */ @FlowPreview @ExperimentalCoroutinesApi @@ -217,7 +170,7 @@ public inline fun Flow.parMapUnordered( * } * //sampleEnd * ``` - * + * */ @FlowPreview @ExperimentalCoroutinesApi @@ -258,16 +211,17 @@ public fun Flow.repeat(): Flow = public fun Flow.metered(period: Duration): Flow = fixedRate(period).zip(this) { _, a -> a } +@ExperimentalTime public fun Flow.metered(period: Long): Flow = fixedRate(period).zip(this) { _, a -> a } @ExperimentalTime public fun fixedRate( - period: Duration, + periodInMillis: Long, dampen: Boolean = true, - timeStampInMillis: () -> Long = { timeInMillis() } + timeStamp: () -> ComparableTimeMark = { TimeSource.Monotonic.markNow() } ): Flow = - fixedRate(period.inWholeMilliseconds, dampen, timeStampInMillis) + fixedRate(periodInMillis.milliseconds, dampen, timeStamp) /** * Flow that emits [Unit] every [period] while taking into account how much time it takes downstream to consume the emission. @@ -283,19 +237,19 @@ public fun fixedRate( * * @param period period between [Unit] emits of the resulting [Flow]. * @param dampen if you set [dampen] to false it will send `n` times [period] time it took downstream to process the emission. - * @param timeStampInMillis allows for supplying a different timestamp function, useful to override with `runBlockingTest` + * @param timeStamp allows for supplying a different timestamp function, useful to override with `runBlockingTest` */ public fun fixedRate( - period: Long, + period: Duration, dampen: Boolean = true, - timeStampInMillis: () -> Long = { timeInMillis() } + timeStamp: () -> ComparableTimeMark = { TimeSource.Monotonic.markNow() } ): Flow = - if (period == 0L) flowOf(Unit).repeat() + if (period == Duration.ZERO) flowOf(Unit).repeat() else flow { - var lastAwakeAt = timeStampInMillis() + var lastAwakeAt = timeStamp() while (true) { - val now = timeStampInMillis() + val now = timeStamp() val next = lastAwakeAt + period if (next > now) { @@ -303,13 +257,13 @@ public fun fixedRate( emit(Unit) lastAwakeAt = next } else { - val ticks: Long = (now - lastAwakeAt - 1) / period + val ticks: Long = ((now - lastAwakeAt).inWholeMilliseconds - 1) / period.inWholeMilliseconds when { ticks < 0L -> Unit ticks == 0L || dampen -> emit(Unit) else -> repeat(ticks.toInt()) { emit(Unit) } } - lastAwakeAt += (period * ticks) + lastAwakeAt += (period * ticks.toDouble()) } } } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/predef.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/predef.kt deleted file mode 100644 index d033195a842..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonMain/kotlin/arrow/fx/coroutines/predef.kt +++ /dev/null @@ -1,11 +0,0 @@ -package arrow.fx.coroutines - -/** - * Gets current system time in milliseconds since certain moment in the past, - * only delta between two subsequent calls makes sense. - * - * For the JVM target this delegates to `java.lang.System.currentTimeMillis()` - * For the native targets this delegates to `kotlin.system.getTimeMillis` - * For Javascript it relies on `new Date().getTime()` - */ -public expect fun timeInMillis(): Long diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/AtomicTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/AtomicTest.kt deleted file mode 100644 index 74822e0eb4b..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/AtomicTest.kt +++ /dev/null @@ -1,130 +0,0 @@ -package arrow.fx.coroutines - -import io.kotest.common.Platform -import io.kotest.common.platform -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.checkAll -import kotlin.coroutines.Continuation -import kotlin.coroutines.EmptyCoroutineContext -import kotlin.coroutines.intrinsics.startCoroutineUninterceptedOrReturn - -class AtomicTest : StringSpec({ - - "set get - successful" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val r = Atomic(x) - r.set(y) - r.get() shouldBe y - } - } - - "getAndSet - successful" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val ref = Atomic(x) - ref.getAndSet(y) shouldBe x - ref.get() shouldBe y - } - } - - "access - successful" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val ref = Atomic(x) - val (_, setter) = ref.access() - setter(y) shouldBe true - ref.get() shouldBe y - } - } - - "access - setter should fail if value is modified before setter is called" { - checkAll(Arb.int(), Arb.int()) { x, z -> - val ref = Atomic(x) - val (_, setter) = ref.access() - ref.update { it + 1 } - setter(z) shouldBe false - ref.get() shouldBe x + 1 - } - } - - "access - setter should fail if called twice" { - checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int()) { w, x, y, z -> - val ref = Atomic(w) - val (_, setter) = ref.access() - setter(x) shouldBe true - ref.set(y) - setter(z) shouldBe false - ref.get() shouldBe y - } - } - - "tryUpdate - modification occurs successfully" { - checkAll(Arb.int()) { x -> - val ref = Atomic(x) - ref.tryUpdate { it + 1 } - ref.get() shouldBe x + 1 - } - } - - "tryUpdate - should fail to update if modification has occurred" { - checkAll(Arb.int()) { x -> - val ref = Atomic(x) - ref.tryUpdate { - suspend { ref.update(Int::inc) } - .startCoroutineUninterceptedOrReturn(Continuation(EmptyCoroutineContext) { }) - it + 1 - } shouldBe false - } - } - - "consistent set update" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val set = suspend { - val r = Atomic(x) - r.set(y) - r.get() - } - - val update = suspend { - val r = Atomic(x) - r.update { y } - r.get() - } - - set() shouldBe update() - } - } - - "access id" { - checkAll(Arb.int()) { x -> - val r = Atomic(x) - val (a, _) = r.access() - r.get() shouldBe a - } - } - - "consistent access tryUpdate" { - checkAll(Arb.int()) { x -> - val acccessMap = suspend { - val r = Atomic(x) - val (a, setter) = r.access() - setter(a + 1) - } - val tryUpdate = suspend { - val r = Atomic(x) - r.tryUpdate { it + 1 } - } - - acccessMap() shouldBe tryUpdate() - } - } - - "concurrent modifications".config(enabled = platform == Platform.JVM) { - val finalValue = 50_000 - val r = Atomic(0) - (0 until finalValue).parTraverse { r.update { it + 1 } } - r.get() shouldBe finalValue - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/BracketCaseTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/BracketCaseTest.kt index 5892715e859..62cd84c51bb 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/BracketCaseTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/BracketCaseTest.kt @@ -1,7 +1,6 @@ package arrow.fx.coroutines import arrow.core.Either -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf @@ -12,358 +11,380 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.test.runTest +import kotlin.test.Test import kotlin.time.ExperimentalTime @ExperimentalTime -class BracketCaseTest : StringSpec({ - "Immediate acquire bracketCase finishes successfully" { - checkAll(Arb.int(), Arb.int()) { a, b -> - var once = true - bracketCase( - acquire = { a }, - use = { aa -> Pair(aa, b) }, - release = { _, _ -> - require(once) - once = false - } - ) shouldBe Pair(a, b) - } +class BracketCaseTest { + @Test + fun immediateAcquireBracketCaseFinishesSuccessfully() = runTest { + checkAll(Arb.int(), Arb.int()) { a, b -> + var once = true + bracketCase( + acquire = { a }, + use = { aa -> Pair(aa, b) }, + release = { _, _ -> + require(once) + once = false + } + ) shouldBe Pair(a, b) } + } - "Suspended acquire bracketCase finishes successfully" { - checkAll(Arb.int(), Arb.int()) { a, b -> - var once = true - bracketCase( - acquire = { a.suspend() }, - use = { aa -> Pair(aa, b) }, - release = { _, _ -> - require(once) - once = false - } - ) shouldBe Pair(a, b) - } + @Test + fun suspendedAcquireBracketCaseFinishedSuccessfully() = runTest { + checkAll(Arb.int(), Arb.int()) { a, b -> + var once = true + bracketCase( + acquire = { a.suspend() }, + use = { aa -> Pair(aa, b) }, + release = { _, _ -> + require(once) + once = false + } + ) shouldBe Pair(a, b) } + } - "Immediate error in acquire stays the same error" { - checkAll(Arb.throwable()) { e -> - Either.catch { - bracketCase( - acquire = { throw e }, - use = { 5 }, - release = { _, _ -> Unit } - ) - } should leftException(e) - } + @Test + fun immediateErrorInAcquireStaysTheSameError() = runTest { + checkAll(Arb.throwable()) { e -> + Either.catch { + bracketCase( + acquire = { throw e }, + use = { 5 }, + release = { _, _ -> Unit } + ) + } should leftException(e) } + } - "Suspend error in acquire stays the same error" { - checkAll(Arb.throwable()) { e -> - Either.catch { - bracketCase( - acquire = { e.suspend() }, - use = { 5 }, - release = { _, _ -> Unit } - ) - } should leftException(e) - } + @Test + fun suspendErrorInAcquireStaysTheSameError() = runTest { + checkAll(Arb.throwable()) { e -> + Either.catch { + bracketCase( + acquire = { e.suspend() }, + use = { 5 }, + release = { _, _ -> Unit } + ) + } should leftException(e) } + } - "Immediate use bracketCase finishes successfully" { - checkAll(Arb.int(), Arb.int()) { a, b -> - var once = true - bracketCase( - acquire = { a }, - use = { aa -> Pair(aa, b).suspend() }, - release = { _, _ -> - require(once) - once = false - } - ) shouldBe Pair(a, b) - } + @Test + fun immediateUseBracketCaseFinishedSuccessfully() = runTest { + checkAll(Arb.int(), Arb.int()) { a, b -> + var once = true + bracketCase( + acquire = { a }, + use = { aa -> Pair(aa, b).suspend() }, + release = { _, _ -> + require(once) + once = false + } + ) shouldBe Pair(a, b) } + } - "Suspended use bracketCase finishes successfully" { - checkAll(Arb.int(), Arb.int()) { a, b -> - var once = true - bracketCase( - acquire = { a }, - use = { aa -> Pair(aa, b).suspend() }, - release = { _, _ -> - require(once) - once = false + @Test + fun suspendedUseBracketCaseFinishesSuccessfully() = runTest { + checkAll(Arb.int(), Arb.int()) { a, b -> + var once = true + bracketCase( + acquire = { a }, + use = { aa -> Pair(aa, b).suspend() }, + release = { _, _ -> + require(once) + once = false + } + ) shouldBe Pair(a, b) + } + } + + @Test + fun bracketCaseMustRunReleaseTaskOnUseImmediateError() = runTest { + checkAll(Arb.int(), Arb.throwable()) { i, e -> + val promise = CompletableDeferred() + + Either.catch { + bracketCase( + acquire = { i }, + use = { throw e }, + release = { _, ex -> + require(promise.complete(ex)) { "Release should only be called once, called again with $ex" } } - ) shouldBe Pair(a, b) + ) } - } - "bracketCase must run release task on use immediate error" { - checkAll(Arb.int(), Arb.throwable()) { i, e -> - val promise = CompletableDeferred() - - Either.catch { - bracketCase( - acquire = { i }, - use = { throw e }, - release = { _, ex -> - require(promise.complete(ex)) { "Release should only be called once, called again with $ex" } - } - ) - } + promise.await() shouldBe ExitCase.Failure(e) + } + } - promise.await() shouldBe ExitCase.Failure(e) + @Test + fun bracketCaseMustRunReleaseTaskOnUseSuspendedError() = runTest { + checkAll(Arb.int(), Arb.throwable()) { x, e -> + val promise = CompletableDeferred>() + + Either.catch { + bracketCase( + acquire = { x }, + use = { e.suspend() }, + release = { xx, ex -> + require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } + } + ) } + + promise.await() shouldBe Pair(x, ExitCase.Failure(e)) } + } - "bracketCase must run release task on use suspended error" { - checkAll(Arb.int(), Arb.throwable()) { x, e -> - val promise = CompletableDeferred>() - - Either.catch { - bracketCase( - acquire = { x }, - use = { e.suspend() }, - release = { xx, ex -> - require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } - } - ) - } + @Test + fun bracketCaseMustAlwaysRunImmediateRelease() = runTest { + checkAll(Arb.int()) { x -> + val promise = CompletableDeferred>() - promise.await() shouldBe Pair(x, ExitCase.Failure(e)) + Either.catch { + bracketCase( + acquire = { x }, + use = { it }, + release = { xx, ex -> + require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } + } + ) } + + promise.await() shouldBe Pair(x, ExitCase.Completed) } + } - "bracketCase must always run immediate release" { - checkAll(Arb.int()) { x -> - val promise = CompletableDeferred>() - - Either.catch { - bracketCase( - acquire = { x }, - use = { it }, - release = { xx, ex -> - require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } - } - ) - } + @Test + fun bracketCaseMustAlwaysRunSuspendedRelease() = runTest { + checkAll(Arb.int()) { x -> + val promise = CompletableDeferred>() - promise.await() shouldBe Pair(x, ExitCase.Completed) + Either.catch { + bracketCase( + acquire = { x }, + use = { it }, + release = { xx, ex -> + require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } + .suspend() + } + ) } + + promise.await() shouldBe Pair(x, ExitCase.Completed) } + } - "bracketCase must always run suspended release" { - checkAll(Arb.int()) { x -> - val promise = CompletableDeferred>() - - Either.catch { - bracketCase( - acquire = { x }, - use = { it }, - release = { xx, ex -> - require(promise.complete(Pair(xx, ex))) { "Release should only be called once, called again with $ex" } - .suspend() - } - ) - } + @Test + fun bracketCaseMustAlwaysRunImmediateReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable()) { n, e -> + Either.catch { + bracketCase( + acquire = { n }, + use = { it }, + release = { _, _ -> throw e } + ) + } should leftException(e) + } + } - promise.await() shouldBe Pair(x, ExitCase.Completed) - } + @Test + fun bracketCaseMustAlwaysRunSuspendedReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable()) { n, e -> + Either.catch { + bracketCase( + acquire = { n }, + use = { it }, + release = { _, _ -> e.suspend() } + ) + } should leftException(e) } + } - "bracketCase must always run immediate release error" { - checkAll(Arb.int(), Arb.throwable()) { n, e -> - Either.catch { - bracketCase( - acquire = { n }, - use = { it }, - release = { _, _ -> throw e } - ) - } should leftException(e) - } + operator fun Throwable.plus(other: Throwable): Throwable = + apply { addSuppressed(other) } + + @Test + fun bracketCaseMustComposeImmediateUseAndImmediateReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> + Either.catch { + bracketCase( + acquire = { n }, + use = { throw e }, + release = { _, _ -> throw e2 } + ) + } shouldBe Either.Left(e + e2) } + } - "bracketCase must always run suspended release error" { - checkAll(Arb.int(), Arb.throwable()) { n, e -> - Either.catch { - bracketCase( - acquire = { n }, - use = { it }, - release = { _, _ -> e.suspend() } - ) - } should leftException(e) - } + @Test + fun bracketCaseMustComposeSuspendUseAndImmediateReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> + Either.catch { + bracketCase( + acquire = { n }, + use = { e.suspend() }, + release = { _, _ -> throw e2 } + ) + } shouldBe Either.Left(e + e2) } - - operator fun Throwable.plus(other: Throwable): Throwable = - apply { addSuppressed(other) } - - "bracketCase must compose immediate use & immediate release error" { - checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> - Either.catch { - bracketCase( - acquire = { n }, - use = { throw e }, - release = { _, _ -> throw e2 } - ) - } shouldBe Either.Left(e + e2) - } + } + + @Test + fun bracketCaseMustComposeImmediateUseAndSuspendReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> + Either.catch { + bracketCase( + acquire = { n }, + use = { throw e }, + release = { _, _ -> e2.suspend() } + ) + } shouldBe Either.Left(e + e2) } + } - "bracketCase must compose suspend use & immediate release error" { - checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> - Either.catch { - bracketCase( - acquire = { n }, - use = { e.suspend() }, - release = { _, _ -> throw e2 } - ) - } shouldBe Either.Left(e + e2) - } + @Test + fun bracketCaseMustComposeSuspendUseAndSuspendReleaseError() = runTest { + checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> + Either.catch { + bracketCase( + acquire = { n }, + use = { e.suspend() }, + release = { _, _ -> e2.suspend() } + ) + } shouldBe Either.Left(e + e2) } + } - "bracketCase must compose immediate use & suspend release error" { - checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> - Either.catch { - bracketCase( - acquire = { n }, - use = { throw e }, - release = { _, _ -> e2.suspend() } - ) - } shouldBe Either.Left(e + e2) - } + @Test + fun cancelOnBracketCaseReleaseWithImmediateAcquire() = runTest { + val start = CompletableDeferred() + val exit = CompletableDeferred() + + val f = async { + bracketCase( + acquire = { }, + use = { + // Signal that fiber is running + start.complete(Unit) + awaitCancellation() + }, + release = { _, exitCase -> + require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } + } + ) } - "bracketCase must compose suspend use & suspend release error" { - checkAll(Arb.int(), Arb.throwable(), Arb.throwable()) { n, e, e2 -> - Either.catch { - bracketCase( - acquire = { n }, - use = { e.suspend() }, - release = { _, _ -> e2.suspend() } - ) - } shouldBe Either.Left(e + e2) - } + // Wait until the fiber is started before cancelling + start.await() + f.cancel() + exit.await().shouldBeInstanceOf() + } + + @Test + fun cancelOnBracketCaseReleasesWithSuspendingAcquire() = runTest { + val start = CompletableDeferred() + val exit = CompletableDeferred() + + val f = async { + bracketCase( + acquire = { Unit.suspend() }, + use = { + // Signal that fiber is running + start.complete(Unit) + awaitCancellation() + }, + release = { _, exitCase -> + require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } + } + ) } - "cancel on bracketCase releases with immediate acquire" { - val start = CompletableDeferred() - val exit = CompletableDeferred() + // Wait until the fiber is started before cancelling + start.await() + f.cancel() + exit.await().shouldBeInstanceOf() + } - val f = async { - bracketCase( - acquire = { Unit }, - use = { - // Signal that fiber is running - start.complete(Unit) - awaitCancellation() - }, - release = { _, exitCase -> - require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } - } - ) - } + @Test + fun cancelOnBracketCaseDoesNotInvokeAfterFinishing() = runTest { + val start = CompletableDeferred() + val exit = CompletableDeferred() + + val f = async { + bracketCase( + acquire = { Unit }, + use = { Unit.suspend() }, + release = { _, exitCase -> + require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } + } + ) - // Wait until the fiber is started before cancelling - start.await() - f.cancel() - exit.await().shouldBeInstanceOf() + // Signal that fiber can be cancelled running + start.complete(Unit) + awaitCancellation() } - "cancel on bracketCase releases with suspending acquire" { - val start = CompletableDeferred() - val exit = CompletableDeferred() + // Wait until the fiber is started before cancelling + start.await() + f.cancel() + exit.await() shouldBe ExitCase.Completed + } + + @Test + fun acquireOnBracketCaseIsNotCancellable() = runTest { + checkAll(Arb.int(), Arb.int()) { x, y -> + val mVar = Channel(1).apply { send(x) } + val latch = CompletableDeferred() + val p = CompletableDeferred() - val f = async { + val fiber = async { bracketCase( - acquire = { Unit.suspend() }, - use = { - // Signal that fiber is running - start.complete(Unit) - awaitCancellation() + acquire = { + latch.complete(Unit) + // This should be uncancellable, and suspends until capacity 1 is received + mVar.send(y) }, - release = { _, exitCase -> - require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } - } + use = { awaitCancellation() }, + release = { _, exitCase -> require(p.complete(exitCase)) } ) } - // Wait until the fiber is started before cancelling - start.await() - f.cancel() - exit.await().shouldBeInstanceOf() + // Wait until acquire started + latch.await() + async { fiber.cancel() } + + mVar.receive() shouldBe x + mVar.receive() shouldBe y + p.await().shouldBeInstanceOf() } + } - "cancel on bracketCase doesn't invoke after finishing" { - val start = CompletableDeferred() - val exit = CompletableDeferred() + @Test + fun releaseOnBracketCaseIsNotCancellable() = runTest { + checkAll(Arb.int(), Arb.int()) { x, y -> + val mVar = Channel(1).apply { send(x) } + val latch = CompletableDeferred() - val f = async { + val fiber = async { bracketCase( - acquire = { Unit }, - use = { Unit.suspend() }, - release = { _, exitCase -> - require(exit.complete(exitCase)) { "Release should only be called once, called again with $exitCase" } - } + acquire = { latch.complete(Unit) }, + use = { awaitCancellation() }, + release = { _, _ -> mVar.send(y) } ) - - // Signal that fiber can be cancelled running - start.complete(Unit) - awaitCancellation() - } - - // Wait until the fiber is started before cancelling - start.await() - f.cancel() - exit.await() shouldBe ExitCase.Completed - } - - "acquire on bracketCase is not cancellable" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val mVar = Channel(1).apply { send(x) } - val latch = CompletableDeferred() - val p = CompletableDeferred() - - val fiber = async { - bracketCase( - acquire = { - latch.complete(Unit) - // This should be uncancellable, and suspends until capacity 1 is received - mVar.send(y) - }, - use = { awaitCancellation() }, - release = { _, exitCase -> require(p.complete(exitCase)) } - ) - } - - // Wait until acquire started - latch.await() - async { fiber.cancel() } - - mVar.receive() shouldBe x - mVar.receive() shouldBe y - p.await().shouldBeInstanceOf() } - } - "release on bracketCase is not cancellable" { - checkAll(Arb.int(), Arb.int()) { x, y -> - val mVar = Channel(1).apply { send(x) } - val latch = CompletableDeferred() - - val fiber = async { - bracketCase( - acquire = { latch.complete(Unit) }, - use = { awaitCancellation() }, - release = { _, _ -> mVar.send(y) } - ) - } - - latch.await() - async { fiber.cancel() } + latch.await() + async { fiber.cancel() } - mVar.receive() shouldBe x - // If release was cancelled this hangs since the buffer is empty - mVar.receive() shouldBe y - } + mVar.receive() shouldBe x + // If release was cancelled this hangs since the buffer is empty + mVar.receive() shouldBe y } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CircuitBreakerTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CircuitBreakerTest.kt deleted file mode 100644 index 80026b0c88e..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CircuitBreakerTest.kt +++ /dev/null @@ -1,333 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.Either -import io.kotest.assertions.asClue -import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.delay -import kotlinx.coroutines.withContext -import kotlin.time.Duration -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.minutes -import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime - -@ExperimentalTime -class CircuitBreakerTest : StringSpec({ - val dummy = RuntimeException("dummy") - val maxFailures = 5 - val exponentialBackoffFactor = 2.0 - val resetTimeout = 200.milliseconds - val maxTimeout = 600.milliseconds - - "should work for successful async tasks" { - val cb = CircuitBreaker.of(maxFailures = maxFailures, resetTimeout = resetTimeout) - var effect = 0 - Schedule.recurs(10_000).repeat { - cb.protectOrThrow { withContext(Dispatchers.Default) { effect += 1 } } - } - effect shouldBe 10_001 - } - - "should work for successful immediate tasks" { - val cb = CircuitBreaker.of(maxFailures = maxFailures, resetTimeout = resetTimeout) - var effect = 0 - Schedule.recurs(10_000).repeat { - cb.protectOrThrow { effect += 1 } - } - effect shouldBe 10_001 - } - - "Circuit breaker stays closed after less than maxFailures" { - val cb = CircuitBreaker.of(maxFailures = maxFailures, resetTimeout = resetTimeout) - - recurAndCollect>(3).repeat { - Either.catch { cb.protectOrThrow { throw dummy } } - } shouldBe (0..3).map { Either.Left(dummy) } - - cb.state() shouldBe CircuitBreaker.State.Closed(4) - } - - "Closed circuit breaker resets failure count after success" { - val cb = CircuitBreaker.of(maxFailures = maxFailures, resetTimeout = resetTimeout) - - recurAndCollect>(3).repeat { - Either.catch { cb.protectOrThrow { throw dummy } } - } shouldBe (0..3).map { Either.Left(dummy) } - - cb.state() shouldBe CircuitBreaker.State.Closed(4) - - cb.protectOrThrow { 1 } shouldBe 1 - - cb.state() shouldBe CircuitBreaker.State.Closed(0) - } - - "Circuit breaker opens after max failures" { - val cb = CircuitBreaker.of(maxFailures = maxFailures, resetTimeout = resetTimeout) - - recurAndCollect>(3).repeat { - Either.catch { cb.protectOrThrow { throw dummy } } - } shouldBe (0..3).map { Either.Left(dummy) } - - cb.state() shouldBe CircuitBreaker.State.Closed(4) - - Either.catch { cb.protectOrThrow { throw dummy } } shouldBe Either.Left(dummy) - - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - } - - "Circuit breaker can be closed again after waiting resetTimeOut" { - var openedCount = 0 - var closedCount = 0 - var halfOpenCount = 0 - var rejectedCount = 0 - - val cb = CircuitBreaker.of( - maxFailures = maxFailures, - resetTimeout = resetTimeout, - exponentialBackoffFactor = exponentialBackoffFactor, - maxResetTimeout = maxTimeout - ).doOnOpen { openedCount += 1 } - .doOnClosed { closedCount += 1 } - .doOnHalfOpen { halfOpenCount += 1 } - .doOnRejectedTask { rejectedCount += 1 } - - // CircuitBreaker opens after 4 failures - recurAndCollect(4).repeat { Either.catch { cb.protectOrThrow { throw dummy } } } - - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - - // If CircuitBreaker is Open our tasks our rejected - shouldThrow { - cb.protectOrThrow { throw dummy } - } - - // After resetTimeout passes, CB should still be Open, and we should be able to reset to Closed. - delay(resetTimeout + 10.milliseconds) - - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - - val checkHalfOpen = CompletableDeferred() - val delayProtectLatch = CompletableDeferred() - val stateAssertionLatch = CompletableDeferred() - - @Suppress("DeferredResultUnused") - async { // Successful tasks puts circuit breaker back in HalfOpen - cb.protectOrThrow { - checkHalfOpen.complete(Unit) - delayProtectLatch.await() - } // Delay protect, to inspect HalfOpen state. - stateAssertionLatch.complete(Unit) - } - - checkHalfOpen.await() - - when (val s = cb.state()) { - is CircuitBreaker.State.HalfOpen -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.HalfOpen but found $s") - } - - // Rejects all other tasks in HalfOpen - shouldThrow { cb.protectOrThrow { throw dummy } } - shouldThrow { cb.protectOrThrow { throw dummy } } - - // Once we complete `protect`, the circuit breaker will go back to closer state - delayProtectLatch.complete(Unit) - stateAssertionLatch.await() - - // Circuit breaker should be reset after successful task. - cb.state() shouldBe CircuitBreaker.State.Closed(0) - - rejectedCount shouldBe 3 // 3 tasks were rejected in total - openedCount shouldBe 1 // Circuit breaker opened once - halfOpenCount shouldBe 1 // Circuit breaker went into halfOpen once - closedCount shouldBe 1 // Circuit breaker closed once after it opened - } - - "Circuit breaker stays open with failure after resetTimeOut" { - var openedCount = 0 - var closedCount = 0 - var halfOpenCount = 0 - var rejectedCount = 0 - - val cb = CircuitBreaker.of( - maxFailures = maxFailures, - resetTimeout = resetTimeout, - exponentialBackoffFactor = 2.0, - maxResetTimeout = maxTimeout - ).doOnOpen { openedCount += 1 } - .doOnClosed { closedCount += 1 } - .doOnHalfOpen { halfOpenCount += 1 } - .doOnRejectedTask { rejectedCount += 1 } - - // CircuitBreaker opens after 4 failures - recurAndCollect(4).repeat { Either.catch { cb.protectOrThrow { throw dummy } } } - - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - - // If CircuitBreaker is Open our tasks our rejected - shouldThrow { - cb.protectOrThrow { throw dummy } - } - - // After resetTimeout passes, CB should still be Open, and we should be able to reset to Closed. - delay(resetTimeout + 10.milliseconds) - - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - - val checkHalfOpen = CompletableDeferred() - val delayProtectLatch = CompletableDeferred() - val stateAssertionLatch = CompletableDeferred() - - @Suppress("DeferredResultUnused") - async { // Successful tasks puts circuit breaker back in HalfOpen - // Delay protect, to inspect HalfOpen state. - Either.catch { - cb.protectOrThrow { - checkHalfOpen.complete(Unit) - delayProtectLatch.await(); throw dummy - } - } - stateAssertionLatch.complete(Unit) - } - - checkHalfOpen.await() - - when (val s = cb.state()) { - is CircuitBreaker.State.HalfOpen -> { - s.resetTimeout shouldBe resetTimeout - } - else -> fail("Invalid state: Expect CircuitBreaker.State.HalfOpen but found $s") - } - - // Rejects all other tasks in HalfOpen - shouldThrow { cb.protectOrThrow { throw dummy } } - shouldThrow { cb.protectOrThrow { throw dummy } } - - // Once we complete `protect`, the circuit breaker will go back to closer state - delayProtectLatch.complete(Unit) - stateAssertionLatch.await() - - // Circuit breaker should've stayed open on failure after timeOutReset - // resetTimeout should've applied - when (val s = cb.state()) { - is CircuitBreaker.State.Open -> { - s.resetTimeout shouldBe resetTimeout * exponentialBackoffFactor - } - else -> fail("Invalid state: Expect CircuitBreaker.State.Open but found $s") - } - - rejectedCount shouldBe 3 // 3 tasks were rejected in total - openedCount shouldBe 2 // Circuit breaker opened once - halfOpenCount shouldBe 1 // Circuit breaker went into halfOpen once - closedCount shouldBe 0 // Circuit breaker closed once after it opened - } - - "should be stack safe for successful async tasks" { - stackSafeSuspend( - CircuitBreaker.of(maxFailures = 5, resetTimeout = 1.minutes), - stackSafeIteration(), 0 - ) shouldBe stackSafeIteration() - } - - "should be stack safe for successful immediate tasks" { - stackSafeImmediate( - CircuitBreaker.of(maxFailures = 5, resetTimeout = 1.minutes), - stackSafeIteration(), 0 - ) shouldBe stackSafeIteration() - } - - listOf( - ConstructorValues(maxFailures = -1), - ConstructorValues(resetTimeout = Duration.ZERO), - ConstructorValues(resetTimeout = (-1).seconds), - ConstructorValues(exponentialBackoffFactor = 0.0), - ConstructorValues(exponentialBackoffFactor = -1.0), - ConstructorValues(maxResetTimeout = Duration.ZERO), - ConstructorValues(maxResetTimeout = (-1).seconds), - ).forEach { value -> - "should require valid constructor values" { - value.asClue { (maxFailures, resetTimeout, exponentialBackoffFactor, maxResetTimeout) -> - shouldThrow { - CircuitBreaker.of(maxFailures, resetTimeout, exponentialBackoffFactor, maxResetTimeout) - } - - shouldThrow { - CircuitBreaker.of( - maxFailures, - resetTimeout, - exponentialBackoffFactor, - maxResetTimeout - ) - } - - shouldThrow { - CircuitBreaker.of( - maxFailures, - resetTimeout, - exponentialBackoffFactor, - maxResetTimeout - ) - } - } - } - } - } -) - -private data class ConstructorValues( - val maxFailures: Int = 1, - val resetTimeout: Duration = 1.seconds, - val exponentialBackoffFactor: Double = 1.0, - val maxResetTimeout: Duration = Duration.INFINITE, -) - -/** - * Recurs the effect [n] times, and collects the output along the way for easy asserting. - */ -fun recurAndCollect(n: Int): Schedule> = - Schedule.recurs(n).zipRight(Schedule.identity().collect()) - -tailrec suspend fun stackSafeSuspend(cb: CircuitBreaker, n: Int, acc: Int): Int = - if (n > 0) { - val s = cb.protectOrThrow { withContext(Dispatchers.Default) { acc + 1 } } - stackSafeSuspend(cb, n - 1, s) - } else acc - -tailrec suspend fun stackSafeImmediate(cb: CircuitBreaker, n: Int, acc: Int): Int = - if (n > 0) { - val s = cb.protectOrThrow { acc + 1 } - stackSafeImmediate(cb, n - 1, s) - } else acc diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CountDownLatchSpec.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CountDownLatchSpec.kt index b39b93397c8..738c48ffdb0 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CountDownLatchSpec.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CountDownLatchSpec.kt @@ -1,7 +1,6 @@ package arrow.fx.coroutines import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.nulls.shouldBeNull import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -13,58 +12,67 @@ import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withTimeoutOrNull +import kotlin.test.Test -class CountDownLatchSpec : StringSpec({ - "should raise an exception when constructed with a negative or zero capacity" { +class CountDownLatchSpec { + @Test + fun shouldRaiseAnExceptionWhenConstructedWithNegativeOrZeroCapacity() = runTest { checkAll(Arb.long(Long.MIN_VALUE, 0)) { i -> shouldThrow { CountDownLatch(i) }.message shouldBe "CountDownLatch must be constructed with positive non-zero initial count, but was $i" } } - - "release and then await should complete" { - checkAll(Arb.long(1, 100)) { count -> + + @Test + fun releaseAndThenAwaitShouldComplete() = runTest { + checkAll(Arb.long(1, 20)) { count -> val latch = CountDownLatch(count) repeat(count.toInt()) { latch.countDown() } latch.await() shouldBe Unit } } - - "await and then release should complete" { - checkAll(Arb.long(1, 100)) { count -> + + @Test + fun awaitAndThenReleaseShouldComplete() = runTest { + checkAll(Arb.long(1, 20)) { count -> val latch = CountDownLatch(count) val job = launch { latch.await() } repeat(count.toInt()) { latch.countDown() } job.join() shouldBe Unit } } - - "await with > 1 latch unreleased should block" { - checkAll(Arb.long(1, 100)) { count -> + + @Test + fun awaitWithMoreThanOneLatchUnreleasedShouldBlock() = runTest { + checkAll(Arb.long(1, 20)) { count -> val latch = CountDownLatch(count) repeat(count.toInt() - 1) { latch.countDown() } withTimeoutOrNull(1) { latch.await() }.shouldBeNull() latch.count() shouldBe 1 } } - - "multiple awaits should all complete" { - checkAll(Arb.long(1, 100)) { count -> + + @Test + fun multipleAwaitsShouldAllComplete() = runTest { + checkAll(Arb.long(1, 20)) { count -> val latch = CountDownLatch(count) val jobs = (0 until count).map { launch { latch.await() } } repeat(count.toInt()) { latch.countDown() } jobs.joinAll() } } - - "should release when latches == 0" { + + @Test + fun shouldReleaseWhenLatchesEqualsZero() = runTest { val latch = CountDownLatch(1) latch.countDown() latch.countDown() } - - "await is cancelable" { + + @Test + fun awaitIsCancelable() = runTest { val latch = CountDownLatch(1) val exit = CompletableDeferred() val job = launch(start = CoroutineStart.UNDISPATCHED) { @@ -74,4 +82,4 @@ class CountDownLatchSpec : StringSpec({ exit.isCompleted shouldBe true exit.await().shouldBeTypeOf() } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CyclicBarrierSpec.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CyclicBarrierSpec.kt index d92530df839..c678fa690e8 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CyclicBarrierSpec.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/CyclicBarrierSpec.kt @@ -2,7 +2,6 @@ package arrow.fx.coroutines import arrow.core.Either import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf import io.kotest.property.Arb @@ -13,30 +12,36 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.CoroutineStart import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class CyclicBarrierSpec : StringSpec({ - "should raise an exception when constructed with a negative or zero capacity" { +class CyclicBarrierSpec { + @Test + fun shouldRaiseAnExceptionWhenConstructedWithNegativeOrZeroCapacity() = runTest { checkAll(Arb.int(Int.MIN_VALUE, 0)) { i -> shouldThrow { CyclicBarrier(i) }.message shouldBe "Cyclic barrier must be constructed with positive non-zero capacity $i but was $i > 0" } } - "barrier of capacity 1 is a no op" { + @Test + fun barrierOfCapacity1IsANoOp() = runTest { checkAll(Arb.constant(Unit)) { val barrier = CyclicBarrier(1) barrier.await() } } - "awaiting all in parallel resumes all coroutines" { - checkAll(Arb.int(1, 100)) { i -> + @Test + fun awaitingAllInParallelResumesAllCoroutines() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(1, 20)) { i -> val barrier = CyclicBarrier(i) (0 until i).parMap { barrier.await() } } } - "should reset once full" { + @Test + fun shouldResetOnceFull() = runTestUsingDefaultDispatcher { checkAll(Arb.constant(Unit)) { val barrier = CyclicBarrier(2) parZip({ barrier.await() }, { barrier.await() }) { _, _ -> } @@ -44,7 +49,8 @@ class CyclicBarrierSpec : StringSpec({ } } - "executes runnable once full" { + @Test + fun executesRunnableOnceFull() = runTestUsingDefaultDispatcher { var barrierRunnableInvoked = false val barrier = CyclicBarrier(2) { barrierRunnableInvoked = true } parZip({ barrier.await() }, { barrier.await() }) { _, _ -> } @@ -52,7 +58,8 @@ class CyclicBarrierSpec : StringSpec({ barrierRunnableInvoked shouldBe true } - "await is cancelable" { + @Test + fun awaitIsCancelable() = runTest { checkAll(Arb.int(2, Int.MAX_VALUE)) { i -> val barrier = CyclicBarrier(i) val exitCase = CompletableDeferred() @@ -68,15 +75,17 @@ class CyclicBarrierSpec : StringSpec({ } } - "should clean up upon cancellation of await" { + @Test + fun shouldCleanUpUponCancellationOfAwait() = runTest { checkAll(Arb.constant(Unit)) { val barrier = CyclicBarrier(2) launch(start = CoroutineStart.UNDISPATCHED) { barrier.await() }.cancelAndJoin() } } - "reset cancels all awaiting" { - checkAll(Arb.int(2, 100)) { i -> + @Test + fun resetCancelsAllAwaiting() = runTest { + checkAll(Arb.int(2, 20)) { i -> val barrier = CyclicBarrier(i) val exitCase = CompletableDeferred() @@ -92,8 +101,9 @@ class CyclicBarrierSpec : StringSpec({ } } - "should clean up upon reset" { - checkAll(Arb.int(2, 100)) { i -> + @Test + fun shouldCleanUpUponReset() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(2, 20)) { i -> val barrier = CyclicBarrier(i) val exitCase = CompletableDeferred() @@ -107,7 +117,8 @@ class CyclicBarrierSpec : StringSpec({ } } - "race fiber cancel and barrier full" { + @Test + fun raceFiberCancelAndBarrierFull() = runTestUsingDefaultDispatcher { checkAll(Arb.constant(Unit)) { val barrier = CyclicBarrier(2) val job = launch(start = CoroutineStart.UNDISPATCHED) { barrier.await() } @@ -120,7 +131,8 @@ class CyclicBarrierSpec : StringSpec({ } } - "reset" { + @Test + fun reset() = runTest { checkAll(Arb.int(2..10)) { n -> val barrier = CyclicBarrier(n) @@ -128,7 +140,7 @@ class CyclicBarrierSpec : StringSpec({ val jobs = (0 until n - 1).map { i -> launch(start = CoroutineStart.UNDISPATCHED) { - guaranteeCase(barrier::await, exits[i]::complete) + guaranteeCase({ barrier.await() }, exits[i]::complete) } } @@ -140,4 +152,4 @@ class CyclicBarrierSpec : StringSpec({ } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/FlowTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/FlowTest.kt index 7a2e6448d94..8c4f3baf500 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/FlowTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/FlowTest.kt @@ -1,18 +1,12 @@ package arrow.fx.coroutines import io.kotest.assertions.fail -import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.longs.shouldBeGreaterThanOrEqual -import io.kotest.matchers.longs.shouldBeLessThan 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.map -import io.kotest.property.arbitrary.positiveInt +import io.kotest.property.arbitrary.long import io.kotest.property.checkAll -import kotlin.time.ExperimentalTime import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview @@ -23,365 +17,319 @@ import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.reduce import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toSet import kotlinx.coroutines.launch import kotlinx.coroutines.test.advanceTimeBy -import kotlinx.coroutines.test.currentTime import kotlinx.coroutines.test.runTest +import kotlinx.coroutines.test.testTimeSource import kotlinx.coroutines.withTimeoutOrNull +import kotlin.test.Test +import kotlin.time.ComparableTimeMark +import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.ExperimentalTime @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) -@ExperimentalTime -class FlowTest : StringSpec({ - - "Retry - flow fails" { - val bang = RuntimeException("Bang!") - - checkAll(Arb.int(), Arb.positiveInt(10)) { a, n -> - var counter = 0 - val e = assertThrowable { - flow { - emit(a) - if (++counter <= 11) throw bang - }.retry(Schedule.recurs(n)) - .collect() - } - e shouldBe bang - } - } +class FlowTest { - "Retry - flow succeeds" { - checkAll(Arb.int(), Arb.int(5, 10)) { a, n -> - var counter = 0 - val sum = flow { - emit(a) - if (++counter <= 5) throw RuntimeException("Bang!") - }.retry(Schedule.recurs(n)) - .reduce { acc, int -> acc + int } - - sum shouldBe a * 6 - } + @Test + fun parMapConcurrentEqualOneMinusIdentity() = runTestUsingDefaultDispatcher { + checkAll(Arb.flow(Arb.int(), range = 1 .. 20)) { flow -> + flow.parMap(1) { it } + .toList() shouldBe flow.toList() } + } - "parMap - concurrency = 1 - identity" { - checkAll(Arb.flow(Arb.int())) { flow -> - flow.parMap(1) { it } - .toList() shouldBe flow.toList() - } + @Test + fun parMapRunsInParallel() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int(1..2)) { i, n -> + val latch = CompletableDeferred() + flowOf(1, 2).parMap { index -> + if (index == n) latch.await() + else { + latch.complete(i) + null + } + }.toList().filterNotNull() shouldBe listOf(i) } + } - "parMap - runs in parallel" { - checkAll(Arb.int(), Arb.int(1..2)) { i, n -> - val latch = CompletableDeferred() - flowOf(1, 2).parMap { index -> - if (index == n) latch.await() - else { - latch.complete(i) - null - } - }.toList().filterNotNull() shouldBe listOf(i) - } + @Test + fun parMapTriggersCancelSignal() = runTestUsingDefaultDispatcher { + val latch = CompletableDeferred() + val exit = CompletableDeferred() + + val job = launch { + flowOf(1).parMap { _ -> + guaranteeCase({ + latch.complete(Unit) + awaitCancellation() + }, { ex -> exit.complete(ex) }) + }.collect() } + latch.await() + job.cancelAndJoin() + job.isCancelled shouldBe true + exit.await().shouldBeTypeOf() + } - "parMap - triggers cancel signal" { - val latch = CompletableDeferred() - val exit = CompletableDeferred() + @Test + fun parMapExceptionInParMapCancelsAllRunningTasks() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable(), Arb.int(1..2)) { i, e, n -> + val latch = CompletableDeferred() + val exit = CompletableDeferred>() - val job = launch { - flowOf(1).parMap { _ -> + assertThrowable { + flowOf(1, 2).parMap { index -> + if (index == n) { guaranteeCase({ latch.complete(Unit) awaitCancellation() - }, { ex -> exit.complete(ex) }) - }.collect() - } - latch.await() - job.cancelAndJoin() - job.isCancelled shouldBe true - exit.await().shouldBeTypeOf() - } + }, { ex -> exit.complete(Pair(i, ex)) }) + } else { + latch.await() + throw e + } + }.collect() + fail("Cannot reach here. $e should be thrown.") + } shouldBe e - "parMap - exception in parMap cancels all running tasks" { - checkAll(Arb.int(), Arb.throwable(), Arb.int(1..2)) { i, e, n -> - val latch = CompletableDeferred() - val exit = CompletableDeferred>() - - assertThrowable { - flowOf(1, 2).parMap { index -> - if (index == n) { - guaranteeCase({ - latch.complete(Unit) - awaitCancellation() - }, { ex -> exit.complete(Pair(i, ex)) }) - } else { - latch.await() - throw e - } - }.collect() - fail("Cannot reach here. $e should be thrown.") - } shouldBe e - - val (ii, ex) = exit.await() - ii shouldBe i - ex.shouldBeTypeOf() - } + val (ii, ex) = exit.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parMap - Cancelling parMap cancels all running jobs" { - checkAll(Arb.int(), Arb.int()) { i, i2 -> - val latch = CompletableDeferred() - val exitA = CompletableDeferred>() - val exitB = CompletableDeferred>() + @Test + fun parMapCancellingParMapCancelsAllRunningJobs() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { i, i2 -> + val latch = CompletableDeferred() + val exitA = CompletableDeferred>() + val exitB = CompletableDeferred>() - val job = launch { - flowOf(1, 2).parMap { index -> - guaranteeCase({ - if (index == 2) latch.complete(Unit) - awaitCancellation() - }, { ex -> - if (index == 1) exitA.complete(Pair(i, ex)) - else exitB.complete(Pair(i2, ex)) - }) - }.collect() - } + val job = launch { + flowOf(1, 2).parMap { index -> + guaranteeCase({ + if (index == 2) latch.complete(Unit) + awaitCancellation() + }, { ex -> + if (index == 1) exitA.complete(Pair(i, ex)) + else exitB.complete(Pair(i2, ex)) + }) + }.collect() + } - latch.await() - job.cancel() + latch.await() + job.cancel() - val (ii, ex) = exitA.await() - ii shouldBe i - ex.shouldBeTypeOf() + val (ii, ex) = exitA.await() + ii shouldBe i + ex.shouldBeTypeOf() - val (ii2, ex2) = exitB.await() - ii2 shouldBe i2 - ex2.shouldBeTypeOf() - } + val (ii2, ex2) = exitB.await() + ii2 shouldBe i2 + ex2.shouldBeTypeOf() } + } - "parMapUnordered - concurrency = 1 - identity" { - checkAll(Arb.flow(Arb.int())) { flow -> - flow.parMapUnordered(concurrency = 1) { it } - .toSet() shouldBe flow.toSet() - } + @Test + fun parMapUnorderedConcurrentEqualOneMinusIdentity() = runTestUsingDefaultDispatcher { + checkAll(Arb.flow(Arb.int(), range = 1 .. 20)) { flow -> + flow.parMapUnordered(concurrency = 1) { it } + .toSet() shouldBe flow.toSet() } + } - "parMapUnordered - runs in parallel" { - checkAll(Arb.int(), Arb.int(1..2)) { i, n -> - val latch = CompletableDeferred() - flowOf(1, 2).parMapUnordered { index -> - if (index == n) latch.await() - else { - latch.complete(i) - null - } - }.toSet().filterNotNull() shouldBe setOf(i) - } + @Test + fun parMapUnorderedRunsInParallel() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int(1..2)) { i, n -> + val latch = CompletableDeferred() + flowOf(1, 2).parMapUnordered { index -> + if (index == n) latch.await() + else { + latch.complete(i) + null + } + }.toSet().filterNotNull() shouldBe setOf(i) } + } + + @Test + fun parMapUnorderedTriggersCancelSignal() = runTestUsingDefaultDispatcher { + val latch = CompletableDeferred() + val exit = CompletableDeferred() + + val job = launch { + flowOf(1).parMapUnordered { _ -> + guaranteeCase({ + latch.complete(Unit) + awaitCancellation() + }, { ex -> exit.complete(ex) }) + }.collect() + } + latch.await() + job.cancelAndJoin() - "parMapUnordered - triggers cancel signal" { - val latch = CompletableDeferred() - val exit = CompletableDeferred() + job.isCancelled shouldBe true + exit.await().shouldBeTypeOf() + } - val job = launch { - flowOf(1).parMapUnordered { + @Test + fun parMapUnorderedExceptionInParMapCancelsAllRunningTasks() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable(), Arb.int(1..2)) { i, e, n -> + val latch = CompletableDeferred() + val exit = CompletableDeferred>() + + assertThrowable { + flowOf(1, 2).parMapUnordered { index -> + if (index == n) { guaranteeCase({ latch.complete(Unit) awaitCancellation() - }, { ex -> exit.complete(ex) }) - }.collect() - } - latch.await() - job.cancelAndJoin() + }, { ex -> exit.complete(Pair(i, ex)) }) + } else { + latch.await() + throw e + } + }.collect() + fail("Cannot reach here. $e should be thrown.") + } shouldBe e - job.isCancelled shouldBe true - exit.await().shouldBeTypeOf() + val (ii, ex) = exit.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parMapUnordered - exception in parMap cancels all running tasks" { - checkAll(Arb.int(), Arb.throwable(), Arb.int(1..2)) { i, e, n -> - val latch = CompletableDeferred() - val exit = CompletableDeferred>() - - assertThrowable { - flowOf(1, 2).parMapUnordered { index -> - if (index == n) { - guaranteeCase({ - latch.complete(Unit) - awaitCancellation() - }, { ex -> exit.complete(Pair(i, ex)) }) - } else { - latch.await() - throw e - } - }.collect() - fail("Cannot reach here. $e should be thrown.") - } shouldBe e - - val (ii, ex) = exit.await() - ii shouldBe i - ex.shouldBeTypeOf() + @Test + fun parMapUnorderedCancellingParMapCancelsAllRunningJobs() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { i, i2 -> + val latch = CompletableDeferred() + val exitA = CompletableDeferred>() + val exitB = CompletableDeferred>() + + val job = launch { + flowOf(1, 2).parMapUnordered { index -> + guaranteeCase({ + if (index == 2) latch.complete(Unit) + awaitCancellation() + }, { ex -> + if (index == 1) exitA.complete(Pair(i, ex)) + else exitB.complete(Pair(i2, ex)) + }) + }.collect() } - } - "parMapUnordered - Cancelling parMap cancels all running jobs" { - checkAll(Arb.int(), Arb.int()) { i, i2 -> - val latch = CompletableDeferred() - val exitA = CompletableDeferred>() - val exitB = CompletableDeferred>() + latch.await() + job.cancel() - val job = launch { - flowOf(1, 2).parMapUnordered { index -> - guaranteeCase({ - if (index == 2) latch.complete(Unit) - awaitCancellation() - }, { ex -> - if (index == 1) exitA.complete(Pair(i, ex)) - else exitB.complete(Pair(i2, ex)) - }) - }.collect() - } + val (ii, ex) = exitA.await() + ii shouldBe i + ex.shouldBeTypeOf() - latch.await() - job.cancel() + val (ii2, ex2) = exitB.await() + ii2 shouldBe i2 + ex2.shouldBeTypeOf() + } + } - val (ii, ex) = exitA.await() - ii shouldBe i - ex.shouldBeTypeOf() + @Test + fun mapIndexed() = runTestUsingDefaultDispatcher { + val flow = flowOf(1, 2, 3) + .mapIndexed { index, value -> IndexedValue(index, value) } + + flow.toList() shouldBe listOf( + IndexedValue(0, 1), + IndexedValue(1, 2), + IndexedValue(2, 3) + ) + + flow.toList() shouldBe listOf( + IndexedValue(0, 1), + IndexedValue(1, 2), + IndexedValue(2, 3) + ) + } - val (ii2, ex2) = exitB.await() - ii2 shouldBe i2 - ex2.shouldBeTypeOf() - } - } - - "Retry - schedule with delay" { - runTest { - checkAll(Arb.int(), Arb.int(100, 1000)) { a, delayMs -> - val start = currentTime - val timestamps = mutableListOf() - shouldThrow { - flow { - emit(a) - timestamps.add(currentTime) - throw RuntimeException("Bang!") - } - .retry(Schedule.recurs(2) and Schedule.spaced(delayMs.milliseconds)) - .collect() - } - timestamps.size shouldBe 3 - - // total run should be between start time + delay * 3 AND start + tolerance % - val min = start + (delayMs * 2) - val max = min + delayMs / 10 - - timestamps.last() shouldBeGreaterThanOrEqual min - timestamps.last() shouldBeLessThan max - } - } - } - - "fixedDelay" { - runTest { - checkAll(Arb.positiveInt().map(Int::toLong), Arb.int(1..100)) { waitPeriod, n -> - val emissionDuration = waitPeriod / 10L - var state: Long? = null - - val rate = flow { emit(delay(waitPeriod)) }.repeat() - .map { - val now = state ?: currentTime - val nextNow = currentTime - val lapsed = nextNow - now - state = nextNow - delay(emissionDuration) - lapsed - } - .take(n) - .toList() - - rate.first() shouldBe 0 // First element is immediately - rate.drop(1).forEach { act -> - act shouldBe (waitPeriod + emissionDuration) // Remaining elements all take delay + emission duration - } - } - } - } - - "fixedRate" { - runTest { - checkAll(Arb.positiveInt().map(Int::toLong), Arb.int(1..100)) { waitPeriod, n -> - val emissionDuration = waitPeriod / 10 - var state: Long? = null - - val rate = fixedRate(waitPeriod) { currentTime } - .map { - val now = state ?: currentTime - val nextNow = currentTime - val lapsed = nextNow - now - state = nextNow - delay(emissionDuration) - lapsed - } - .take(n) - .toList() - - rate.first() shouldBe 0 // First element is immediately - rate.drop(1).forEach { act -> - // Remaining elements all take total of waitPeriod, emissionDuration is correctly taken into account. - act shouldBe waitPeriod - } + @Test @ExperimentalTime + fun fixedDelay() = runTest { + checkAll(Arb.long(10L .. 50L), Arb.int(3..20)) { waitPeriodInMillis, n -> + val waitPeriod = waitPeriodInMillis.milliseconds + val emissionDuration = (waitPeriodInMillis / 10L).milliseconds + var state: ComparableTimeMark? = null + + val rate = flow { emit(delay(waitPeriod)) }.repeat() + .map { + val now = state ?: testTimeSource.markNow() + val nextNow = testTimeSource.markNow() + val lapsed = nextNow - now + state = nextNow + delay(emissionDuration) + lapsed } + .take(n) + .toList() + + rate.first() shouldBe Duration.ZERO // First element is immediately + rate.drop(1).forEach { act -> + act shouldBe (waitPeriod + emissionDuration) // Remaining elements all take delay + emission duration } } - - "fixedRate(dampen = true)" { - runTest { - val buffer = mutableListOf() - withTimeoutOrNull(4500) { - fixedRate(1000, true) { currentTime } - .mapIndexed { index, _ -> - if (index == 0) delay(3000) else Unit - advanceTimeBy(1) - }.collect(buffer::add) + } + + @Test @ExperimentalTime + fun fixedRate() = runTest { + checkAll(Arb.long(10L..50L), Arb.int(3..20)) { waitPeriodInMillis, n -> + val waitPeriod = waitPeriodInMillis.milliseconds + val emissionDuration = (waitPeriodInMillis / 10L).milliseconds + var state: ComparableTimeMark? = null + + val rate = fixedRate(waitPeriod) { testTimeSource.markNow() } + .map { + val now = state ?: testTimeSource.markNow() + val nextNow = testTimeSource.markNow() + val lapsed = nextNow - now + state = nextNow + delay(emissionDuration) + lapsed } - buffer.size shouldBe 2 + .take(n) + .toList() + + rate.first() shouldBe Duration.ZERO // First element is immediately + rate.drop(1).forEach { act -> + // Remaining elements all take total of waitPeriod, emissionDuration is correctly taken into account. + act shouldBe waitPeriod } } - - "fixedRate(dampen = false)" { - runTest { - val buffer = mutableListOf() - withTimeoutOrNull(4500) { - fixedRate(1000, false) { currentTime } - .mapIndexed { index, _ -> - if (index == 0) delay(3000) else Unit - advanceTimeBy(1) - }.collect(buffer::add) - } - buffer.size shouldBe 4 - } + } + + + @Test @ExperimentalTime + fun fixedRateWithDampenTrue() = runTest { + val buffer = mutableListOf() + withTimeoutOrNull(4500) { + fixedRate(1000, true) { testTimeSource.markNow() } + .mapIndexed { index, _ -> + if (index == 0) delay(3000) else Unit + advanceTimeBy(1) + }.collect(buffer::add) } - - "mapIndexed" { - runTest { - val flow = flowOf(1, 2, 3) - .mapIndexed { index, value -> IndexedValue(index, value) } - - flow.toList() shouldBe listOf( - IndexedValue(0, 1), - IndexedValue(1, 2), - IndexedValue(2, 3) - ) - - flow.toList() shouldBe listOf( - IndexedValue(0, 1), - IndexedValue(1, 2), - IndexedValue(2, 3) - ) - } + buffer.size shouldBe 2 + } + + @Test @ExperimentalTime + fun fixedRateWithDampenFalse() = runTest { + val buffer = mutableListOf() + withTimeoutOrNull(4500) { + fixedRate(1000, false) { testTimeSource.markNow() } + .mapIndexed { index, _ -> + if (index == 0) delay(3000) else Unit + advanceTimeBy(1) + }.collect(buffer::add) } + buffer.size shouldBe 4 } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Generators.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Generators.kt index 8449ae0474c..98996374d23 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Generators.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Generators.kt @@ -1,9 +1,6 @@ package arrow.fx.coroutines import arrow.core.Either -import arrow.core.ValidatedNel -import arrow.core.invalidNel -import arrow.core.validNel import io.kotest.assertions.fail import io.kotest.matchers.Matcher import io.kotest.matchers.MatcherResult @@ -30,10 +27,10 @@ import kotlin.coroutines.intrinsics.intercepted import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.startCoroutine -fun Arb.Companion.flow(arbA: Arb): Arb> = +fun Arb.Companion.flow(arbA: Arb, range: IntRange = 1 .. 20): Arb> = Arb.choose( - 10 to Arb.list(arbA).map { it.asFlow() }, - 10 to Arb.list(arbA).map { channelFlow { it.forEach { send(it) } }.buffer(Channel.RENDEZVOUS) }, + 10 to Arb.list(arbA, range).map { it.asFlow() }, + 10 to Arb.list(arbA, range).map { channelFlow { it.forEach { send(it) } }.buffer(Channel.RENDEZVOUS) }, 1 to Arb.constant(emptyFlow()), ) @@ -41,7 +38,7 @@ fun Arb.Companion.functionAToB(arb: Arb): Arb<(A) -> B> = arb.map { b: B -> { _: A -> b } } fun Arb.Companion.throwable(): Arb = - Arb.of(listOf(RuntimeException(), NoSuchElementException(), IllegalArgumentException())) + Arb.of(listOf(IndexOutOfBoundsException(), NoSuchElementException(), IllegalArgumentException())) fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { val arbLeft = arbE.map { Either.Left(it) } @@ -52,12 +49,6 @@ fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { fun Arb.Companion.result(arbA: Arb): Arb> = Arb.choice(arbA.map(Result.Companion::success), throwable().map(Result.Companion::failure)) -fun Arb.Companion.validatedNel(left: Arb, right: Arb): Arb> { - val failure: Arb> = left.map { l -> l.invalidNel() } - val success: Arb> = right.map { r -> r.validNel() } - return Arb.choice(failure, success) -} - suspend fun Throwable.suspend(): Nothing = suspendCoroutineUninterceptedOrReturn { cont -> suspend { throw this }.startCoroutine( @@ -87,24 +78,24 @@ fun leftException(e: Throwable): Matcher> = is Either.Left -> when { value.value::class != e::class -> MatcherResult( false, - "Expected exception of type ${e::class} but found ${value.value::class}", - "Should not be exception of type ${e::class}" + { "Expected exception of type ${e::class} but found ${value.value::class}" }, + { "Should not be exception of type ${e::class}" } ) value.value.message != e.message -> MatcherResult( false, - "Expected exception with message ${e.message} but found ${value.value.message}", - "Should not be exception with message ${e.message}" + { "Expected exception with message ${e.message} but found ${value.value.message}" }, + { "Should not be exception with message ${e.message}" } ) else -> MatcherResult( true, - "Expected exception of type ${e::class} and found ${value.value::class}", - "Expected exception of type ${e::class} and found ${value.value::class}" + { "Expected exception of type ${e::class} and found ${value.value::class}" }, + { "Expected exception of type ${e::class} and found ${value.value::class}" } ) } is Either.Right -> MatcherResult( false, - "Expected Either.Left with exception of type ${e::class} and found Right with ${value.value}", - "Should not be Either.Left with exception" + { "Expected Either.Left with exception of type ${e::class} and found Right with ${value.value}" }, + { "Should not be Either.Left with exception" } ) } } @@ -114,10 +105,10 @@ fun either(e: Either): Matcher> = override fun test(value: Either): MatcherResult = when (value) { is Either.Left -> when { - value.value::class != (e.swap().orNull() ?: Int)::class -> MatcherResult( + value.value::class != (e.swap().getOrNull() ?: Int)::class -> MatcherResult( false, - "Expected $e but found $value (class check failed)", - "Should not be $e" + { "Expected $e but found $value (class check failed)" }, + { "Should not be $e" } ) /* there are problems matching the message value.value.message != (e.swap().orNull()?.message ?: -1) -> MatcherResult( @@ -127,8 +118,8 @@ fun either(e: Either): Matcher> = ) */ else -> MatcherResult( true, - "Expected exception of type ${e::class} and found ${value.value::class}", - "Expected exception of type ${e::class} and found ${value.value::class}" + { "Expected exception of type ${e::class} and found ${value.value::class}" }, + { "Expected exception of type ${e::class} and found ${value.value::class}" } ) } is Either.Right -> equalityMatcher(e).test(value) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/GuaranteeCaseTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/GuaranteeCaseTest.kt index 2f636a7b381..1795c98fc0f 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/GuaranteeCaseTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/GuaranteeCaseTest.kt @@ -1,7 +1,6 @@ package arrow.fx.coroutines import arrow.core.Either -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf import io.kotest.property.Arb @@ -10,55 +9,59 @@ import io.kotest.property.checkAll import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class GuaranteeCaseTest : StringSpec({ +class GuaranteeCaseTest { - "release for success was invoked" { - checkAll(Arb.int()) { i -> - val p = CompletableDeferred() - - val res = guaranteeCase( - fa = { i }, - finalizer = { ex -> require(p.complete(ex)) } - ) - - p.await() shouldBe ExitCase.Completed - res shouldBe i - } - } + @Test + fun releaseForSuccessWasInvoked() = runTest { + checkAll(Arb.int()) { i -> + val p = CompletableDeferred() - "release for error was invoked" { - checkAll(Arb.throwable()) { e -> - val p = CompletableDeferred() - val attempted = Either.catch { - guaranteeCase( - fa = { throw e }, - finalizer = { ex -> require(p.complete(ex)) } - ) - } + val res = guaranteeCase( + fa = { i }, + finalizer = { ex -> require(p.complete(ex)) } + ) - p.await() shouldBe ExitCase.Failure(e) - attempted shouldBe Either.Left(e) - } + p.await() shouldBe ExitCase.Completed + res shouldBe i } + } - "release for never was invoked" { + @Test + fun releaseForErrorWasInvoked() = runTest { + checkAll(Arb.throwable()) { e -> val p = CompletableDeferred() - val start = CompletableDeferred() - - val fiber = async { - guaranteeCase( - fa = { - start.complete(Unit) - awaitCancellation() - }, + val attempted = Either.catch { + guaranteeCase( + fa = { throw e }, finalizer = { ex -> require(p.complete(ex)) } ) } - start.await() - fiber.cancel() - p.await().shouldBeInstanceOf() + p.await() shouldBe ExitCase.Failure(e) + attempted shouldBe Either.Left(e) } } -) + + @Test + fun releaseForNeverWasInvoked() = runTest { + val p = CompletableDeferred() + val start = CompletableDeferred() + + val fiber = async { + guaranteeCase( + fa = { + start.complete(Unit) + awaitCancellation() + }, + finalizer = { ex -> require(p.complete(ex)) } + ) + } + + start.await() + fiber.cancel() + p.await().shouldBeInstanceOf() + } +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/KotestConfig.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/KotestConfig.kt deleted file mode 100644 index e2c196cdbed..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/KotestConfig.kt +++ /dev/null @@ -1,10 +0,0 @@ -package arrow.fx.coroutines - -import io.kotest.core.config.AbstractProjectConfig -import io.kotest.property.PropertyTesting - -class KotestConfig : AbstractProjectConfig() { - override suspend fun beforeProject() { - PropertyTesting.defaultIterationCount = 250 - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParMapTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParMapTest.kt index 0ee57f17021..5a925875cd2 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParMapTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParMapTest.kt @@ -13,13 +13,13 @@ import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll import kotlin.test.Test -import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.test.runTest +import kotlin.time.Duration.Companion.milliseconds class ParMapTest { - @Test fun parMapIsStackSafe() = runTestWithDelay { + @Test fun parMapIsStackSafe() = runTestUsingDefaultDispatcher { val count = stackSafeIteration() val ref = AtomicInt(0) (0 until count).parMap { _: Int -> @@ -28,7 +28,7 @@ class ParMapTest { ref.get() shouldBe count } - @Test fun parMapRunsInParallel() = runTest { + @Test fun parMapRunsInParallel() = runTestUsingDefaultDispatcher { val promiseA = CompletableDeferred() val promiseB = CompletableDeferred() val promiseC = CompletableDeferred() @@ -49,7 +49,7 @@ class ParMapTest { ).parMap { it.invoke() } } - @Test fun parTraverseResultsInTheCorrectError() = runTest { + @Test fun parTraverseResultsInTheCorrectError() = runTestUsingDefaultDispatcher { checkAll( Arb.int(min = 10, max = 20), Arb.int(min = 1, max = 9), @@ -74,7 +74,7 @@ class ParMapTest { } shouldBe null } - @Test fun parMapWithEitherResultsInTheCorrectLeft() = runTest { + @Test fun parMapWithEitherResultsInTheCorrectLeft() = runTestUsingDefaultDispatcher { checkAll( Arb.int(min = 10, max = 20), Arb.int(min = 1, max = 9), @@ -88,7 +88,7 @@ class ParMapTest { } } - @Test fun parMapOrAccumulateIsStackSafe() = runTestWithDelay { + @Test fun parMapOrAccumulateIsStackSafe() = runTestUsingDefaultDispatcher { val count = stackSafeIteration() val ref = AtomicInt(0) (0 until count).parMapOrAccumulate(combine = emptyError) { _: Int -> @@ -118,7 +118,7 @@ class ParMapTest { ).parMapOrAccumulate(combine = emptyError) { it.invoke() } } - @Test fun parMapOrAccumulateResultsInTheCorrectError() = runTest { + @Test fun parMapOrAccumulateResultsInTheCorrectError() = runTestUsingDefaultDispatcher { checkAll( Arb.int(min = 10, max = 20), Arb.int(min = 1, max = 9), @@ -143,7 +143,7 @@ class ParMapTest { } shouldBe null } - @Test fun parMapOrAccumulateAccumulatesShifts() = runTest { + @Test fun parMapOrAccumulateAccumulatesShifts() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { e -> (0 until 10).parMapOrAccumulate { _ -> raise(e) @@ -151,7 +151,7 @@ class ParMapTest { } } - @Test fun parMapNotNullIsStackSafe() = runTestWithDelay { + @Test fun parMapNotNullIsStackSafe() = runTestUsingDefaultDispatcher { val count = stackSafeIteration() val ref = AtomicInt(0) (0 until count).parMapNotNull { _: Int -> @@ -160,7 +160,7 @@ class ParMapTest { ref.get() shouldBe count } - @Test fun parMapNotNullRunsInParallel() = runTest { + @Test fun parMapNotNullRunsInParallel() = runTestUsingDefaultDispatcher { val promiseA = CompletableDeferred() val promiseB = CompletableDeferred() val promiseC = CompletableDeferred() @@ -181,7 +181,7 @@ class ParMapTest { ).parMapNotNull { it.invoke() } } - @Test fun parMapNotNullResultsInTheCorrectError() = runTest { + @Test fun parMapNotNullResultsInTheCorrectError() = runTestUsingDefaultDispatcher { checkAll( Arb.int(min = 10, max = 20), Arb.int(min = 1, max = 9), @@ -206,13 +206,13 @@ class ParMapTest { } shouldBe null } - @Test fun parMapNotNullDiscardsNulls() = runTest { + @Test fun parMapNotNullDiscardsNulls() = runTestUsingDefaultDispatcher { (0 until 10).parMapNotNull { _ -> null } shouldBe emptyList() } - @Test fun parMapNotNullRetainsNonNulls() = runTest { + @Test fun parMapNotNullRetainsNonNulls() = runTestUsingDefaultDispatcher { checkAll(Arb.int()) { i -> (0 until 10).parMapNotNull { _ -> i diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseEitherTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseEitherTest.kt deleted file mode 100644 index ac7fa472ff7..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseEitherTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -package arrow.fx.coroutines - -import arrow.atomic.AtomicInt -import arrow.atomic.update -import arrow.core.Either -import arrow.core.left -import arrow.core.right -import arrow.core.sequence -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.should -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll -import kotlinx.coroutines.CompletableDeferred - -class ParTraverseEitherTest : StringSpec({ - "parTraverseEither can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100).parTraverseEither { - ref.update { it + 1 }.right() - } - ref.get() shouldBe 100 - } - - "parTraverseEither runs in parallel" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - listOf( - suspend { - promiseA.await() - promiseC.complete(Unit).right() - }, - suspend { - promiseB.await() - promiseA.complete(Unit).right() - }, - suspend { - promiseB.complete(Unit) - promiseC.await().right() - } - ).parTraverseEither { it() } - } - - "parTraverseEither results in the correct left" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.string() - ) { n, killOn, e -> - (0 until n).parTraverseEither { i -> - if (i == killOn) e.left() else Unit.right() - } shouldBe e.left() - } - } - - "parTraverseEither identity is identity" { - checkAll(Arb.list(Arb.either(Arb.string(), Arb.int()))) { l -> - val containsError = l.any(Either::isLeft) - val res = l.parTraverseEither { it } - - if (containsError) l.contains>(res) shouldBe true - else res shouldBe l.sequence() - } - } - - "parTraverseEither results in the correct error" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.throwable() - ) { n, killOn, e -> - Either.catch { - (0 until n).parTraverseEither { i -> - if (i == killOn) throw e else Unit.right() - } - } should leftException(e) - } - } - - "parTraverseEither stack-safe" { - val count = 20_000 - val l = (0 until count).parTraverseEither { it.right() } - l shouldBe (0 until count).toList().right() - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseResultTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseResultTest.kt deleted file mode 100644 index d53e9c7c2dd..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseResultTest.kt +++ /dev/null @@ -1,89 +0,0 @@ -package arrow.fx.coroutines - -import arrow.atomic.AtomicInt -import arrow.atomic.update -import arrow.core.Either -import arrow.core.sequence -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.collections.shouldContain -import io.kotest.matchers.result.shouldBeFailure -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.list -import io.kotest.property.arbitrary.orNull -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll -import kotlinx.coroutines.CompletableDeferred - -class ParTraverseResultTest : StringSpec({ - "parTraverseResult can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100).parTraverseResult { - Result.success(ref.update { it + 1 }) - } - ref.get() shouldBe 100 - } - - "parTraverseResult runs in parallel" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - listOf( - suspend { - promiseA.await() - Result.success(promiseC.complete(Unit)) - }, - suspend { - promiseB.await() - Result.success(promiseA.complete(Unit)) - }, - suspend { - promiseB.complete(Unit) - Result.success(promiseC.await()) - } - ).parTraverseResult { it() } - } - - "parTraverseResult results in the correct left" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9) - ) { n, killOn -> - (0 until n).parTraverseResult { i -> - if (i == killOn) Result.failure(RuntimeException()) else Result.success(Unit) - }.shouldBeFailure() - } - } - - "parTraverseResult identity is identity" { - checkAll(Arb.list(Arb.result(Arb.int()))) { l -> - val res = l.parTraverseResult { it } - if (l.any { it.isFailure }) l.shouldContain(res) - else res shouldBe l.sequence() - } - } - - "parTraverseResult results in the correct error" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.string().orNull() - ) { n, killOn, msg -> - Either.catch { - (0 until n).parTraverseResult { i -> - if (i == killOn) throw RuntimeException(msg) else Result.success(Unit) - }.let(::println) - }.shouldBeTypeOf>().value.message shouldBe msg - } - } - - "parTraverseResult stack-safe" { - val count = 20_000 - val l = (0 until count).parTraverseResult { Result.success(it) } - l shouldBe Result.success((0 until count).toList()) - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseTest.kt deleted file mode 100644 index 5d4ba2d69a1..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseTest.kt +++ /dev/null @@ -1,163 +0,0 @@ -package arrow.fx.coroutines - -import arrow.atomic.AtomicInt -import arrow.atomic.update -import arrow.core.Either -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.should -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list -import io.kotest.property.checkAll -import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.withTimeoutOrNull -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.ExperimentalTime - -@ExperimentalTime -class ParTraverseTest : StringSpec({ - - "parTraverse can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100).parTraverse { - ref.update { it + 1 } - } - ref.get() shouldBe 100 - } - - "parTraverse runs in parallel" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - listOf( - suspend { - promiseA.await() - promiseC.complete(Unit) - }, - suspend { - promiseB.await() - promiseA.complete(Unit) - }, - suspend { - promiseB.complete(Unit) - promiseC.await() - } - ).parSequence() - } - - "parTraverse results in the correct error" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.throwable() - ) { n, killOn, e -> - Either.catch { - (0 until n).parTraverse { i -> - if (i == killOn) throw e else Unit - } - } should leftException(e) - } - } - - "parTraverse identity is identity" { - checkAll(Arb.list(Arb.int())) { l -> - l.parTraverse { it } shouldBe l - } - } - - "parTraverse stack-safe" { - val count = 20_000 - val l = (0 until count).parTraverse { it } - l shouldBe (0 until count).toList() - } - - "parTraverseN can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100).parTraverseN(5) { - ref.update { it + 1 } - } - ref.get() shouldBe 100 - } - - "parTraverseN(3) runs in (3) parallel" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - listOf( - suspend { - promiseA.await() - promiseC.complete(Unit) - }, - suspend { - promiseB.await() - promiseA.complete(Unit) - }, - suspend { - promiseB.complete(Unit) - promiseC.await() - } - ).parSequenceN(3) - } - - "parTraverseN(1) times out running 3 tasks" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - withTimeoutOrNull(10.milliseconds) { - listOf( - suspend { - promiseA.await() - promiseC.complete(Unit) - }, - suspend { - promiseB.await() - promiseA.complete(Unit) - }, - suspend { - promiseB.complete(Unit) - promiseC.await() - } - ).parSequenceN(1) - } shouldBe null - } - - "parTraverseN identity is identity" { - checkAll(Arb.list(Arb.int())) { l -> - l.parTraverseN(5) { it } shouldBe l - } - } - - "parTraverseN results in the correct error" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.throwable() - ) { n, killOn, e -> - Either.catch { - (0 until n).parTraverseN(3) { i -> - if (i == killOn) throw e else Unit - } - } should leftException(e) - } - } - - "parTraverseN stack-safe" { - val count = 20_000 - val l = (0 until count).parTraverseN(20) { it } - l shouldBe (0 until count).toList() - } - - "parSequenceN can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100) - .map { suspend { ref.update { it + 1 } } } - .parSequenceN(5) - - ref.get() shouldBe 100 - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedTest.kt deleted file mode 100644 index 495017a1cdd..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -package arrow.fx.coroutines - -import arrow.atomic.AtomicInt -import arrow.atomic.update -import arrow.core.Either -import arrow.core.NonEmptyList -import arrow.core.Validated -import arrow.core.invalidNel -import arrow.core.sequence -import arrow.core.validNel -import arrow.typeclasses.Semigroup -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.should -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll -import kotlinx.coroutines.CompletableDeferred - -class ParTraverseValidatedTest : StringSpec({ - "parTraverseValidated can traverse effect full computations" { - val ref = AtomicInt(0) - (0 until 100).parTraverseValidated(Semigroup.nonEmptyList()) { - ref.update { it + 1 }.validNel() - } - ref.get() shouldBe 100 - } - - "parTraverseValidated runs in parallel" { - val promiseA = CompletableDeferred() - val promiseB = CompletableDeferred() - val promiseC = CompletableDeferred() - - listOf( - suspend { - promiseA.await() - promiseC.complete(Unit).validNel() - }, - suspend { - promiseB.await() - promiseA.complete(Unit).validNel() - }, - suspend { - promiseB.complete(Unit) - promiseC.await().validNel() - } - ).parTraverseValidated(Semigroup.nonEmptyList()) { it() } - } - - "parTraverseValidated results in the correct left" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.string() - ) { n, killOn, e -> - (0 until n).parTraverseValidated(Semigroup.nonEmptyList()) { i -> - if (i == killOn) e.invalidNel() else Unit.validNel() - } shouldBe e.invalidNel() - } - } - - "parTraverseValidated identity is identity" { - checkAll(Arb.list(Arb.validatedNel(Arb.int(), Arb.int()))) { l -> - val res: Validated, List> = l.parTraverseValidated(Semigroup.nonEmptyList()) { it } - res shouldBe l.sequence(Semigroup.nonEmptyList()) - } - } - - "parTraverseValidated results in the correct error" { - checkAll( - Arb.int(min = 10, max = 20), - Arb.int(min = 1, max = 9), - Arb.throwable() - ) { n, killOn, e -> - Either.catch { - (0 until n).parTraverseValidated(Semigroup.nonEmptyList()) { i -> - if (i == killOn) throw e else Unit.validNel() - } - } should leftException(e) - } - } - - "parTraverseValidated stack-safe" { - val count = 20_000 - val l = (0 until count).parTraverseValidated(Semigroup.nonEmptyList()) { it.validNel() } - l shouldBe (0 until count).toList().validNel() - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip2Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip2Test.kt index 123057932e7..86bd3478d4f 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip2Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip2Test.kt @@ -1,14 +1,9 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.AtomicInt +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.guaranteeCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -23,93 +18,93 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.channels.Channel +import kotlin.test.Test -class ParZip2Test : StringSpec({ - "parZip 2 runs in parallel" { - checkAll(Arb.int(), Arb.int()) { a, b -> - val r = Atomic("") - val modifyGate = CompletableDeferred() +class ParZip2Test { + @Test fun parZip2RunsInParallel() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { a, b -> + val r = AtomicInt(0) + val modifyGate = CompletableDeferred() - parZip( - { - modifyGate.await() - r.update { i -> "$i$a" } - }, - { - r.set("$b") - modifyGate.complete(0) - } - ) { _a, _b -> - Pair(_a, _b) + parZip( + { + modifyGate.await() + r.update { i -> i + a } + }, + { + r.value = b + modifyGate.complete(0) } - - r.get() shouldBe "$b$a" + ) { _a, _b -> + Pair(_a, _b) } + + r.value shouldBe b + a } + } - "Cancelling parZip 2 cancels all participants" { - checkAll(Arb.int(), Arb.int()) { a, b -> - val s = Channel() - val pa = CompletableDeferred>() - val pb = CompletableDeferred>() + @Test fun cancellingParZip2CancelsAllParticipants() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { a, b -> + val s = Channel() + val pa = CompletableDeferred>() + val pb = CompletableDeferred>() - val loserA: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } - val loserB: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } + val loserA: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } + val loserB: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } - val f = async { parZip(loserA, loserB) { _a, _b -> Pair(_a, _b) } } + val f = async { parZip(loserA, loserB) { _a, _b -> Pair(_a, _b) } } - s.send(Unit) // Suspend until all racers started - s.send(Unit) - f.cancel() + s.send(Unit) // Suspend until all racers started + s.send(Unit) + f.cancel() - pa.await().let { (res, exit) -> - res shouldBe a - exit.shouldBeTypeOf() - } - pb.await().let { (res, exit) -> - res shouldBe b - exit.shouldBeTypeOf() - } + pa.await().let { (res, exit) -> + res shouldBe a + exit.shouldBeTypeOf() + } + pb.await().let { (res, exit) -> + res shouldBe b + exit.shouldBeTypeOf() } } + } - "parZip 2 cancels losers if a failure occurs in one of the tasks" { - checkAll(Arb.throwable(), Arb.boolean()) { e, leftWinner -> - val s = Channel() - val pa = CompletableDeferred() - - val winner: suspend CoroutineScope.() -> Unit = { s.send(Unit); throw e } - val loserA: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(ex) } } + @Test fun parZip2CancelsLosersIfAFailtureOccursInOneOfTheTasts() = runTestUsingDefaultDispatcher { + checkAll(Arb.throwable(), Arb.boolean()) { e, leftWinner -> + val s = Channel() + val pa = CompletableDeferred() - val r = Either.catch { - if (leftWinner) parZip(winner, loserA) { _, _ -> Unit } - else parZip(loserA, winner) { _, _ -> Unit } - } + val winner: suspend CoroutineScope.() -> Unit = { s.send(Unit); throw e } + val loserA: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(ex) } } - pa.await().shouldBeTypeOf() - r should leftException(e) + val r = Either.catch { + if (leftWinner) parZip(winner, loserA) { _, _ -> Unit } + else parZip(loserA, winner) { _, _ -> Unit } } + + pa.await().shouldBeTypeOf() + r should leftException(e) } + } - "parZip CancellationException on right can cancel rest" { - checkAll(Arb.string()) { msg -> - val exit = CompletableDeferred() - val start = CompletableDeferred() - try { - parZip({ - awaitExitCase(start, exit) - }, { - start.await() - throw CancellationException(msg) - }) { _, _ -> } - } catch (e: CancellationException) { - e.message shouldBe msg - } - exit.await().shouldBeTypeOf() + @Test fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { + checkAll(Arb.string()) { msg -> + val exit = CompletableDeferred() + val start = CompletableDeferred() + try { + parZip({ + awaitExitCase(start, exit) + }, { + start.await() + throw CancellationException(msg) + }) { _, _ -> } + } catch (e: CancellationException) { + e.message shouldBe msg } + exit.await().shouldBeTypeOf() } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip3Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip3Test.kt index bc715db2f4f..bf10afad390 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip3Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip3Test.kt @@ -1,13 +1,9 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -21,112 +17,112 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope - -class ParZip3Test : StringSpec({ - "parZip 3 runs in parallel" { - checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> - val r = Atomic("") - val modifyGate1 = CompletableDeferred() - val modifyGate2 = CompletableDeferred() - - parZip( - { - modifyGate2.await() - r.update { i -> "$i$a" } - }, - { - modifyGate1.await() - r.update { i -> "$i$b" } - modifyGate2.complete(Unit) - }, - { - r.set("$c") - modifyGate1.complete(Unit) - } - ) { _a, _b, _c -> - Triple(_a, _b, _c) +import kotlin.test.Test + +class ParZip3Test { + @Test fun parZip3RunsInParallel() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> + val r = Atomic("") + val modifyGate1 = CompletableDeferred() + val modifyGate2 = CompletableDeferred() + + parZip( + { + modifyGate2.await() + r.update { i -> "$i$a" } + }, + { + modifyGate1.await() + r.update { i -> "$i$b" } + modifyGate2.complete(Unit) + }, + { + r.value ="$c" + modifyGate1.complete(Unit) } - - r.get() shouldBe "$c$b$a" + ) { _a, _b, _c -> + Triple(_a, _b, _c) } - } - "Cancelling parZip 3 cancels all participants" { - val s = Channel() - val pa = CompletableDeferred() - val pb = CompletableDeferred() - val pc = CompletableDeferred() - - val loserA: suspend CoroutineScope.() -> Int = - { awaitExitCase(s, pa) } - val loserB: suspend CoroutineScope.() -> Int = - { awaitExitCase(s, pb) } - val loserC: suspend CoroutineScope.() -> Int = - { awaitExitCase(s, pc) } - - val f = async { parZip(loserA, loserB, loserC) { _a, _b, _c -> Triple(_a, _b, _c) } } - - s.send(Unit) // Suspend until all racers started - s.send(Unit) - s.send(Unit) - f.cancel() - - pa.await().shouldBeTypeOf() - pb.await().shouldBeTypeOf() - pc.await().shouldBeTypeOf() + r.value shouldBe "$c$b$a" } + } - "parZip 3 cancels losers if a failure occurs in one of the tasks" { - checkAll( - Arb.throwable(), - Arb.element(listOf(1, 2, 3)), - ) { e, winningTask -> - val s = Channel() - val pa = CompletableDeferred() - val pb = CompletableDeferred() - - val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); s.send(Unit); throw e } - val loserA: suspend CoroutineScope.() -> Int = - { awaitExitCase(s, pa) } - val loserB: suspend CoroutineScope.() -> Int = - { awaitExitCase(s, pb) } - - val r = Either.catch { - when (winningTask) { - 1 -> parZip(winner, loserA, loserB) { _, _, _ -> } - 2 -> parZip(loserA, winner, loserB) { _, _, _ -> } - else -> parZip(loserA, loserB, winner) { _, _, _ -> } - } - } + @Test fun cancellingParZip3CancelsAllParticipants() = runTestUsingDefaultDispatcher { + val s = Channel() + val pa = CompletableDeferred() + val pb = CompletableDeferred() + val pc = CompletableDeferred() + + val loserA: suspend CoroutineScope.() -> Int = + { awaitExitCase(s, pa) } + val loserB: suspend CoroutineScope.() -> Int = + { awaitExitCase(s, pb) } + val loserC: suspend CoroutineScope.() -> Int = + { awaitExitCase(s, pc) } + + val f = async { parZip(loserA, loserB, loserC) { _a, _b, _c -> Triple(_a, _b, _c) } } + + s.send(Unit) // Suspend until all racers started + s.send(Unit) + s.send(Unit) + f.cancel() + + pa.await().shouldBeTypeOf() + pb.await().shouldBeTypeOf() + pc.await().shouldBeTypeOf() + } - pa.await().shouldBeTypeOf() - pb.await().shouldBeTypeOf() - r should leftException(e) + @Test fun parZip3CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { + checkAll( + Arb.throwable(), + Arb.element(listOf(1, 2, 3)), + ) { e, winningTask -> + val s = Channel() + val pa = CompletableDeferred() + val pb = CompletableDeferred() + + val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); s.send(Unit); throw e } + val loserA: suspend CoroutineScope.() -> Int = + { awaitExitCase(s, pa) } + val loserB: suspend CoroutineScope.() -> Int = + { awaitExitCase(s, pb) } + + val r = Either.catch { + when (winningTask) { + 1 -> parZip(winner, loserA, loserB) { _, _, _ -> } + 2 -> parZip(loserA, winner, loserB) { _, _, _ -> } + else -> parZip(loserA, loserB, winner) { _, _, _ -> } + } } + + pa.await().shouldBeTypeOf() + pb.await().shouldBeTypeOf() + r should leftException(e) } + } - "parZip CancellationException on right can cancel rest" { - checkAll(Arb.string(), Arb.int(1..3)) { msg, cancel -> - val s = Channel() - val pa = CompletableDeferred() - val pb = CompletableDeferred() - - val winner: suspend CoroutineScope.() -> Int = { repeat(2) { s.send(Unit) }; throw CancellationException(msg) } - val loserA: suspend CoroutineScope.() -> Int = { awaitExitCase(s, pa) } - val loserB: suspend CoroutineScope.() -> Int = { awaitExitCase(s, pb) } - - try { - when (cancel) { - 1 -> parZip(winner, loserA, loserB) { _, _, _ -> } - 2 -> parZip(loserA, winner, loserB) { _, _, _ -> } - else -> parZip(loserA, loserB, winner) { _, _, _ -> } - } - } catch (e: CancellationException) { - e.message shouldBe msg + @Test fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { + checkAll(Arb.string(), Arb.int(1..3)) { msg, cancel -> + val s = Channel() + val pa = CompletableDeferred() + val pb = CompletableDeferred() + + val winner: suspend CoroutineScope.() -> Int = { repeat(2) { s.send(Unit) }; throw CancellationException(msg) } + val loserA: suspend CoroutineScope.() -> Int = { awaitExitCase(s, pa) } + val loserB: suspend CoroutineScope.() -> Int = { awaitExitCase(s, pb) } + + try { + when (cancel) { + 1 -> parZip(winner, loserA, loserB) { _, _, _ -> } + 2 -> parZip(loserA, winner, loserB) { _, _, _ -> } + else -> parZip(loserA, loserB, winner) { _, _, _ -> } } - pa.await().shouldBeTypeOf() - pb.await().shouldBeTypeOf() + } catch (e: CancellationException) { + e.message shouldBe msg } + pa.await().shouldBeTypeOf() + pb.await().shouldBeTypeOf() } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip4Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip4Test.kt index 106d0b7b3c3..11b668e7f5e 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip4Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip4Test.kt @@ -1,14 +1,10 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either import arrow.core.Tuple4 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +18,11 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope - -class ParZip4Test : StringSpec({ - "parZip 4 runs in parallel" { +import kotlin.test.Test + +class ParZip4Test { + @Test + fun parZip4RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -47,18 +45,19 @@ class ParZip4Test : StringSpec({ modifyGate3.complete(Unit) }, { - r.set("$d") + r.value = "$d" modifyGate1.complete(Unit) } ) { _a, _b, _c, _d -> Tuple4(_a, _b, _c, _d) } - r.get() shouldBe "$d$c$b$a" + r.value shouldBe "$d$c$b$a" } } - - "Cancelling parZip 4 cancels all participants" { + + @Test + fun CancellingParZip4CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -80,8 +79,9 @@ class ParZip4Test : StringSpec({ pc.await().shouldBeTypeOf() pd.await().shouldBeTypeOf() } - - "parZip 4 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip4CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4)), @@ -111,8 +111,9 @@ class ParZip4Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..4)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -140,4 +141,3 @@ class ParZip4Test : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip5Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip5Test.kt index be3b3373e33..a4ee82da26b 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip5Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip5Test.kt @@ -1,14 +1,10 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either import arrow.core.Tuple5 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +18,11 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope +import kotlin.test.Test -class ParZip5Test : StringSpec({ - "parZip 5 runs in parallel" { +class ParZip5Test { + @Test + fun parZip5RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d, e -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -53,18 +51,19 @@ class ParZip5Test : StringSpec({ modifyGate4.complete(Unit) }, { - r.set("$e") + r.value = "$e" modifyGate1.complete(Unit) } ) { _a, _b, _c, _d, _e -> Tuple5(_a, _b, _c, _d, _e) } - r.get() shouldBe "$e$d$c$b$a" + r.value shouldBe "$e$d$c$b$a" } } - - "Cancelling parZip 5 cancels all participants" { + + @Test + fun CancellingParZip5CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -99,8 +98,9 @@ class ParZip5Test : StringSpec({ pd.await().shouldBeTypeOf() pe.await().shouldBeTypeOf() } - - "parZip 5 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip5CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4, 5)), @@ -134,8 +134,9 @@ class ParZip5Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..5)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -167,4 +168,3 @@ class ParZip5Test : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip6Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip6Test.kt index 3446272504b..8fef5baf9fe 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip6Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip6Test.kt @@ -1,14 +1,10 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either import arrow.core.Tuple6 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +18,11 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope +import kotlin.test.Test -class ParZip6Test : StringSpec({ - "parZip 6 runs in parallel" { +class ParZip6Test { + @Test + fun parZip6RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d, e, f -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -59,18 +57,19 @@ class ParZip6Test : StringSpec({ modifyGate5.complete(Unit) }, { - r.set("$f") + r.value = "$f" modifyGate1.complete(Unit) } ) { _a, _b, _c, _d, _e, _f -> Tuple6(_a, _b, _c, _d, _e, _f) } - r.get() shouldBe "$f$e$d$c$b$a" + r.value shouldBe "$f$e$d$c$b$a" } } - "Cancelling parZip 6 cancels all participants" { + @Test + fun CancellingParZip6CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -102,8 +101,9 @@ class ParZip6Test : StringSpec({ pe.await().shouldBeTypeOf() pf.await().shouldBeTypeOf() } - - "parZip 6 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip6CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4, 5, 6)) @@ -141,8 +141,9 @@ class ParZip6Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..6)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -178,4 +179,3 @@ class ParZip6Test : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip7Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip7Test.kt index c904ca6cccd..cf7b672da48 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip7Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip7Test.kt @@ -1,14 +1,10 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either import arrow.core.Tuple7 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +18,11 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope +import kotlin.test.Test -class ParZip7Test : StringSpec({ - "parZip 7 runs in parallel" { +class ParZip7Test { + @Test + fun parZip7RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d, e, f, g -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -65,18 +63,19 @@ class ParZip7Test : StringSpec({ modifyGate6.complete(Unit) }, { - r.set("$g") + r.value = "$g" modifyGate1.complete(Unit) } ) { _a, _b, _c, _d, _e, _f, _g -> Tuple7(_a, _b, _c, _d, _e, _f, _g) } - r.get() shouldBe "$g$f$e$d$c$b$a" + r.value shouldBe "$g$f$e$d$c$b$a" } } - - "Cancelling parZip 7 cancels all participants" { + + @Test + fun CancellingParZip7CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -111,8 +110,9 @@ class ParZip7Test : StringSpec({ pf.await().shouldBeTypeOf() pg.await().shouldBeTypeOf() } - - "parZip 7 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip7CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4, 5, 6, 7)) @@ -155,8 +155,9 @@ class ParZip7Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..7)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -195,5 +196,4 @@ class ParZip7Test : StringSpec({ pf.await().shouldBeTypeOf() } } - } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip8Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip8Test.kt index 999b6e415e2..cfae45a0450 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip8Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip8Test.kt @@ -1,14 +1,10 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.core.Either import arrow.core.Tuple8 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +18,11 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope +import kotlin.test.Test -class ParZip8Test : StringSpec({ - "parZip 8 runs in parallel" { +class ParZip8Test { + @Test + fun parZip8RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d, e, f, g, h -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -71,18 +69,19 @@ class ParZip8Test : StringSpec({ modifyGate7.complete(Unit) }, { - r.set("$h") + r.value = "$h" modifyGate1.complete(Unit) } ) { _a, _b, _c, _d, _e, _f, _g, _h -> Tuple8(_a, _b, _c, _d, _e, _f, _g, _h) } - r.get() shouldBe "$h$g$f$e$d$c$b$a" + r.value shouldBe "$h$g$f$e$d$c$b$a" } } - - "Cancelling parZip 8 cancels all participants" { + + @Test + fun CancellingParZip8CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -120,8 +119,9 @@ class ParZip8Test : StringSpec({ pg.await().shouldBeTypeOf() ph.await().shouldBeTypeOf() } - - "parZip 8 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip8CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4, 5, 6, 7, 8)) @@ -167,8 +167,9 @@ class ParZip8Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..8)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -212,4 +213,3 @@ class ParZip8Test : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip9Test.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip9Test.kt index 0b22d828796..7e22dd83592 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip9Test.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ParZip9Test.kt @@ -1,14 +1,9 @@ -package arrow.fx.coroutines.parZip +package arrow.fx.coroutines +import arrow.atomic.Atomic +import arrow.atomic.update import arrow.core.Either import arrow.core.Tuple9 -import arrow.fx.coroutines.Atomic -import arrow.fx.coroutines.ExitCase -import arrow.fx.coroutines.awaitExitCase -import arrow.fx.coroutines.leftException -import arrow.fx.coroutines.parZip -import arrow.fx.coroutines.throwable -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf @@ -22,9 +17,12 @@ import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.async import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.CoroutineScope +import kotlin.test.Test -class ParZip9Test : StringSpec({ - "parZip 9 runs in parallel" { +class ParZip9Test { + + @Test + fun parZip9RunsInParallel() = runTestUsingDefaultDispatcher { checkAll(Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int(), Arb.int()) { a, b, c, d, e, f, g, h, i -> val r = Atomic("") val modifyGate1 = CompletableDeferred() @@ -87,8 +85,9 @@ class ParZip9Test : StringSpec({ r.get() shouldBe "$i$h$g$f$e$d$c$b$a" } } - - "Cancelling parZip 9 cancels all participants" { + + @Test + fun CancellingParZip9CancelsAllParticipants() = runTestUsingDefaultDispatcher { val s = Channel() val pa = CompletableDeferred() val pb = CompletableDeferred() @@ -129,8 +128,9 @@ class ParZip9Test : StringSpec({ ph.await().shouldBeTypeOf() pi.await().shouldBeTypeOf() } - - "parZip 9 cancels losers if a failure occurs in one of the tasks" { + + @Test + fun parZip9CancelsLosersIfAFailureOccursInOneOfTheTasks() = runTestUsingDefaultDispatcher { checkAll( Arb.throwable(), Arb.element(listOf(1, 2, 3, 4, 5, 6, 7, 8, 9)) @@ -180,8 +180,9 @@ class ParZip9Test : StringSpec({ r should leftException(e) } } - - "parZip CancellationException on right can cancel rest" { + + @Test + fun parZipCancellationExceptionOnRightCanCancelRest() = runTestUsingDefaultDispatcher { checkAll(Arb.string(), Arb.int(1..9)) { msg, cancel -> val s = Channel() val pa = CompletableDeferred() @@ -229,4 +230,3 @@ class ParZip9Test : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Platform.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Platform.kt index 90c72caf9f9..b516d7a1d5c 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Platform.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/Platform.kt @@ -4,15 +4,23 @@ import io.kotest.common.Platform import io.kotest.common.platform import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.test.TestResult +import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withContext +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds fun stackSafeIteration(): Int = when (platform) { Platform.JVM -> 20_000 else -> 1000 } -fun runTestWithDelay(testBody: suspend () -> Unit): TestResult = runTest { +// The normal dispatcher with 'runTest' does some magic +// which doesn't go well with 'parZip', 'parMap', and 'raceN' +fun runTestUsingDefaultDispatcher( + timeout: Duration = 40.seconds, + testBody: suspend TestScope.() -> Unit +): TestResult = runTest(timeout = timeout) { withContext(Dispatchers.Default) { testBody() } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/RaceNTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/RaceNTest.kt index 8a1e9e3e3e0..8fc5a0cdddd 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/RaceNTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/RaceNTest.kt @@ -4,7 +4,6 @@ import arrow.core.Either import arrow.core.identity import arrow.core.merge import io.kotest.assertions.retry -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf @@ -18,154 +17,116 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.channels.Channel +import kotlin.test.Test import kotlin.time.Duration.Companion.seconds fun Either.rethrow(): A = fold({ throw it }, ::identity) -class RaceNTest : StringSpec({ - "race2 can join first" { - checkAll(Arb.int()) { i -> - raceN({ i }, { awaitCancellation() }) shouldBe Either.Left(i) - } +class RaceNTest { + @Test fun race2JoinFirst() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + raceN({ i }, { awaitCancellation() }) shouldBe Either.Left(i) } + } - "race2 can join second" { - checkAll(Arb.int()) { i -> - raceN({ awaitCancellation() }, { i }) shouldBe Either.Right(i) - } + @Test fun race2JoinSecond() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + raceN({ awaitCancellation() }, { i }) shouldBe Either.Right(i) } + } - "Cancelling race 2 cancels all participants" { - checkAll(Arb.int(), Arb.int()) { a, b -> - val s = Channel() - val pa = CompletableDeferred>() - val pb = CompletableDeferred>() + @Test fun race2CancelsAll() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { a, b -> + val s = Channel() + val pa = CompletableDeferred>() + val pb = CompletableDeferred>() - val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } - val loserB: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } + val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } + val loserB: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } - val f = async { raceN(loserA, loserB) } + val f = async { raceN(loserA, loserB) } - // Suspend until all racers started - s.send(Unit) - s.send(Unit) - f.cancel() + // Suspend until all racers started + s.send(Unit) + s.send(Unit) + f.cancel() - pa.await().let { (res, exit) -> - res shouldBe a - exit.shouldBeInstanceOf() - } - pb.await().let { (res, exit) -> - res shouldBe b - exit.shouldBeInstanceOf() - } + pa.await().let { (res, exit) -> + res shouldBe a + exit.shouldBeInstanceOf() } - } - - "race 2 cancels losers with first success or failure determining winner" { - checkAll( - Arb.either(Arb.throwable(), Arb.int()), - Arb.boolean(), - Arb.int() - ) { eith, leftWinner, a -> - val s = Channel() - val pa = CompletableDeferred>() - - val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); eith.rethrow() } - val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } - - val res = Either.catch { - if (leftWinner) raceN(winner, loserA) - else raceN(loserA, winner) - }.map { it.merge() } - - pa.await().let { (res, exit) -> - res shouldBe a - exit.shouldBeInstanceOf() - } - res shouldBe either(eith) + pb.await().let { (res, exit) -> + res shouldBe b + exit.shouldBeInstanceOf() } } + } - "race3 can join first" { - checkAll(Arb.int()) { i -> - raceN({ i }, { awaitCancellation() }, { awaitCancellation() }) shouldBe Race3.First(i) + @Test fun race2CancelsWithFirstSuccess() = runTestUsingDefaultDispatcher { + checkAll( + Arb.either(Arb.throwable(), Arb.int()), + Arb.boolean(), + Arb.int() + ) { eith, leftWinner, a -> + val s = Channel() + val pa = CompletableDeferred>() + + val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); eith.rethrow() } + val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } + + val res = Either.catch { + if (leftWinner) raceN(winner, loserA) + else raceN(loserA, winner) + }.map { it.merge() } + + pa.await().let { (res, exit) -> + res shouldBe a + exit.shouldBeInstanceOf() } + res shouldBe either(eith) } + } - "race3 can join second" { - checkAll(Arb.int()) { i -> - raceN({ awaitCancellation() }, { i }, { awaitCancellation() }) shouldBe Race3.Second(i) - } + @Test fun race3JoinFirst() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + raceN({ i }, { awaitCancellation() }, { awaitCancellation() }) shouldBe Race3.First(i) } + } - "race3 can join third" { - checkAll(Arb.int()) { i -> - raceN({ awaitCancellation() }, { awaitCancellation() }, { i }) shouldBe Race3.Third(i) - } + @Test fun race3JoinSecond() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + raceN({ awaitCancellation() }, { i }, { awaitCancellation() }) shouldBe Race3.Second(i) } + } - "Cancelling race 3 cancels all participants" { - retry(10, 1.seconds) { - checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> - val s = Channel() - val pa = CompletableDeferred>() - val pb = CompletableDeferred>() - val pc = CompletableDeferred>() - - val loserA: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } - val loserB: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } - val loserC: suspend CoroutineScope.() -> Int = - { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pc.complete(Pair(c, ex)) } } - - val f = async { raceN(loserA, loserB, loserC) } - - s.send(Unit) // Suspend until all racers started - s.send(Unit) - s.send(Unit) - f.cancel() - - pa.await().let { (res, exit) -> - res shouldBe a - exit.shouldBeInstanceOf() - } - pb.await().let { (res, exit) -> - res shouldBe b - exit.shouldBeInstanceOf() - } - pc.await().let { (res, exit) -> - res shouldBe c - exit.shouldBeInstanceOf() - } - } - } + @Test fun race3JoinThird() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + raceN({ awaitCancellation() }, { awaitCancellation() }, { i }) shouldBe Race3.Third(i) } + } - "race 3 cancels losers with first success or failure determining winner" { - checkAll( - Arb.either(Arb.throwable(), Arb.int()), - Arb.element(listOf(1, 2, 3)), - Arb.int(), - Arb.int() - ) { eith, leftWinner, a, b -> + @Test fun race3CancelsAll() = runTestUsingDefaultDispatcher { + retry(10, 1.seconds) { + checkAll(Arb.int(), Arb.int(), Arb.int()) { a, b, c -> val s = Channel() val pa = CompletableDeferred>() val pb = CompletableDeferred>() + val pc = CompletableDeferred>() - val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); s.send(Unit); eith.rethrow() } - val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } - val loserB: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } + val loserA: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } + val loserB: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } + val loserC: suspend CoroutineScope.() -> Int = + { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pc.complete(Pair(c, ex)) } } - val res = Either.catch { - when (leftWinner) { - 1 -> raceN(winner, loserA, loserB) - 2 -> raceN(loserA, winner, loserB) - else -> raceN(loserA, loserB, winner) - } - }.map { it.fold(::identity, ::identity, ::identity) } + val f = async { raceN(loserA, loserB, loserC) } + + s.send(Unit) // Suspend until all racers started + s.send(Unit) + s.send(Unit) + f.cancel() pa.await().let { (res, exit) -> res shouldBe a @@ -175,8 +136,46 @@ class RaceNTest : StringSpec({ res shouldBe b exit.shouldBeInstanceOf() } - res should either(eith) + pc.await().let { (res, exit) -> + res shouldBe c + exit.shouldBeInstanceOf() + } + } + } + } + + @Test fun race3CancelsWithFirstSuccess() = runTestUsingDefaultDispatcher { + checkAll( + Arb.either(Arb.throwable(), Arb.int()), + Arb.element(listOf(1, 2, 3)), + Arb.int(), + Arb.int() + ) { eith, leftWinner, a, b -> + val s = Channel() + val pa = CompletableDeferred>() + val pb = CompletableDeferred>() + + val winner: suspend CoroutineScope.() -> Int = { s.send(Unit); s.send(Unit); eith.rethrow() } + val loserA: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pa.complete(Pair(a, ex)) } } + val loserB: suspend CoroutineScope.() -> Int = { guaranteeCase({ s.receive(); awaitCancellation() }) { ex -> pb.complete(Pair(b, ex)) } } + + val res = Either.catch { + when (leftWinner) { + 1 -> raceN(winner, loserA, loserB) + 2 -> raceN(loserA, winner, loserB) + else -> raceN(loserA, loserB, winner) + } + }.map { it.fold(::identity, ::identity, ::identity) } + + pa.await().let { (res, exit) -> + res shouldBe a + exit.shouldBeInstanceOf() + } + pb.await().let { (res, exit) -> + res shouldBe b + exit.shouldBeInstanceOf() } + res should either(eith) } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ResourceTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ResourceTest.kt index b1cdaaf3843..80d9dbac273 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ResourceTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ResourceTest.kt @@ -2,15 +2,14 @@ package arrow.fx.coroutines import arrow.autoCloseScope import arrow.core.Either -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.update -import arrow.core.identity import arrow.core.left +import arrow.core.raise.either +import arrow.fx.coroutines.ExitCase.Companion.ExitCase import io.kotest.assertions.fail import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec -import io.kotest.inspectors.forAll +import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.should import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeInstanceOf @@ -22,11 +21,11 @@ import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.negativeInt import io.kotest.property.arbitrary.positiveInt -import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import io.kotest.property.arbitrary.string import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableDeferred -import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.flow.map @@ -35,498 +34,603 @@ import kotlinx.coroutines.test.runTest import kotlin.random.Random import kotlin.test.Test -@OptIn(ExperimentalCoroutinesApi::class) -class ResourceTest : StringSpec({ +class ResourceTest { - "Can consume resource" { - checkAll(Arb.int()) { n -> - val r = resource({ n }, { _, _ -> }) - r.use { it + 1 } shouldBe n + 1 + @Test + fun acquireSuccessIdentity() = runTest { + checkAll(Arb.int()) { n -> + resourceScope { + install({ n }) { _, _ -> } shouldBe n } } + } + + @Test + fun respectFIFOOrderInstalledFunction() = runTest { + checkAll(Arb.positiveInt(), Arb.negativeInt()) { a, b -> + val order = mutableListOf() - "flatMap resource is released first" { - checkAll(Arb.positiveInt(), Arb.negativeInt()) { a, b -> - val l = AtomicRef>(mutableListOf()) - fun r(n: Int) = resource( - { - l.update { it + n } - n - }, - { x, _ -> l.update { it + (-x) } } - ) - - r(a).flatMap { r(it + b) } - .use { it + 1 } shouldBe (a + b) + 1 - - l.get().shouldContainExactly(a, a + b, -a - b, -a) + suspend fun ResourceScope.scoped(n: Int): Int = + install({ n.also(order::add) }, { it, _ -> order.add(-it) }) + + resourceScope { + val x = scoped(a) + val y = scoped(x + b) + y + 1 shouldBe (a + b) + 1 } - } - "value resource is released with Complete" { - checkAll(Arb.int()) { n -> - val p = CompletableDeferred() - resource({ n }, { _, ex -> require(p.complete(ex)) }) - .use { Unit } + order.shouldContainExactly(a, a + b, -a - b, -a) + } + } - p.await() shouldBe ExitCase.Completed + @Test + fun resourceReleasedWithComplete() = runTest { + checkAll(Arb.int()) { n -> + val p = CompletableDeferred() + resourceScope { + install({ n }) { _, ex -> require(p.complete(ex)) } } + p.await() shouldBe ExitCase.Completed } + } - "error resource finishes with error" { - checkAll(Arb.throwable()) { e -> - val p = CompletableDeferred() - val r = resource({ throw e }, { _, ex -> require(p.complete(ex)) }) + @Test + fun errorFinishesWithError() = runTest { + checkAll(Arb.throwable()) { e -> + val p = CompletableDeferred() + suspend fun ResourceScope.failingScope(): Nothing = + install({ throw e }, { _, ex -> require(p.complete(ex)) }) - Either.catch { - r.use { it + 1 } - } should leftException(e) - } + Either.catch { + resourceScope { failingScope() } + } should leftException(e) } + } - "never use can be cancelled with ExitCase.Completed" { - checkAll(Arb.int()) { n -> - val p = CompletableDeferred() - val start = CompletableDeferred() - val r = resource({ n }, { _, ex -> require(p.complete(ex)) }) + @Test + fun neverCancelled() = runTest { + checkAll(Arb.int()) { n -> + val p = CompletableDeferred() + val start = CompletableDeferred() + suspend fun ResourceScope.n(): Int = install({ n }, { _, ex -> require(p.complete(ex)) }) - val f = async { - r.use { - require(start.complete(Unit)) - awaitCancellation() - } + val f = async { + resourceScope { + n() + require(start.complete(Unit)) + awaitCancellation() } - - start.await() - f.cancel() - p.await().shouldBeInstanceOf() } - } - "traverseResource: identity" { - checkAll( - Arb.list(Arb.int()), - Arb.functionAToB(Arb.string()) - ) { list, f -> - list.traverse { Resource.just(f(it)) } resourceShouldBe Resource.just(list.map(f)) - } + start.await() + f.cancel() + p.await().shouldBeInstanceOf() } + } - "traverse: map + sequence == traverse" { - checkAll( - Arb.list(Arb.int()), - Arb.string().map { { _: Int -> Resource.just(it) } } - ) { list, f -> - list.traverse(f) resourceShouldBe list.map(f).sequence() - } - } - "traverse: parallelComposition" { - checkAll( - Arb.list(Arb.int()), - Arb.functionAToB(Arb.string()), - Arb.functionAToB(Arb.string()) - ) { list, f, g -> - - val ff = list.traverse { Resource.just(f(it)) } - val gg = list.traverse { Resource.just(g(it)) } - - val result = ff.zip(gg).map { (a, b) -> - a.zip(b) + @Test + fun mapBind() = runTest { + checkAll( + Arb.list(Arb.int()), + Arb.functionAToB(Arb.string()) + ) { list, f -> + resourceScope { + list.map { + resource { f(it) }.bind() } - - list.traverse { Resource.just(f(it) to g(it)) } resourceShouldBe result - } + } shouldBe list.map(f) } + } - "traverse: leftToRight" { - checkAll(Arb.list(Arb.int())) { list -> - list.traverse { Resource.just(it) } - .use(::identity) shouldBe list + @Test + fun resourceCloseFromEither() = runTest { + val exit = CompletableDeferred() + either { + resourceScope { + install({ 1 }) { _, ex -> + require(exit.complete(ex)) + } + raise("error") } - } + } shouldBe "error".left() + exit.await().shouldBeTypeOf() + } + + private val depth = 10 - "Resource can close from either" { - val exit = CompletableDeferred() - arrow.core.computations.either { - arrow.fx.coroutines.continuations.resource { - resource({ 1 }) { _, ex -> require(exit.complete(ex)) }.bind() - "error".left().bind() - 1 - }.use { it } - } shouldBe "error".left() - // Should be ExitCase.Cancelled but still Failure due to ShortCircuit - // Effect will fix this issue by properly shifting and cancelling - exit.await().shouldBeTypeOf() + class CheckableAutoClose { + var started = true + fun close() { + started = false } + } - val depth: Int = 100 + @Test + fun closeTheScopeOnCancellation() = runTest { + val exit = CompletableDeferred() - class CheckableAutoClose { - val started: AtomicRef = AtomicRef(true) - fun close() { - started.update { _ -> false } + shouldThrow { + resourceScope { + install({ }) { _, ex -> require(exit.complete(ex)) } + throw CancellationException("BOOM!") } - } + }.message shouldBe "BOOM!" - fun closeable(): Resource = - resource({ CheckableAutoClose() }) { a, _ -> a.close() } - - "close the scope on cancellation" { - val exit = CompletableDeferred() + exit.await() + .shouldBeTypeOf() + .exception + .message shouldBe "BOOM!" + } - shouldThrow { - resourceScope { - install({ }) { _, ex -> require(exit.complete(ex)) } - throw CancellationException("BOOM!") - } - }.message shouldBe "BOOM!" + @Test + fun parZipSuccess() = runTestUsingDefaultDispatcher { + suspend fun ResourceScope.closeable(): CheckableAutoClose = + install({ CheckableAutoClose() }) { a: CheckableAutoClose, _: ExitCase -> a.close() } - exit.await() - .shouldBeTypeOf() - .exception - .message shouldBe "BOOM!" + resourceScope { + parZip({ + (1..depth).map { closeable() } + }, { + (1..depth).map { closeable() } + }, { a, b -> a + b }) } + } - "parZip - success" { - val all = (1..depth).traverse { closeable() }.parZip( - (1..depth).traverse { closeable() } - ) { a, b -> a + b }.use { all -> - all.also { all.forEach { it.started.get() shouldBe true } } + private fun generate(): Pair>, Resource> { + val promises = (1..depth).map { Pair(it, CompletableDeferred()) } + val res = promises.fold(resource({ 0 }, { _, _ -> })) { acc, (i, promise) -> + resource { + val ii = acc.bind() + install({ ii + i }) { _, _ -> + require(promise.complete(i)) + } } - all.forEach { it.started.get() shouldBe false } } + return Pair(promises.map { it.second }, res) + } - fun generate(): Pair>, Resource> { - val promises = (1..depth).map { Pair(it, CompletableDeferred()) } - val res = promises.fold(resource({ 0 }) { _, _ -> }) { acc, (i, p) -> - resource { - acc.bind() + install({ i }) { ii, _ -> p.complete(ii) } + @Test + fun parZipFinalizersBlow() = runTestUsingDefaultDispatcher { + checkAll(3, Arb.int(10..100)) { + val (promises, resource) = generate() + shouldThrow { + resourceScope { + parZip({ + resource.bind() + throw RuntimeException() + }, { }) { _, _ -> } + fail("It should never reach here") } } - return Pair(promises.map { it.second }, res) - } - "parZip - deep finalizers are called when final one blows" { - checkAll(3, Arb.int(10..100)) { - val (promises, resource) = generate() - assertThrowable { - resource.flatMap { - resource({ throw RuntimeException() }) { _, _ -> } - }.parZip(resource({ }) { _, _ -> }) { _, _ -> } - .use { fail("It should never reach here") } - }.shouldBeTypeOf() - - (1..depth).zip(promises) { i, promise -> - promise.await() shouldBe i - } + (1..depth).zip(promises) { i, promise -> + promise.await() shouldBe i } } + } - "parZip - deep finalizers are called when final one cancels" { - checkAll(3, Arb.int(10..100)) { - val cancel = CancellationException(null, null) - val (promises, resource) = generate() - assertThrowable { - resource.flatMap { - resource({ throw cancel }) { _, _ -> } - }.parZip(resource({ }) { _, _ -> }) { _, _ -> } - .use { fail("It should never reach here") } - }.shouldBeTypeOf() - - (1..depth).zip(promises) { i, promise -> - promise.await() shouldBe i + @Test + fun parZipFinalizersCancel() = runTestUsingDefaultDispatcher { + checkAll(3, Arb.int(10..100)) { + val cancel = CancellationException(null, null) + val (promises, resource) = generate() + shouldThrow { + resourceScope { + parZip({}, { + resource.bind() + throw cancel + }) { _, _ -> } + fail("It should never reach here") } } + + (1..depth).zip(promises) { i, promise -> + promise.await() shouldBe i + } } + } - // Test multiple release triggers on acquire fail. - "parZip - Deep finalizers get called on left or right cancellation" { - checkAll(Arb.boolean()) { isLeft -> - val cancel = CancellationException(null, null) - val (promises, resource) = generate() - val latch = CompletableDeferred() - assertThrowable { - val res = if (isLeft) resource({ - latch.await() shouldBe (1..depth).sum() - throw cancel - }) { _, _ -> }.parZip( - resource.flatMap { - resource({ require(latch.complete(it)) }) { _, _ -> } - } - ) { _, _ -> } - else resource.flatMap { - resource({ require(latch.complete(it)) }) { _, _ -> } - }.parZip( - resource({ + // Test multiple release triggers on acquire fail. + @Test + fun parZipFinalizersLeftOrRightCancellation() = runTestUsingDefaultDispatcher { + checkAll(Arb.boolean()) { isLeft -> + val cancel = CancellationException(null, null) + val (promises, resource) = generate() + val latch = CompletableDeferred() + shouldThrow { + resourceScope { + if (isLeft) { + parZip({ latch.await() shouldBe (1..depth).sum() throw cancel + }, { + val i = resource.bind() + require(latch.complete(i)) }) { _, _ -> } - ) { _, _ -> } - - res.use { fail("It should never reach here") } - }.shouldBeTypeOf() - - (1..depth).zip(promises) { i, promise -> - promise.await() shouldBe i + } else { + parZip({ + val i = resource.bind() + require(latch.complete(i)) + }, { + latch.await() shouldBe (1..depth).sum() + throw cancel + }) { _, _ -> } + } + fail("It should never reach here") } } - } - "parZip - Right CancellationException on acquire" { - checkAll(Arb.int()) { i -> - val cancel = CancellationException(null, null) - val released = CompletableDeferred>() - val started = CompletableDeferred() - assertThrowable { - resource({ require(started.complete(Unit)); i }, { ii, ex -> - require(released.complete(ii to ex)) - }).parZip(resource({ started.await(); throw cancel }) { _, _ -> }) { _, _ -> } - .use { fail("It should never reach here") } - }.shouldBeTypeOf() - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() + (1..depth).zip(promises) { i, promise -> + promise.await() shouldBe i } } + } - "parZip - Left CancellationException on acquire" { - checkAll(Arb.int()) { i -> - val cancel = CancellationException(null, null) - val released = CompletableDeferred>() - val started = CompletableDeferred() - - assertThrowable { - resource({ + @Test + fun parZipRightCancellationExceptionOnAcquire() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + val cancel = CancellationException(null, null) + val released = CompletableDeferred>() + val started = CompletableDeferred() + shouldThrow { + resourceScope { + parZip({ + install({ + require(started.complete(Unit)) + i + }, { ii: Int, ex: ExitCase -> + require(released.complete(ii to ex)) + }) + }, { started.await() throw cancel }) { _, _ -> } - .parZip( - resource({ require(started.complete(Unit)); i }, { ii, ex -> - require(released.complete(ii to ex)) - }) - ) { _, _ -> } - .use { fail("It should never reach here") } - }.shouldBeTypeOf() - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() + fail("It should never reach here") + } } + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - Right error on acquire" { - checkAll(Arb.int(), Arb.throwable()) { i, throwable -> - val released = CompletableDeferred>() - val started = CompletableDeferred() - assertThrowable { - resource( - { require(started.complete(Unit)); i }, - { ii, ex -> require(released.complete(ii to ex)) } - ).parZip( - resource({ started.await(); throw throwable }) { _, _ -> } - ) { _, _ -> } - .use { fail("It should never reach here") } - } shouldBe throwable - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() + @Test + fun parZipLeftCancellationExceptionOnAcquire() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + val cancel = CancellationException(null, null) + val released = CompletableDeferred>() + val started = CompletableDeferred() + + shouldThrow { + resourceScope { + parZip({ + started.await() + throw cancel + }, { + install({ + require(started.complete(Unit)) + i + }, { ii: Int, ex: ExitCase -> + require(released.complete(ii to ex)) + }) + }) { _, _ -> } + fail("It should never reach here") + } } + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - Left error on acquire" { - checkAll(Arb.int(), Arb.throwable()) { i, throwable -> - val released = CompletableDeferred>() - val started = CompletableDeferred() - assertThrowable { - resource({ + @Test + fun parZipRightErrorOnAcquire() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable()) { i, throwable -> + val released = CompletableDeferred>() + val started = CompletableDeferred() + shouldThrow { + resourceScope { + parZip({ + install({ + require(started.complete(Unit)) + i + }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) } + ) + }, { started.await() throw throwable }) { _, _ -> } - .parZip( - resource( - { require(started.complete(Unit)); i }, - { ii, ex -> require(released.complete(ii to ex)) } - ) - ) { _, _ -> } - .use { fail("It should never reach here") } - } shouldBe throwable - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() - } + fail("It should never reach here") + } + + } shouldBe throwable + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - Right CancellationException on release" { - checkAll(Arb.int()) { i -> - val cancel = CancellationException(null, null) - val released = CompletableDeferred>() - - assertThrowable { - resource({ i }, { ii, ex -> require(released.complete(ii to ex)) }) - .parZip( - resource({ }) { _, _ -> throw cancel } - ) { _, _ -> } - .use { } - }.shouldBeTypeOf() - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() - } + @Test + fun parZipLeftErrorOnAcquire() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable()) { i, throwable -> + val released = CompletableDeferred>() + val started = CompletableDeferred() + shouldThrow { + resourceScope { + parZip({ + started.await() + throw throwable + }, { + install({ + require(started.complete(Unit)) + i + }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) } + ) + }) { _, _ -> } + fail("It should never reach here") + } + } shouldBe throwable + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } + + @Test + fun parZipRightCancellationExceptionOnRelease() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + val cancel = CancellationException(null, null) + val released = CompletableDeferred>() - "parZip - Left CancellationException on release" { - checkAll(Arb.int()) { i -> - val cancel = CancellationException(null, null) - val released = CompletableDeferred>() - - assertThrowable { - resource({ }) { _, _ -> throw cancel } - .parZip( - resource({ i }, { ii, ex -> require(released.complete(ii to ex)) }) - ) { _, _ -> } - .use { /*fail("It should never reach here")*/ } - }.shouldBeTypeOf() - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() + shouldThrow { + resourceScope { + parZip({ + install({ i }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) }) + }, { + install({ }, { _: Unit, _: ExitCase -> throw cancel }) + }) { _, _ -> } + } } + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - Right error on release" { - checkAll(Arb.int(), Arb.throwable()) { i, throwable -> - val released = CompletableDeferred>() - - assertThrowable { - resource({ i }, { ii, ex -> require(released.complete(ii to ex)) }) - .parZip( - resource({ }) { _, _ -> throw throwable } - ) { _, _ -> } - .use { } - } shouldBe throwable - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() + @Test + fun parZipLeftCancellationExceptionOnRelease() = runTestUsingDefaultDispatcher { + checkAll(Arb.int()) { i -> + val cancel = CancellationException(null, null) + val released = CompletableDeferred>() + + shouldThrow { + resourceScope { + parZip({ + install({ }, { _: Unit, _: ExitCase -> throw cancel }) + }, { + install({ i }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) }) + }) { _, _ -> } + } } + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - Left error on release" { - checkAll(Arb.int(), Arb.throwable()) { i, throwable -> - val released = CompletableDeferred>() - - assertThrowable { - resource({ }) { _, _ -> throw throwable } - .parZip( - resource({ i }, { ii, ex -> require(released.complete(ii to ex)) }) - ) { _, _ -> } - .use { } - } shouldBe throwable - - val (ii, ex) = released.await() - ii shouldBe i - ex.shouldBeTypeOf() - } + @Test + fun parZipRightErrorOnRelease() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable()) { i, throwable -> + val released = CompletableDeferred>() + + shouldThrow { + resourceScope { + parZip({ + install({ i }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) }) + }, { + install({ }, { _: Unit, _: ExitCase -> throw throwable }) + }) { _, _ -> } + } + } shouldBe throwable + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - error in use" { - checkAll(Arb.int(), Arb.int(), Arb.throwable()) { a, b, throwable -> - val releasedA = CompletableDeferred>() - val releasedB = CompletableDeferred>() - - assertThrowable { - resource({ a }) { aa, ex -> require(releasedA.complete(aa to ex)) } - .parZip( - resource({ b }) { bb, ex -> require(releasedB.complete(bb to ex)) } - ) { _, _ -> } - .use { throw throwable } - } shouldBe throwable - - val (aa, exA) = releasedA.await() - aa shouldBe a - exA.shouldBeTypeOf() - - val (bb, exB) = releasedB.await() - bb shouldBe b - exB.shouldBeTypeOf() - } + @Test + fun parZipLeftErrorOnRelease() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.throwable()) { i, throwable -> + val released = CompletableDeferred>() + + shouldThrow { + resourceScope { + parZip({ + install({ }, { _: Unit, _: ExitCase -> throw throwable }) + }, { + install({ i }, { ii: Int, ex: ExitCase -> require(released.complete(ii to ex)) }) + }) { _, _ -> } + } + } shouldBe throwable + + val (ii, ex) = released.await() + ii shouldBe i + ex.shouldBeTypeOf() } + } - "parZip - runs in parallel" { - checkAll(Arb.int(), Arb.int()) { a, b -> - val r = Atomic("") - val modifyGate = CompletableDeferred() - - resource({ - modifyGate.await() - r.update { i -> "$i$a" } - }) { _, _ -> } - .parZip( - resource({ - r.set("$b") - require(modifyGate.complete(0)) - }) { _, _ -> } - ) { _a, _b -> _a to _b } - .use { - r.get() shouldBe "$b$a" - } - } + @Test + fun parZipErrorInUse() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int(), Arb.throwable()) { a, b, throwable -> + val releasedA = CompletableDeferred>() + val releasedB = CompletableDeferred>() + + shouldThrow { + resourceScope { + parZip({ + install({ a }) { aa: Int, ex: ExitCase -> require(releasedA.complete(aa to ex)) } + }, { + install({ b }) { bb: Int, ex: ExitCase -> require(releasedB.complete(bb to ex)) } + }) { _, _ -> } + throw throwable + } + } shouldBe throwable + + val (aa, exA) = releasedA.await() + aa shouldBe a + exA.shouldBeTypeOf() + + val (bb, exB) = releasedB.await() + bb shouldBe b + exB.shouldBeTypeOf() } + } - "resource.asFlow()" { - checkAll(Arb.int()) { n -> - val r = resource({ n }, { _, _ -> Unit }) + @Test + fun parZipCancellationInUse() = runTestUsingDefaultDispatcher { + checkAll(Arb.int(), Arb.int()) { a, b -> + val releasedA = CompletableDeferred>() + val releasedB = CompletableDeferred>() - r.asFlow().map { it + 1 }.toList() shouldBe listOf(n + 1) + shouldThrow { + resourceScope { + parZip({ + install({ a }) { aa: Int, ex: ExitCase -> require(releasedA.complete(aa to ex)) } + }, { + install({ b }) { bb: Int, ex: ExitCase -> require(releasedB.complete(bb to ex)) } + }) { _, _ -> } + throw CancellationException("") + } } + + val (aa, exA) = releasedA.await() + aa shouldBe a + exA.shouldBeTypeOf() + + val (bb, exB) = releasedB.await() + bb shouldBe b + exB.shouldBeTypeOf() } + } - suspend fun checkAllocated(mkResource: (() -> Int, (Int, ExitCase) -> Unit) -> Resource) { - listOf( - ExitCase.Completed, - ExitCase.Failure(Exception()), - ExitCase.Cancelled(CancellationException(null, null)) - ).forAll { exit -> - val released = CompletableDeferred() - val seed = Random.nextInt() + @Test + fun resourceAsFlow() = runTest { + checkAll(Arb.int()) { n -> + val released = CompletableDeferred() + val r = resource({ n }, { _, ex -> require(released.complete(ex)) }) - val (allocate, release) = mkResource({ seed }) { i, _ -> released.complete(i) }.allocated() + r.asFlow().map { it + 1 }.toList() shouldBe listOf(n + 1) - release(allocate(), exit) + released.await() shouldBe ExitCase.Completed + } + } - released.getCompleted() shouldBe seed - } + @Test + fun resourceAsFlowFail() = runTest { + checkAll(Arb.int(), Arb.throwable()) { n, throwable -> + val released = CompletableDeferred() + val r = resource({ n }, { _, ex -> require(released.complete(ex)) }) + + shouldThrow { + r.asFlow().collect { throw throwable } + } shouldBe throwable + + released.await().shouldBeTypeOf().failure shouldBe throwable } + } + + @Test + fun resourceAsFlowCancel() = runTest { + checkAll(Arb.int()) { n -> + val released = CompletableDeferred() + val r = resource({ n }, { _, ex -> require(released.complete(ex)) }) - "allocated - Allocate" { - checkAllocated { allocate, release -> - resource(allocate, release) + shouldThrow { + r.asFlow().collect { throw CancellationException("") } } + + released.await().shouldBeTypeOf() } + } - "allocated - Defer" { - checkAllocated { allocate, release -> - Resource.defer { resource(allocate, release) } - } + @OptIn(DelicateCoroutinesApi::class) + @Test + fun allocatedWorks() = runTest { + checkAll(Arb.int()) { seed -> + val released = CompletableDeferred() + val (allocate, release) = resource({ seed }) { _, exitCase -> released.complete(exitCase) } + .allocated() + + allocate shouldBe seed + release(ExitCase.Completed) + released.await() shouldBe ExitCase.Completed } + } - "allocated - Bind" { - checkAllocated { allocate, release -> - Resource.Bind(resource(allocate, release)) { Resource.just(it) } + @OptIn(DelicateCoroutinesApi::class) + @Test + fun allocatedSupressedException() = runTest { + checkAll( + Arb.int(), + Arb.string().map(::RuntimeException), + Arb.string().map(::IllegalStateException) + ) { seed, original, suppressed -> + val released = CompletableDeferred() + val (allocate, release) = + resource({ seed }) { _, exitCase -> + released.complete(exitCase) + throw suppressed + }.allocated() + + val exception = shouldThrow { + try { + allocate shouldBe seed + throw original + } catch (e: Throwable) { + release(ExitCase(e)) + } } + + exception shouldBe original + exception.suppressedExceptions.firstOrNull().shouldNotBeNull() shouldBe suppressed + released.await().shouldBeTypeOf() } + } - "allocated - Dsl" { - checkAllocated { allocate, close -> - arrow.fx.coroutines.continuations.resource { allocate() } releaseCase (close) + @OptIn(DelicateCoroutinesApi::class) + @Test + fun allocatedCancellationException() = runTest { + checkAll( + Arb.int(), + Arb.string().map { CancellationException(it, null) }, + Arb.string().map(::IllegalStateException) + ) { seed, cancellation, suppressed -> + val released = CompletableDeferred() + val (allocate, release) = + resource({ seed }) { _, exitCase -> + released.complete(exitCase) + throw suppressed + }.allocated() + + val exception = shouldThrow { + try { + allocate shouldBe seed + throw cancellation + } catch (e: Throwable) { + release(ExitCase(e)) + } } + + exception shouldBe cancellation + exception.suppressedExceptions.firstOrNull().shouldNotBeNull() shouldBe suppressed + released.await().shouldBeTypeOf() } } -) - -private suspend infix fun Resource.resourceShouldBe(expected: Resource): Unit = - zip(expected).use { (a, b) -> a shouldBe b } +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ScheduleTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ScheduleTest.kt deleted file mode 100644 index 1d693bd34d8..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/commonTest/kotlin/arrow/fx/coroutines/ScheduleTest.kt +++ /dev/null @@ -1,359 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.Either -import arrow.core.Eval -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.should -import io.kotest.matchers.shouldBe -import kotlinx.coroutines.withTimeoutOrNull -import kotlin.math.pow -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.asFlow -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.flow.zip - -internal data class SideEffect(var counter: Int = 0) { - fun increment() { - counter++ - } -} - -@ExperimentalTime -class ScheduleTest : StringSpec({ - class MyException : Exception() - - val exception = MyException() - - "Schedule.identity()" { - val dec = Schedule.identity().calculateSchedule1(1) - val expected = Schedule.Decision(true, 0.0, Unit, Eval.now(1)) - - dec eqv expected - } - - "Schedule.unfold()" { - val dec = Schedule.unfold(0) { it + 1 }.calculateSchedule1(0) - val expected = Schedule.Decision(true, 0.0, 1, Eval.now(1)) - - dec eqv expected - } - - "Schedule.forever() == Schedule.unfold(0) { it + 1 }" { - val foreverDesc = Schedule.forever().calculateSchedule1(0) - val unfoldDesc = Schedule.unfold(0) { it + 1 }.calculateSchedule1(0) - - foreverDesc eqv unfoldDesc - } - - "Schedule.recurs(negative number)" { - checkRepeat(Schedule.recurs(-500), expected = 0) - } - - "Schedule.recurs(0)" { - checkRepeat(Schedule.recurs(0), expected = 0) - } - - "Schedule.recurs(1)" { - checkRepeat(Schedule.recurs(1), expected = 1) - } - - "Schedule.recurs(n: Int)" { - val n = 500 - val res = Schedule.recurs(n).calculateSchedule(0, n + 1) - - res.dropLast(1).map { it.delayInNanos.nanoseconds } shouldBe res.dropLast(1).map { 0.nanoseconds } - res.dropLast(1).map { it.cont } shouldBe res.dropLast(1).map { true } - - res.last() eqv Schedule.Decision(false, 0.0, n + 1, Eval.now(n + 1)) - } - - "Schedule.once() repeats 1 additional time" { - var count = 0 - Schedule.once().repeat { - count++ - } - count shouldBe 2 - } - - "Schedule.doWhile repeats while condition holds and returns itself" { - checkRepeat(Schedule.doWhile { it < 10 }, expected = 10) - checkRepeat(Schedule.doWhile { it > 10 }, expected = 1) - checkRepeat(Schedule.doWhile { it == 1 }, expected = 2) - } - - "Schedule.doUntil repeats until the cond is satisfied" { - checkRepeat(Schedule.doUntil { it < 10 }, expected = 1) - checkRepeat(Schedule.doUntil { it > 10 }, expected = 11) - checkRepeat(Schedule.doUntil { it == 1 }, expected = 1) - } - - "Schedule.doWhile.collect() collects all inputs into a list" { - checkRepeat( - Schedule - .doWhile { it < 10 } - .collect(), - expected = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9) - ) - } - - "Schedule.doUntil.collect() collects all inputs into a list" { - checkRepeat( - Schedule - .doUntil { it > 10 } - .collect(), - expected = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - ) - } - - "Repeat a scheduled repeat repeats the whole number" { - val n = 42 - var count = 0 - Schedule.recurs(1).repeat { - Schedule.recurs(n).repeat { - count++ - } - } - - count shouldBe ((n + 1) * 2) - } - - "Schedule.never() times out" { - withTimeoutOrNull(10.milliseconds) { - val a: Nothing = Schedule.never().repeat { - 1 - } - } shouldBe null - } - - "Schedule.spaced()" { - val duration = 5.seconds - val res = Schedule.spaced(duration).calculateSchedule(0, 500) - - res.map { it.cont } shouldBe res.map { true } - res.map { it.delayInNanos.nanoseconds } shouldBe res.map { duration } - } - - fun secondsToNanos(sec: Int): Double = - sec * 1_000_000_000.0 - - "Schedule.fibonacci()" { - val i = secondsToNanos(10) - val n = 10 - val res = Schedule.fibonacci(i).calculateSchedule(0, n) - - val sum = res.fold(0.0) { acc, v -> - acc + v.delayInNanos - } - val fib = fibs(i).drop(1).take(n) - - res.all { it.cont } shouldBe true - sum shouldBe fib.sum() - } - - "Schedule.linear()" { - val i = secondsToNanos(10) - val n = 10 - val res = Schedule.linear(i).calculateSchedule(0, n) - - val sum = res.fold(0.0) { acc, v -> acc + v.delayInNanos } - val exp = linear(i).drop(1).take(n) - - res.all { it.cont } shouldBe true - sum shouldBe exp.sum() - } - - "Schedule.exponential()" { - val i = secondsToNanos(10) - val n = 10 - val res = Schedule.exponential(i).calculateSchedule(0, n) - - val sum = res.fold(0.0) { acc, v -> acc + v.delayInNanos } - val expSum = exp(i).drop(1).take(n).sum() - - res.all { it.cont } shouldBe true - sum shouldBe expSum - } - - "repeat is stack-safe" { - checkRepeat(Schedule.recurs(20_000), expected = 20_000) - } - - "repeatAsFlow is stack-safe" { - checkRepeatAsFlow(Schedule.recurs(500_000), expected = (1..500_000).asFlow()) - } - - "repeat" { - val stop = RuntimeException("WOOO") - val dec = Schedule.Decision(true, 10.0, 0, Eval.now("state")) - val n = 100 - val schedule = Schedule({ 0 }) { _: Unit, _ -> dec } - - val eff = SideEffect() - - val l = Either.catch { - schedule.repeat { - if (eff.counter >= n) throw stop - else eff.increment() - } - } - - eff.counter shouldBe 100 - l shouldBe Either.Left(stop) - } - - "repeatAsFlow" { - val stop = RuntimeException("WOOO") - val dec = Schedule.Decision(true, 10.0, 0, Eval.now("state")) - val n = 100 - val schedule = Schedule({ 0 }) { _: Unit, _ -> dec } - - val eff = SideEffect() - - val l = Either.catch { - schedule.repeatAsFlow { - if (eff.counter >= n) throw stop - else eff.increment() - }.collect() - } - - eff.counter shouldBe 100 - l shouldBe Either.Left(stop) - } - - "repeat fails fast on errors" { - val ex = Throwable("Hello") - Schedule.recurs(0).repeatOrElseEither({ throw ex }) { exc, _ -> exc } - .fold({ it shouldBe ex }, { fail("The impossible happened") }) - } - - "repeatAsFlow fails fast on errors" { - val ex = Throwable("Hello") - Schedule.recurs(0).repeatOrElseEitherAsFlow({ throw ex }, { t, _ -> t }) - .collect { either -> either.fold({ it shouldBe ex }, { fail("The impossible happened") }) } - } - - "repeat should run the schedule with the correct input" { - var i = 0 - val n = 10 - (Schedule.recurs(n).zipRight(Schedule.collect())).repeat { i++ } shouldBe (0..n).toList() - } - - "repeatAsFlow should run the schedule with the correct input" { - var i = 0 - val n = 10 - (Schedule.recurs(n).zipRight(Schedule.collect())).repeatAsFlow { i++ }.toList() shouldBe - (0..n).map { (0..it).toList() } - } - - "retry is stack-safe" { - val count = Atomic(0) - val l = Either.catch { - Schedule.recurs(20_000).retry { - count.updateAndGet { it + 1 } - throw exception - } - } - - l should leftException(exception) - count.get() shouldBe 20_001 - } - - "retry succeeds if no exception is thrown" { - Schedule.recurs(0).retry { 1 } shouldBe 1 - } - - "retryOrElseEither runs the schedule with the correct input and runs the orElse handler if it does not retry" { - val ex = Throwable("Hello") - val res = Schedule.recurs(0) - .retryOrElseEither({ throw ex }) { e, _ -> e } - - res.fold({ it shouldBe ex }, { fail("The impossible happened") }) - } - } -) - -@ExperimentalTime -private fun fibs(one: Double): Sequence = - generateSequence(Pair(0.0, one)) { (a, b) -> - Pair(b, (a + b)) - }.map { it.first } - -@ExperimentalTime -private fun exp(base: Double): Sequence = - generateSequence(Pair(base, 1.0)) { (_, n) -> - Pair(base * 2.0.pow(n), n + 1) - }.map { it.first } - -@ExperimentalTime -private fun linear(base: Double): Sequence = - generateSequence(Pair(base, 1.0)) { (_, n) -> - Pair((base * n), (n + 1)) - }.map { it.first } - -@ExperimentalTime -internal fun Sequence.sum(): Double { - var sum = 0.0 - for (element in this) { - sum += element - } - return sum -} - -private suspend fun Schedule.calculateSchedule1(input: I): Schedule.Decision = - calculateSchedule(input, 1).first() - -/** - * Calculates the schedule for [input] I, and [n] iterations - * This allows to calculate the resulting [Schedule.Decision] state and make assertions. - */ -@Suppress("UNCHECKED_CAST") -private suspend fun Schedule.calculateSchedule(input: I, n: Int): List> { - (this as Schedule.ScheduleImpl) - val state = initialState.invoke() - return go(this, input, state, n, emptyList()) -} - -private tailrec suspend fun go( - schedule: Schedule.ScheduleImpl, - input: I, - s: Any?, - rem: Int, - acc: List> -): List> = - if (rem <= 0) acc - else { - val res = schedule.update(input, s) // Calculate new decision - go(schedule, input, res.state, rem - 1, acc + listOf(res)) - } - -private suspend fun checkRepeat(schedule: Schedule, expected: B): Unit { - val count = Atomic(0) - schedule.repeat { - count.updateAndGet { it + 1 } - } shouldBe expected -} - -private suspend fun checkRepeatAsFlow(schedule: Schedule, expected: Flow): Unit { - val count = Atomic(0) - schedule.repeatAsFlow { - count.updateAndGet { it + 1 } - }.zip(expected, ::Pair) - .collect { (a, b) -> a shouldBe b } -} - -@ExperimentalTime -private infix fun Schedule.Decision.eqv(other: Schedule.Decision): Unit { - require(cont == other.cont) { "Decision#cont: ${this.cont} shouldBe ${other.cont}" } - require(delayInNanos.nanoseconds == other.delayInNanos.nanoseconds) { "Decision#delay.nanoseconds: ${this.delayInNanos.nanoseconds} shouldBe ${other.delayInNanos.nanoseconds}" } - if (cont) { - val lh = finish.value() - val rh = other.finish.value() - require(lh == rh) { "Decision#cont: $lh shouldBe $rh" } - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jsMain/kotlin/arrow/fx/coroutines/predef.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jsMain/kotlin/arrow/fx/coroutines/predef.kt deleted file mode 100644 index 27e1ac7d0ca..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jsMain/kotlin/arrow/fx/coroutines/predef.kt +++ /dev/null @@ -1,6 +0,0 @@ -package arrow.fx.coroutines - -public actual fun timeInMillis(): Long { - val x: Number = js("new Date().getTime()") - return x.toLong() -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/ResourceExtensions.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/ResourceExtensions.kt index 96f9bfc9a13..b36b6e8bf3e 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/ResourceExtensions.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/ResourceExtensions.kt @@ -1,10 +1,10 @@ package arrow.fx.coroutines -import arrow.fx.coroutines.continuations.ResourceDSL import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExecutorCoroutineDispatcher +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.newFixedThreadPoolContext import kotlinx.coroutines.newSingleThreadContext @@ -12,7 +12,6 @@ import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.withContext import java.io.Closeable import java.util.concurrent.ExecutorService -import java.util.concurrent.Executors import java.util.concurrent.TimeUnit import kotlin.coroutines.CoroutineContext import kotlin.time.Duration @@ -25,7 +24,7 @@ import kotlin.time.Duration * ```kotlin * import arrow.fx.coroutines.executor * import arrow.fx.coroutines.resourceScope - * import arrow.fx.coroutines.parTraverse + * import arrow.fx.coroutines.parMap * import java.util.concurrent.Executors * import java.util.concurrent.atomic.AtomicInteger * import kotlin.math.max @@ -41,7 +40,7 @@ import kotlin.time.Duration * } * } * - * listOf(1, 2, 3, 4, 5).parTraverse(pool) { i -> + * listOf(1, 2, 3, 4, 5).parMap(pool) { i -> * println("#$i running on ${Thread.currentThread().name}") * } * } @@ -61,16 +60,6 @@ public suspend fun ResourceScope.executor( } }.asCoroutineDispatcher() -@Deprecated( - "This API is being renamed in 2.x.x, use executor builder instead", - ReplaceWith( - "executor { f() }", - "import arrow.fx.coroutines.executor" - ) -) -public fun Resource.Companion.fromExecutor(f: suspend () -> ExecutorService): Resource = - Resource(f) { s, _ -> s.shutdown() }.map(ExecutorService::asCoroutineDispatcher) - public fun executor( timeout: Duration = Duration.INFINITE, closingDispatcher: CoroutineDispatcher = Dispatchers.IO, @@ -110,16 +99,6 @@ public fun closeable( closeable(closingDispatcher, closeable) } -@Deprecated( - "This API is being renamed in 2.x.x, use closeable builder instead", - ReplaceWith( - "closeable { f() }", - "import arrow.fx.coroutines.closeable" - ) -) -public fun Resource.Companion.fromCloseable(f: suspend () -> A): Resource = - Resource(f) { s, _ -> withContext(Dispatchers.IO) { s.close() } } - /** * Creates a [Resource] from an [AutoCloseable], which uses [AutoCloseable.close] for releasing. * @@ -150,16 +129,6 @@ public fun autoCloseable( autoCloseable(closingDispatcher, autoCloseable) } -@Deprecated( - "This API is being renamed in 2.x.x, use closeable builder instead", - ReplaceWith( - "autoCloseable { f() }", - "import arrow.fx.coroutines.autoCloseable" - ) -) -public fun Resource.Companion.fromAutoCloseable(f: suspend () -> A): Resource = - Resource(f) { s, _ -> withContext(Dispatchers.IO) { s.close() } } - /** * Creates a single threaded [CoroutineContext] as a [Resource]. * Upon release an orderly shutdown of the [ExecutorService] takes place in which previously submitted @@ -183,7 +152,7 @@ public fun Resource.Companion.fromAutoCloseable(f: suspend ( * ``` * */ -@OptIn(DelicateCoroutinesApi::class) +@OptIn(DelicateCoroutinesApi::class, ExperimentalCoroutinesApi::class) @ResourceDSL public suspend fun ResourceScope.singleThreadContext(name: String): ExecutorCoroutineDispatcher = closeable { newSingleThreadContext(name) } @@ -191,22 +160,6 @@ public suspend fun ResourceScope.singleThreadContext(name: String): ExecutorCoro public fun singleThreadContext(name: String): Resource = resource { singleThreadContext(name) } -@Deprecated( - "This API is being renamed in 2.x.x, use closeable builder instead", - ReplaceWith( - "singleThreadContext(name)", - "import arrow.fx.coroutines.singleThreadContext" - ) -) -public fun Resource.Companion.singleThreadContext(name: String): Resource = - fromExecutor { - Executors.newSingleThreadExecutor { r -> - Thread(r, name).apply { - isDaemon = true - } - } - } - /** * Creates a single threaded [CoroutineContext] as a [Resource]. * Upon release an orderly shutdown of the [ExecutorService] takes place in which previously submitted diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/predef.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/predef.kt deleted file mode 100644 index 3edd9239d69..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmMain/kotlin/arrow/fx/coroutines/predef.kt +++ /dev/null @@ -1,15 +0,0 @@ -package arrow.fx.coroutines - -/* - * For JS: - * ``` - * val x: Number = js("new Date().getTime()") - * return x.toLong() - * ``` - * - * For Native: - * - `getTimeMillis()` - * - https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.system/get-time-millis.html - */ -public actual fun timeInMillis(): Long = - System.currentTimeMillis() diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/FlowJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/FlowJvmTest.kt index 1732137dabd..7e1421a311f 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/FlowJvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/FlowJvmTest.kt @@ -1,43 +1,44 @@ package arrow.fx.coroutines -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.string.shouldContain import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.checkAll +import kotlin.test.Test import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.toSet -import kotlin.time.ExperimentalTime import kotlinx.coroutines.flow.flowOn @OptIn(FlowPreview::class, ExperimentalCoroutinesApi::class) -@ExperimentalTime -class FlowJvmTest : StringSpec({ - "parMap - single thread - identity" { - single.use { ctx -> +class FlowJvmTest { + @Test fun parMapSingleThreadIdentity() = runTestUsingDefaultDispatcher { + resourceScope { + val ctx = singleThreadContext("single") checkAll(Arb.flow(Arb.int())) { flow -> flow.parMap { it }.flowOn(ctx) .toList() shouldBe flow.toList() } } } - - "parMap - flowOn" { - single.use { ctx -> + + @Test fun parMapflowOn() = runTestUsingDefaultDispatcher { + resourceScope { + val ctx = singleThreadContext("single") checkAll(Arb.flow(Arb.int())) { flow -> flow.parMap { Thread.currentThread().name }.flowOn(ctx) .toList().forEach { - it shouldContain singleThreadName + it shouldContain "single" } } } } - "parMapUnordered - single thread - identity" { - single.use { ctx -> + @Test fun parMapUnorderedSingleThreadIdentity() = runTestUsingDefaultDispatcher { + resourceScope { + val ctx = singleThreadContext("single") checkAll(Arb.flow(Arb.int())) { flow -> flow.parMapUnordered { it }.flowOn(ctx) .toSet() shouldBe flow.toSet() @@ -45,14 +46,15 @@ class FlowJvmTest : StringSpec({ } } - "parMapUnordered - flowOn" { - single.use { ctx -> + @Test fun parMapUnorderedFlowOn() = runTestUsingDefaultDispatcher { + resourceScope { + val ctx = singleThreadContext("single") checkAll(Arb.flow(Arb.int())) { flow -> flow.parMap { Thread.currentThread().name }.flowOn(ctx) .toList().forEach { - it shouldContain singleThreadName + it shouldContain "single" } } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParMapJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParMapJvmTest.kt index 732b246fb2f..71f1617df6b 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParMapJvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParMapJvmTest.kt @@ -1,26 +1,26 @@ package arrow.fx.coroutines import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.string.shouldStartWith import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.checkAll +import kotlin.test.Test -class ParMapJvmTest : StringSpec({ - "parMap runs on provided context" { // 100 is same default length as Arb.list +class ParMapJvmTest { + @Test fun parMapRunsOnProvidedContext() = runTestUsingDefaultDispatcher { // 100 is same default length as Arb.list checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parMap(ctx) { Thread.currentThread().name } + val res = resourceScope { + (0 until i).parMap(single()) { Thread.currentThread().name } } res.forEach { it shouldStartWith "single" } } } - "parMap(concurrency = 3) runs on provided context" { + @Test fun parMapConcurrency3RunsOnProvidedContext() = runTestUsingDefaultDispatcher { checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parMap(ctx, concurrency = 3) { + val res = resourceScope { + (0 until i).parMap(single(), concurrency = 3) { Thread.currentThread().name } } @@ -28,10 +28,10 @@ class ParMapJvmTest : StringSpec({ } } - "parMapOrAccumulate(combine = emptyError) runs on provided context" { // 100 is same default length as Arb.list + @Test fun parMapOrAccumulateCombineEmptyErrorRunsOnProvidedContext() = runTestUsingDefaultDispatcher { // 100 is same default length as Arb.list checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parMapOrAccumulate(ctx, combine = emptyError) { Thread.currentThread().name } + val res = resourceScope { + (0 until i).parMapOrAccumulate(single(), combine = emptyError) { Thread.currentThread().name } } res.fold( { fail("Expected Right but found $res") }, @@ -40,11 +40,11 @@ class ParMapJvmTest : StringSpec({ } } - "parMapOrAccumulate(combine = emptyError, concurrency = 3) runs on provided context" { // 100 is same default length as Arb.list + @Test fun parMapOrAccumulateCombineEmptyErrorConcurrency3RunsOnProvidedContext() = runTestUsingDefaultDispatcher { // 100 is same default length as Arb.list checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> + val res = resourceScope { (0 until i).parMapOrAccumulate( - ctx, + single(), combine = emptyError, concurrency = 3 ) { Thread.currentThread().name } @@ -56,10 +56,10 @@ class ParMapJvmTest : StringSpec({ } } - "parMapOrAccumulate runs on provided context" { // 100 is same default length as Arb.list + @Test fun parMapOrAccumulateRunsOnProvidedContext() = runTestUsingDefaultDispatcher { // 100 is same default length as Arb.list checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parMapOrAccumulate(ctx) { + val res = resourceScope { + (0 until i).parMapOrAccumulate(single()) { Thread.currentThread().name } } @@ -70,10 +70,11 @@ class ParMapJvmTest : StringSpec({ } } - "parMapOrAccumulate(concurrency = 3) runs on provided context" { // 100 is same default length as Arb.list + @Test fun parMapOrAccumulateConcurrency3RunsOnProvidedContext() = runTestUsingDefaultDispatcher { // 100 is same default length as Arb.list checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parMapOrAccumulate(ctx, concurrency = 3) { + + val res = resourceScope { + (0 until i).parMapOrAccumulate(single(), concurrency = 3) { Thread.currentThread().name } } @@ -83,7 +84,9 @@ class ParMapJvmTest : StringSpec({ ) } } -}) +} private val emptyError: (Nothing, Nothing) -> Nothing = { _, _ -> throw AssertionError("Should not be called") } + +suspend fun ResourceScope.single() = singleThreadContext("single") diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseEitherJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseEitherJvmTest.kt deleted file mode 100644 index 40fd88baf3e..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseEitherJvmTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.right -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.string.shouldStartWith -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.checkAll - -class ParTraverseEitherJvmTest : StringSpec({ - "parTraverseEither finishes on single thread " { // 100 is same default length as Arb.list - checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parTraverseEither(ctx) { Thread.currentThread().name.right() } - } - assertSoftly { - res.getOrNull()?.forEach { - it shouldStartWith "single" - } ?: fail("Expected Right but found $res") - } - } - } - } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseJvmTest.kt deleted file mode 100644 index f858e254177..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseJvmTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package arrow.fx.coroutines - -import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.string.shouldStartWith -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.checkAll - -class ParTraverseJvmTest : StringSpec({ - "parTraverse runs on provided context " { // 100 is same default length as Arb.list - checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parTraverse(ctx) { Thread.currentThread().name } - } - assertSoftly { - res.forEach { it shouldStartWith "single" } - } - } - } - - "parTraverseN runs on provided thread" { - checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parTraverseN(ctx, 3) { - Thread.currentThread().name - } - } - assertSoftly { - res.forEach { it shouldStartWith "single" } - } - } - } -}) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedJvmTest.kt deleted file mode 100644 index bfd393fd031..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParTraverseValidatedJvmTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.orNull -import arrow.core.validNel -import arrow.typeclasses.Semigroup -import io.kotest.assertions.assertSoftly -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.string.shouldStartWith -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.checkAll - -class ParTraverseValidatedJvmTest : StringSpec({ - "parTraverseValidated finishes on single thread " { // 100 is same default length as Arb.list - checkAll(Arb.int(min = Int.MIN_VALUE, max = 100)) { i -> - val res = single.use { ctx -> - (0 until i).parTraverseValidated(ctx, Semigroup.nonEmptyList()) { Thread.currentThread().name.validNel() } - } - assertSoftly { - res.orNull()?.forEach { - it shouldStartWith "single" - } ?: fail("Expected Right but found $res") - } - } - } -}) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip2JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip2JvmTest.kt index 8136ad07765..09b631ff251 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip2JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip2JvmTest.kt @@ -2,69 +2,78 @@ package arrow.fx.coroutines import arrow.core.Either import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors - -class ParZip2JvmTest : StringSpec({ - "parZip 2 returns to original context" { - val zipCtxName = "parZip2" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(2, NamedThreadFactory { zipCtxName }) } +import kotlin.coroutines.CoroutineContext +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName +class ParZip2JvmTest { + @Test fun parZip2ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip2" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(2, NamedThreadFactory(zipCtxName)) } + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" - val (s1, s2) = parZip( - _zipCtx, - { Thread.currentThread().name }, - { Thread.currentThread().name }) { a, b -> Pair(a, b) } + val (s1, s2) = parZip( + zipCtx, + { Thread.currentThread().name }, + { Thread.currentThread().name }) { a, b -> Pair(a, b) } - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName - } - } + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + Thread.currentThread().name shouldStartWith "single" + } } + } - "parZip 2 returns to original context on failure" { - val zipCtxName = "parZip2" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(2, NamedThreadFactory { zipCtxName }) } - + @Test fun parZip2ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip2" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(2, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..2), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" - Either.catch { - when (choose) { - 1 -> parZip(_zipCtx, { e.suspend() }, { awaitCancellation() }) { _, _ -> Unit } - else -> parZip(_zipCtx, { awaitCancellation() }, { e.suspend() }) { _, _ -> Unit } - } - } should leftException(e) + Either.catch { + when (choose) { + 1 -> parZip(zipCtx, { throw e }, { awaitCancellation() }) { _, _ -> Unit } + else -> parZip(zipCtx, { awaitCancellation() }, { throw e }) { _, _ -> Unit } + } + } should leftException(e) - threadName() shouldStartWith singleThreadName - } + Thread.currentThread().name shouldStartWith "single" } } } + } - "parZip 2 finishes on single thread" { - checkAll(Arb.string()) { - val res = single.use { ctx -> - parZip(ctx, { Thread.currentThread().name }, { Thread.currentThread().name }) { a, b -> listOf(a, b) } - } - assertSoftly { - res.forEach { it shouldStartWith "single" } - } + @Test fun parZip2FinishesOnSingleThread() = runTestUsingDefaultDispatcher { + checkAll(Arb.string()) { + val res = resourceScope { + val ctx = singleThreadContext("single") + parZip(ctx, { Thread.currentThread().name }, { Thread.currentThread().name }) { a, b -> listOf(a, b) } + } + assertSoftly { + res.forEach { it shouldStartWith "single" } } } } -) +} + +suspend fun parallelCtx( + nThreads: Int, + mapCtxName: String, + use: suspend (CoroutineContext, CoroutineContext) -> Unit, +): Unit = resourceScope { + use(singleThreadContext("single"), fixedThreadPoolContext(nThreads, mapCtxName)) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip3JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip3JvmTest.kt index 8ac1f52f0bf..4a2bc4ae88e 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip3JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip3JvmTest.kt @@ -2,81 +2,84 @@ package arrow.fx.coroutines import arrow.core.Either import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip3JvmTest : StringSpec({ - "parZip 3 returns to original context" { +class ParZip3JvmTest { + @Test fun parZip3ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip3" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(3, NamedThreadFactory { zipCtxName }) } - - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName - - val (s1, s2, s3) = parZip( - _zipCtx, - { Thread.currentThread().name }, - { Thread.currentThread().name }, - { Thread.currentThread().name }) { a, b, c -> Triple(a, b, c) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(3, NamedThreadFactory(zipCtxName)) } + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" + val (s1, s2, s3) = parZip( + zipCtx, + { Thread.currentThread().name }, + { Thread.currentThread().name }, + { Thread.currentThread().name }) { a, b, c -> Triple(a, b, c) } - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName - } + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + Thread.currentThread().name shouldStartWith "single" } + } } - "parZip 3 returns to original context on failure" { + @Test fun parZip3ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip3" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(3, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(3, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..3), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" Either.catch { when (choose) { 1 -> parZip( - _zipCtx, - { e.suspend() }, + zipCtx, + { throw e }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _ -> Unit } + 2 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() } ) { _, _, _ -> Unit } + else -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() } + { throw e } ) { _, _, _ -> Unit } } } should leftException(e) - threadName() shouldStartWith singleThreadName + Thread.currentThread().name shouldStartWith "single" } } } } - "parZip 3 finishes on single thread" { + @Test fun parZip3FinishesOnSingleThread() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { - val res = single.use { ctx -> + val res = resourceScope { + val ctx = singleThreadContext("single") parZip( ctx, { Thread.currentThread().name }, @@ -88,4 +91,4 @@ class ParZip3JvmTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip4JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip4JvmTest.kt index 8149a71da27..763b8c14f2b 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip4JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip4JvmTest.kt @@ -3,28 +3,30 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple4 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip4JvmTest : StringSpec({ - "parZip 4 returns to original context" { +class ParZip4JvmTest { + @Test fun parZip4ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip4" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(4, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(4, NamedThreadFactory(zipCtxName)) } - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" val (s1, s2, s3, s4) = parZip( - _zipCtx, + zipCtx, { Thread.currentThread().name }, { Thread.currentThread().name }, { Thread.currentThread().name }, @@ -35,63 +37,66 @@ class ParZip4JvmTest : StringSpec({ s2 shouldStartWith zipCtxName s3 shouldStartWith zipCtxName s4 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName + Thread.currentThread().name shouldStartWith "single" } } - } - "parZip 4 returns to original context on failure" { + @Test fun parZip4ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip4" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(4, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(4, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..4), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + Thread.currentThread().name shouldStartWith "single" Either.catch { when (choose) { 1 -> parZip( - _zipCtx, - { e.suspend() }, + zipCtx, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _ -> Unit } + 2 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _ -> Unit } + 3 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() } ) { _, _, _, _ -> Unit } + else -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() } + { throw e } ) { _, _, _, _ -> Unit } } } should leftException(e) - threadName() shouldStartWith singleThreadName + Thread.currentThread().name shouldStartWith "single" } } } } - "parZip 4 finishes on single thread" { + @Test fun parZip4FinishesOnSingleThread() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { - val res = single.use { ctx -> + val res = resourceScope { + val ctx = singleThreadContext("single") parZip( ctx, { Thread.currentThread().name }, @@ -105,4 +110,3 @@ class ParZip4JvmTest : StringSpec({ } } } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip5JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip5JvmTest.kt index 1187866b28a..ad6869b306f 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip5JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip5JvmTest.kt @@ -3,122 +3,127 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple5 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip5JvmTest : StringSpec({ - val threadName: suspend CoroutineScope.() -> String = - { Thread.currentThread().name } +class ParZip5JvmTest { + val threadName: suspend CoroutineScope.() -> String = + { Thread.currentThread().name } - "parZip 5 returns to original context" { - val zipCtxName = "parZip5" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(5, NamedThreadFactory { zipCtxName }) } + @Test fun parZip5ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip5" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(5, NamedThreadFactory(zipCtxName)) } - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + threadName() shouldStartWith "single" - val (s1, s2, s3, s4, s5) = parZip( - _zipCtx, threadName, threadName, threadName, threadName, threadName - ) { a, b, c, d, e -> Tuple5(a, b, c, d, e) } - - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - s4 shouldStartWith zipCtxName - s5 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName - } - } + val (s1, s2, s3, s4, s5) = parZip( + zipCtx, threadName, threadName, threadName, threadName, threadName + ) { a, b, c, d, e -> Tuple5(a, b, c, d, e) } + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + s4 shouldStartWith zipCtxName + s5 shouldStartWith zipCtxName + threadName() shouldStartWith "single" + } } + } - "parZip 5 returns to original context on failure" { - val zipCtxName = "parZip5" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(5, NamedThreadFactory { zipCtxName }) } + @Test fun parZip5ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip5" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(5, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..5), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + threadName() shouldStartWith "single" + + Either.catch { + when (choose) { + 1 -> parZip( + zipCtx, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _ -> Unit } - Either.catch { - when (choose) { - 1 -> parZip( - _zipCtx, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _ -> Unit } - 2 -> parZip( - _zipCtx, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _ -> Unit } - 3 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _ -> Unit } - 4 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() } - ) { _, _, _, _, _ -> Unit } - else -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() } - ) { _, _, _, _, _ -> Unit } - } - } should leftException(e) + 2 -> parZip( + zipCtx, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _ -> Unit } - threadName() shouldStartWith singleThreadName - } + 3 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _ -> Unit } + + 4 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() } + ) { _, _, _, _, _ -> Unit } + + else -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e } + ) { _, _, _, _, _ -> Unit } + } + } should leftException(e) + + threadName() shouldStartWith "single" } } } + } - "parZip 5 finishes on single thread" { - checkAll(Arb.string()) { - val res = single.use { ctx -> - parZip(ctx, threadName, threadName, threadName, threadName, threadName) { a, b, c, d, e -> - listOf( - a, - b, - c, - d, - e - ) - } - } - assertSoftly { - res.forEach { it shouldStartWith "single" } + @Test fun parZip5FinishesOnSingleThread() = runTestUsingDefaultDispatcher { + checkAll(Arb.string()) { + val res = resourceScope { + val ctx = singleThreadContext("single") + parZip(ctx, threadName, threadName, threadName, threadName, threadName) { a, b, c, d, e -> + listOf( + a, + b, + c, + d, + e + ) } } + assertSoftly { + res.forEach { it shouldStartWith "single" } + } } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip6JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip6JvmTest.kt index e5b835843f1..1e37b0e8768 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip6JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip6JvmTest.kt @@ -3,124 +3,131 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple6 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip6JvmTest : StringSpec({ +class ParZip6JvmTest { val threadName: suspend CoroutineScope.() -> String = { Thread.currentThread().name } - "parZip 6 returns to original context" { + @Test fun parZip6ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip6" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(6, NamedThreadFactory { zipCtxName }) } - - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(6, NamedThreadFactory(zipCtxName)) } - val (s1, s2, s3, s4, s5, s6) = parZip( - _zipCtx, threadName, threadName, threadName, threadName, threadName, threadName - ) { a, b, c, d, e, f -> - Tuple6(a, b, c, d, e, f) - } + withContext(single()) { + threadName() shouldStartWith "single" - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - s4 shouldStartWith zipCtxName - s5 shouldStartWith zipCtxName - s6 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName + val (s1, s2, s3, s4, s5, s6) = parZip( + zipCtx, threadName, threadName, threadName, threadName, threadName, threadName + ) { a, b, c, d, e, f -> + Tuple6(a, b, c, d, e, f) } - } + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + s4 shouldStartWith zipCtxName + s5 shouldStartWith zipCtxName + s6 shouldStartWith zipCtxName + threadName() shouldStartWith "single" + } + } } - "parZip 6 returns to original context on failure" { + @Test fun parZip6ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip6" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(6, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(6, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..6), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + threadName() shouldStartWith "single" Either.catch { when (choose) { 1 -> parZip( - _zipCtx, - { e.suspend() }, + zipCtx, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _ -> Unit } + 2 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _ -> Unit } + 3 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _ -> Unit } + 4 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _ -> Unit } + 5 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() } ) { _, _, _, _, _, _ -> Unit } + else -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() } + { throw e } ) { _, _, _, _, _, _ -> Unit } } } should leftException(e) - threadName() shouldStartWith singleThreadName + threadName() shouldStartWith "single" } } } } - "parZip 6 finishes on single thread" { + @Test fun parZip6FinishesOnSingleThread() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { - val res = single.use { ctx -> + val res = resourceScope { + val ctx = singleThreadContext("single") parZip(ctx, threadName, threadName, threadName, threadName, threadName, threadName) { a, b, c, d, e, f -> listOf(a, b, c, d, e, f) } @@ -130,4 +137,4 @@ class ParZip6JvmTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip7JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip7JvmTest.kt index 7bb2fbba6e1..fe8d2fc5e85 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip7JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip7JvmTest.kt @@ -3,158 +3,165 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple7 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip7JvmTest : StringSpec({ - val threadName: suspend CoroutineScope.() -> String = - { Thread.currentThread().name } +class ParZip7JvmTest { + val threadName: suspend CoroutineScope.() -> String = + { Thread.currentThread().name } - "parZip 7 returns to original context" { - val zipCtxName = "parZip7" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(7, NamedThreadFactory { zipCtxName }) } + @Test fun parZip7ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip7" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(7, NamedThreadFactory(zipCtxName)) } - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + withContext(single()) { + threadName() shouldStartWith "single" - val (s1, s2, s3, s4, s5, s6, s7) = parZip( - _zipCtx, threadName, threadName, threadName, threadName, threadName, threadName, threadName - ) { a, b, c, d, e, f, g -> - Tuple7(a, b, c, d, e, f, g) - } - - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - s4 shouldStartWith zipCtxName - s5 shouldStartWith zipCtxName - s6 shouldStartWith zipCtxName - s7 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName - } + val (s1, s2, s3, s4, s5, s6, s7) = parZip( + zipCtx, threadName, threadName, threadName, threadName, threadName, threadName, threadName + ) { a, b, c, d, e, f, g -> + Tuple7(a, b, c, d, e, f, g) } + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + s4 shouldStartWith zipCtxName + s5 shouldStartWith zipCtxName + s6 shouldStartWith zipCtxName + s7 shouldStartWith zipCtxName + threadName() shouldStartWith "single" + } } + } - "parZip 7 returns to original context on failure" { - val zipCtxName = "parZip7" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(7, NamedThreadFactory { zipCtxName }) } + @Test fun parZip7ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { + val zipCtxName = "parZip7" + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(7, NamedThreadFactory(zipCtxName)) } checkAll(Arb.int(1..7), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName - - Either.catch { - when (choose) { - 1 -> parZip( - _zipCtx, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - 2 -> parZip( - _zipCtx, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - 3 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - 4 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - 5 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - 6 -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() }, - { awaitCancellation() } - ) { _, _, _, _, _, _, _ -> Unit } - else -> parZip( - _zipCtx, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { awaitCancellation() }, - { e.suspend() } - ) { _, _, _, _, _, _, _ -> Unit } - } - } should leftException(e) - threadName() shouldStartWith singleThreadName - } + withContext(single()) { + threadName() shouldStartWith "single" + + Either.catch { + when (choose) { + 1 -> parZip( + zipCtx, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + 2 -> parZip( + zipCtx, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + 3 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + 4 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + 5 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + 6 -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e }, + { awaitCancellation() } + ) { _, _, _, _, _, _, _ -> Unit } + + else -> parZip( + zipCtx, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { awaitCancellation() }, + { throw e } + ) { _, _, _, _, _, _, _ -> Unit } + } + } should leftException(e) + threadName() shouldStartWith "single" } } } + } - "parZip 7 finishes on single thread" { - checkAll(Arb.string()) { - val res = single.use { ctx -> - parZip( - ctx, - threadName, - threadName, - threadName, - threadName, - threadName, - threadName, - threadName - ) { a, b, c, d, e, f, g -> - listOf(a, b, c, d, e, f, g) - } - } - assertSoftly { - res.forEach { it shouldStartWith "single" } + @Test fun parZip7FinishesOnSingleThread() = runTestUsingDefaultDispatcher { + checkAll(Arb.string()) { + val res = resourceScope { + val ctx = singleThreadContext("single") + parZip( + ctx, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName + ) { a, b, c, d, e, f, g -> + listOf(a, b, c, d, e, f, g) } } + assertSoftly { + res.forEach { it shouldStartWith "single" } + } } } -) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip8JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip8JvmTest.kt index 2282ed6a77d..25d90771a30 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip8JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip8JvmTest.kt @@ -3,64 +3,65 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple8 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import java.util.concurrent.Executors import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class ParZip8JvmTest : StringSpec({ +class ParZip8JvmTest { val threadName: suspend CoroutineScope.() -> String = { Thread.currentThread().name } - "parZip 8 returns to original context" { + @Test fun parZip8ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip8" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(8, NamedThreadFactory { zipCtxName }) } - - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName - - val (s1, s2, s3, s4, s5, s6, s7, s8) = parZip( - _zipCtx, threadName, threadName, threadName, threadName, threadName, threadName, threadName, threadName - ) { a, b, c, d, e, f, g, h -> - Tuple8(a, b, c, d, e, f, g, h) - } - - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - s4 shouldStartWith zipCtxName - s5 shouldStartWith zipCtxName - s6 shouldStartWith zipCtxName - s7 shouldStartWith zipCtxName - s8 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(8, NamedThreadFactory(zipCtxName)) } + withContext(single()) { + threadName() shouldStartWith "single" + + val (s1, s2, s3, s4, s5, s6, s7, s8) = parZip( + zipCtx, threadName, threadName, threadName, threadName, threadName, threadName, threadName, threadName + ) { a, b, c, d, e, f, g, h -> + Tuple8(a, b, c, d, e, f, g, h) } + + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + s4 shouldStartWith zipCtxName + s5 shouldStartWith zipCtxName + s6 shouldStartWith zipCtxName + s7 shouldStartWith zipCtxName + s8 shouldStartWith zipCtxName + threadName() shouldStartWith "single" } + } } - "parZip 8 returns to original context on failure" { + @Test fun parZip8ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip8" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(8, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(8, NamedThreadFactory(zipCtxName)) } - checkAll(Arb.int(1..8), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + checkAll(Arb.int(1..8), Arb.throwable()) { choose, e -> + withContext(single()) { + threadName() shouldStartWith "single" Either.catch { when (choose) { 1 -> parZip( - _zipCtx, - { e.suspend() }, + zipCtx, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -69,10 +70,11 @@ class ParZip8JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } + 2 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -80,62 +82,67 @@ class ParZip8JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } - 3 -> parZip( + 3 -> parZip( { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _ -> Unit } + 4 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } + 5 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } + 6 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } + 7 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _ -> Unit } + else -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -143,19 +150,20 @@ class ParZip8JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() } + { throw e } ) { _, _, _, _, _, _, _, _ -> Unit } } } should leftException(e) - threadName() shouldStartWith singleThreadName + threadName() shouldStartWith "single" } } } } - "parZip 8 finishes on single thread" { + @Test fun parZip8FinishesOnSingleThread() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { - val res = single.use { ctx -> + val res = resourceScope { + val ctx = singleThreadContext("single") parZip( ctx, threadName, @@ -175,4 +183,4 @@ class ParZip8JvmTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip9JvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip9JvmTest.kt index 57369be6449..89d18c47c86 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip9JvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ParZip9JvmTest.kt @@ -3,9 +3,9 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.Tuple9 import io.kotest.assertions.assertSoftly -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith +import io.kotest.mpp.NamedThreadFactory import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string @@ -13,55 +13,65 @@ import io.kotest.property.checkAll import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext +import kotlin.test.Test import java.util.concurrent.Executors +import kotlin.time.Duration.Companion.seconds -class ParZip9JvmTest : StringSpec({ +class ParZip9JvmTest { val threadName: suspend CoroutineScope.() -> String = { Thread.currentThread().name } - "parZip 9 returns to original context" { + @Test fun parZip9ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip9" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(9, NamedThreadFactory { zipCtxName }) } - - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName - - val (s1, s2, s3, s4, s5, s6, s7, s8, s9) = parZip( - _zipCtx, threadName, threadName, threadName, threadName, threadName, threadName, threadName, threadName, threadName - ) { a, b, c, d, e, f, g, h, i -> - Tuple9(a, b, c, d, e, f, g, h, i) - } - - s1 shouldStartWith zipCtxName - s2 shouldStartWith zipCtxName - s3 shouldStartWith zipCtxName - s4 shouldStartWith zipCtxName - s5 shouldStartWith zipCtxName - s6 shouldStartWith zipCtxName - s7 shouldStartWith zipCtxName - s8 shouldStartWith zipCtxName - s9 shouldStartWith zipCtxName - threadName() shouldStartWith singleThreadName + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(9, NamedThreadFactory(zipCtxName)) } + withContext(single()) { + threadName() shouldStartWith "single" + + val (s1, s2, s3, s4, s5, s6, s7, s8, s9) = parZip( + zipCtx, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName, + threadName + ) { a, b, c, d, e, f, g, h, i -> + Tuple9(a, b, c, d, e, f, g, h, i) } + + s1 shouldStartWith zipCtxName + s2 shouldStartWith zipCtxName + s3 shouldStartWith zipCtxName + s4 shouldStartWith zipCtxName + s5 shouldStartWith zipCtxName + s6 shouldStartWith zipCtxName + s7 shouldStartWith zipCtxName + s8 shouldStartWith zipCtxName + s9 shouldStartWith zipCtxName + threadName() shouldStartWith "single" } + } } - "parZip 9 returns to original context on failure" { + @Test fun parZip9ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val zipCtxName = "parZip9" - val zipCtx = Resource.fromExecutor { Executors.newFixedThreadPool(9, NamedThreadFactory { zipCtxName }) } + resourceScope { + val zipCtx = executor { Executors.newFixedThreadPool(9, NamedThreadFactory(zipCtxName)) } - checkAll(Arb.int(1..9), Arb.throwable()) { choose, e -> - single.zip(zipCtx).use { (_single, _zipCtx) -> - withContext(_single) { - threadName() shouldStartWith singleThreadName + checkAll(Arb.int(1..9), Arb.throwable()) { choose, e -> + withContext(single()) { + threadName() shouldStartWith "single" Either.catch { when (choose) { 1 -> parZip( - _zipCtx, - { e.suspend() }, + zipCtx, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -71,10 +81,11 @@ class ParZip9JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 2 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -83,11 +94,12 @@ class ParZip9JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 3 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -95,56 +107,61 @@ class ParZip9JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 4 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 5 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 6 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 7 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + 8 -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -152,11 +169,12 @@ class ParZip9JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() }, + { throw e }, { awaitCancellation() } ) { _, _, _, _, _, _, _, _, _ -> Unit } + else -> parZip( - _zipCtx, + zipCtx, { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, @@ -165,21 +183,21 @@ class ParZip9JvmTest : StringSpec({ { awaitCancellation() }, { awaitCancellation() }, { awaitCancellation() }, - { e.suspend() } + { throw e } ) { _, _, _, _, _, _, _, _, _ -> Unit } } } should leftException(e) - threadName() shouldStartWith singleThreadName + threadName() shouldStartWith "single" } } } } - "parZip 9 finishes on single thread" { + @Test fun parZip9FinishesOnSingleThread() = runTestUsingDefaultDispatcher { checkAll(Arb.string()) { - val res = single.use { ctx -> + val res = resourceScope { parZip( - ctx, + single(), threadName, threadName, threadName, @@ -198,4 +216,4 @@ class ParZip9JvmTest : StringSpec({ } } } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/RaceNJvmTest.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/RaceNJvmTest.kt index 37737a6fff1..83f56602c8d 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/RaceNJvmTest.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/RaceNJvmTest.kt @@ -2,7 +2,6 @@ package arrow.fx.coroutines import arrow.core.Either import arrow.core.identity -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.string.shouldStartWith import io.kotest.property.Arb @@ -10,122 +9,115 @@ import io.kotest.property.arbitrary.int import io.kotest.property.checkAll import kotlinx.coroutines.awaitCancellation import kotlinx.coroutines.withContext -import java.util.concurrent.Executors +import kotlin.test.Test +import kotlin.time.Duration.Companion.seconds -class RaceNJvmTest : StringSpec({ - "race2 returns to original context" { +class RaceNJvmTest { + @Test fun race2ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val racerName = "race2" - val racer = executor { Executors.newFixedThreadPool(2, NamedThreadFactory { racerName }) } - checkAll(Arb.int(1..2)) { choose -> - single.zip(racer).use { (single, raceCtx) -> - withContext(single) { - threadName() shouldStartWith singleThreadName - + resourceScope { + val pool = fixedThreadPoolContext(2, racerName) + withContext(singleThreadContext("single")) { + Thread.currentThread().name shouldStartWith "single" + val racedOn = when (choose) { - 1 -> raceN(raceCtx, { threadName() }, { awaitCancellation() }).swap().getOrNull() - else -> raceN(raceCtx, { awaitCancellation() }, { threadName() }).getOrNull() + 1 -> raceN(pool, { Thread.currentThread().name }, { awaitCancellation() }).swap().getOrNull() + else -> raceN(pool, { awaitCancellation() }, { Thread.currentThread().name }).getOrNull() } - + racedOn shouldStartWith racerName - threadName() shouldStartWith singleThreadName + Thread.currentThread().name shouldStartWith "single" } } } } - "race2 returns to original context on failure" { + @Test fun race2ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val racerName = "race2" - val racer = executor { Executors.newFixedThreadPool(2, NamedThreadFactory { racerName }) } - + checkAll(Arb.int(1..2), Arb.throwable()) { choose, e -> - single.zip(racer).use { (single, raceCtx) -> - withContext(single) { - threadName() shouldStartWith singleThreadName - + resourceScope { + val pool = fixedThreadPoolContext(2, racerName) + withContext(singleThreadContext("single")) { + Thread.currentThread().name shouldStartWith "single" + Either.catch { when (choose) { - 1 -> raceN(raceCtx, { e.suspend() }, { awaitCancellation() }).swap().getOrNull() - else -> raceN(raceCtx, { awaitCancellation() }, { e.suspend() }).getOrNull() + 1 -> raceN(pool, { throw e }, { awaitCancellation() }).swap().getOrNull() + else -> raceN(pool, { awaitCancellation() }, { throw e }).getOrNull() } } should leftException(e) - - threadName() shouldStartWith singleThreadName + + Thread.currentThread().name shouldStartWith "single" } } } } - - "race3 returns to original context" { + + @Test fun firstRacerOutOf2AlwaysWinsOnASingleThread() = runTestUsingDefaultDispatcher { + resourceScope { + val ctx = singleThreadContext("single") + raceN(ctx, { Thread.currentThread().name }, { Thread.currentThread().name }) + }.swap().getOrNull() shouldStartWith "single" + } + + @Test fun race3ReturnsToOriginalContext() = runTestUsingDefaultDispatcher { val racerName = "race3" - val racer = executor { Executors.newFixedThreadPool(3, NamedThreadFactory { racerName }) } checkAll(Arb.int(1..3)) { choose -> - single.zip(racer).use { (single, raceCtx) -> + parallelCtx(3, racerName) { single, raceCtx -> withContext(single) { - threadName() shouldStartWith singleThreadName - + Thread.currentThread().name shouldStartWith "single" + val racedOn = when (choose) { 1 -> - raceN(raceCtx, { threadName() }, { awaitCancellation() }, { awaitCancellation() }) + raceN(raceCtx, { Thread.currentThread().name }, { awaitCancellation() }, { awaitCancellation() }) .fold(::identity, { null }, { null }) + 2 -> - raceN(raceCtx, { awaitCancellation() }, { threadName() }, { awaitCancellation() }) + raceN(raceCtx, { awaitCancellation() }, { Thread.currentThread().name }, { awaitCancellation() }) .fold({ null }, ::identity, { null }) + else -> - raceN(raceCtx, { awaitCancellation() }, { awaitCancellation() }, { threadName() }) + raceN(raceCtx, { awaitCancellation() }, { awaitCancellation() }, { Thread.currentThread().name }) .fold({ null }, { null }, ::identity) } - + racedOn shouldStartWith racerName - threadName() shouldStartWith singleThreadName + Thread.currentThread().name shouldStartWith "single" } } } } - - "race3 returns to original context on failure" { + + @Test fun race3ReturnsToOriginalContextOnFailure() = runTestUsingDefaultDispatcher { val racerName = "race3" - val racer = Resource.fromExecutor { Executors.newFixedThreadPool(3, NamedThreadFactory { racerName }) } - + checkAll(Arb.int(1..3), Arb.throwable()) { choose, e -> - single.zip(racer).use { (single, raceCtx) -> + parallelCtx(3, racerName) { single, raceCtx -> withContext(single) { - threadName() shouldStartWith singleThreadName - + Thread.currentThread().name shouldStartWith "single" + Either.catch { when (choose) { 1 -> - raceN(raceCtx, { e.suspend() }, { awaitCancellation() }, { awaitCancellation() }) - .fold(::identity, { null }, { null }) + raceN(raceCtx, { throw e }, { awaitCancellation() }, { awaitCancellation() }) + .fold({ x: String? -> x }, { null }, { null }) + 2 -> - raceN(raceCtx, { awaitCancellation() }, { e.suspend() }, { awaitCancellation() }) - .fold({ null }, ::identity, { null }) + raceN(raceCtx, { awaitCancellation() }, { throw e }, { awaitCancellation() }) + .fold({ null }, { x: String? -> x }, { null }) + else -> - raceN(raceCtx, { awaitCancellation() }, { awaitCancellation() }, { e.suspend() }) - .fold({ null }, { null }, ::identity) + raceN(raceCtx, { awaitCancellation() }, { awaitCancellation() }, { throw e }) + .fold({ null }, { null }, { x: String? -> x }) } } should leftException(e) - - threadName() shouldStartWith singleThreadName + + Thread.currentThread().name shouldStartWith "single" } } } } - - /* These tests seem to not hold anymore - - "first racer out of 2 always wins on a single thread" { - single.use { ctx -> - raceN(ctx, { threadName() }, { threadName() }) - }.swap().getOrNull() shouldStartWith "single" - } - - "first racer out of 3 always wins on a single thread" { - (single.use { ctx -> - raceN(ctx, { threadName() }, { threadName() }, { threadName() }) - } as? Race3.First)?.winner shouldStartWith "single" - } - */ } -) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ResourceTestJvm.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ResourceTestJvm.kt index b9089fa3af5..20f21fd44cb 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ResourceTestJvm.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/ResourceTestJvm.kt @@ -1,7 +1,6 @@ package arrow.fx.coroutines import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.matchers.types.shouldBeTypeOf import java.util.concurrent.atomic.AtomicBoolean @@ -11,8 +10,10 @@ import io.kotest.property.Arb import io.kotest.property.checkAll import kotlinx.coroutines.CompletableDeferred import kotlin.test.DefaultAsserter.fail +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class ResourceTestJvm : StringSpec({ +class ResourceTestJvm { class AutoCloseableTest : AutoCloseable { val didClose = AtomicBoolean(false) @@ -24,47 +25,57 @@ class ResourceTestJvm : StringSpec({ override fun close() = didClose.set(true) } - "AutoCloseable closes" { + @Test fun autoCloseableCloses() = runTest { val t = AutoCloseableTest() - - autoCloseable { t }.use {} + resourceScope { + autoCloseable { t } + } t.didClose.get() shouldBe true } - "AutoCloseable closes on error" { + @Test fun autoCloseableClosesOnError() = runTest { checkAll(Arb.throwable()) { throwable -> val t = AutoCloseableTest() shouldThrow { - autoCloseable { t }.use { throw throwable } + resourceScope { + autoCloseable { t } + throw throwable + } } shouldBe throwable t.didClose.get() shouldBe true } } - "Closeable closes" { + @Test fun closeableCloses() = runTest { val t = CloseableTest() - closeable { t }.use {} + resourceScope { + closeable { t } + } t.didClose.get() shouldBe true } - "Closeable closes on error" { + @Test fun closeableClosesOnError() = runTest { checkAll(Arb.throwable()) { throwable -> val t = CloseableTest() shouldThrow { - closeable { t }.use { throw throwable } + resourceScope { + closeable { t } + throw throwable + } } shouldBe throwable t.didClose.get() shouldBe true } } - "blow the scope on fatal" { + @Test + fun blowTheScopeOnFatal() = runTest { shouldThrow { resourceScope { install({ }) { _, _ -> fail("Should never come here") } @@ -72,4 +83,4 @@ class ResourceTestJvm : StringSpec({ } }.message shouldBe "BOOM!" } -}) +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/predef-test-jvm.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/predef-test-jvm.kt deleted file mode 100644 index ce40b78cf67..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/arrow/fx/coroutines/predef-test-jvm.kt +++ /dev/null @@ -1,19 +0,0 @@ -package arrow.fx.coroutines - -import arrow.core.continuations.AtomicRef -import java.util.concurrent.ThreadFactory -import kotlin.coroutines.CoroutineContext - -const val singleThreadName: String = "single" - -val single: Resource = singleThreadContext(singleThreadName) - -val threadName: suspend () -> String = - { Thread.currentThread().name } - -class NamedThreadFactory(private val mkName: (Int) -> String) : ThreadFactory { - private val count = AtomicRef(0) - override fun newThread(r: Runnable): Thread = - Thread(r, mkName(count.get())) - .apply { isDaemon = true } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-01.kt deleted file mode 100644 index b5daa8841cf..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-01.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Atomic.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleAtomic01 - -import arrow.fx.coroutines.* - -suspend fun main() { - val count = Atomic(0) - - (0 until 20_000).parTraverse { - count.update(Int::inc) - } - println(count.get()) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-02.kt deleted file mode 100644 index 4c1c9f2cbde..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-02.kt +++ /dev/null @@ -1,24 +0,0 @@ -// This file was automatically generated from Atomic.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleAtomic02 - -import arrow.fx.coroutines.* - -typealias Id = Int -data class Job(val description: String) - -val initialState = (0 until 10).map { i -> Pair(i, Job("Task #$i")) } - -suspend fun main(): Unit { - val jobs = Atomic(initialState) - - val batch = jobs.modify { j -> - val batch = j.take(5) - Pair(j.drop(5), batch) - } - - batch.forEach { (id, job) -> - println("Going to work on $job with id $id\n") - } - - println("Remaining: ${jobs.get()}") -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-03.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-03.kt deleted file mode 100644 index 4431588c459..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-03.kt +++ /dev/null @@ -1,28 +0,0 @@ -// This file was automatically generated from Atomic.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleAtomic03 - -import arrow.fx.coroutines.* - -data class Preference(val isEnabled: Boolean) -data class User(val name: String, val age: Int, val preference: Preference) -data class ViewState(val user: User) - -suspend fun main(): Unit { - //sampleStart - val state: Atomic = Atomic(ViewState(User("Simon", 27, Preference(false)))) - val isEnabled: Atomic = - state.lens( - { it.user.preference.isEnabled }, - { state, isEnabled -> - state.copy( - user = - state.user.copy( - preference = - state.user.preference.copy(isEnabled = isEnabled) - ) - ) - } - ) - isEnabled.set(true) - println(state.get()) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-04.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-04.kt deleted file mode 100644 index ea357dcf2df..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-atomic-04.kt +++ /dev/null @@ -1,12 +0,0 @@ -// This file was automatically generated from Atomic.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleAtomic04 - -import arrow.fx.coroutines.* - -suspend fun main() { - val count = Atomic(0) - (0 until 20_000).parTraverse { - count.update(Int::inc) - } - println(count.get()) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-01.kt index ecec44ced00..5ccc4eeb503 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-01.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-01.kt @@ -3,10 +3,10 @@ package arrow.fx.coroutines.examples.exampleBracket01 import arrow.fx.coroutines.* -class File(url: String) { +class File(val url: String) { fun open(): File = this fun close(): Unit {} - override fun toString(): String = "This file contains some interesting content!" + override fun toString(): String = "This file contains some interesting content from $url!" } suspend fun openFile(uri: String): File = File(uri).open() diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-02.kt index dfa4131c13e..d16d7ca953d 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-02.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-bracket-02.kt @@ -3,13 +3,13 @@ package arrow.fx.coroutines.examples.exampleBracket02 import arrow.fx.coroutines.* -class File(url: String) { +class File(val url: String) { fun open(): File = this fun close(): Unit {} } suspend fun File.content(): String = - "This file contains some interesting content!" + "This file contains some interesting content from $url!" suspend fun openFile(uri: String): File = File(uri).open() suspend fun closeFile(file: File): Unit = file.close() diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt deleted file mode 100644 index 2fa0b9e43b3..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt +++ /dev/null @@ -1,30 +0,0 @@ -// This file was automatically generated from CircuitBreaker.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleCircuitbreaker01 - -import arrow.core.Either -import arrow.fx.coroutines.CircuitBreaker -import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -import kotlinx.coroutines.delay - -@ExperimentalTime -suspend fun main(): Unit { - val circuitBreaker = CircuitBreaker.of( - maxFailures = 2, - resetTimeout = 2.seconds, - exponentialBackoffFactor = 1.2, - maxResetTimeout = 60.seconds, - ) - circuitBreaker.protectOrThrow { "I am in Closed: ${circuitBreaker.state()}" }.also(::println) - - println("Service getting overloaded . . .") - - Either.catch { circuitBreaker.protectOrThrow { throw RuntimeException("Service overloaded") } }.also(::println) - Either.catch { circuitBreaker.protectOrThrow { throw RuntimeException("Service overloaded") } }.also(::println) - circuitBreaker.protectEither { }.also { println("I am Open and short-circuit with ${it}. ${circuitBreaker.state()}") } - - println("Service recovering . . .").also { delay(2000) } - - circuitBreaker.protectOrThrow { "I am running test-request in HalfOpen: ${circuitBreaker.state()}" }.also(::println) - println("I am back to normal state closed ${circuitBreaker.state()}") -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt deleted file mode 100644 index 360172174c1..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt +++ /dev/null @@ -1,45 +0,0 @@ -// This file was automatically generated from CircuitBreaker.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleCircuitbreaker02 - -import arrow.core.Either -import arrow.fx.coroutines.CircuitBreaker -import arrow.fx.coroutines.Schedule -import arrow.fx.coroutines.retry -import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -import kotlinx.coroutines.delay - -@ExperimentalTime -suspend fun main(): Unit { - suspend fun apiCall(): Unit { - println("apiCall . . .") - throw RuntimeException("Overloaded service") - } - - //sampleStart - val circuitBreaker = CircuitBreaker.of( - maxFailures = 2, - resetTimeout = 2.seconds, - exponentialBackoffFactor = 2.0, // enable exponentialBackoffFactor - maxResetTimeout = 60.seconds, // limit exponential back-off time - ) - - suspend fun resilient(schedule: Schedule, f: suspend () -> A): A = - schedule.retry { circuitBreaker.protectOrThrow(f) } - - Either.catch { - resilient(Schedule.recurs(5), ::apiCall) - }.let { println("recurs(5) apiCall twice and 4x short-circuit result from CircuitBreaker: $it") } - - delay(2000) - println("CircuitBreaker ready to half-open") - - // Retry once and when the CircuitBreaker opens after 2 failures then retry with exponential back-off with same time as CircuitBreaker's resetTimeout - val fiveTimesWithBackOff = Schedule.recurs(1) andThen - Schedule.exponential(2.seconds) and Schedule.recurs(5) - - Either.catch { - resilient(fiveTimesWithBackOff, ::apiCall) - }.let { println("exponential(2.seconds) and recurs(5) always retries with actual apiCall: $it") } - //sampleEnd -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-01.kt index e79d9e78fe2..9bcd7615eb9 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-01.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-01.kt @@ -1,17 +1,16 @@ // This file was automatically generated from flow.kt by Knit tool. Do not edit. package arrow.fx.coroutines.examples.exampleFlow01 -import kotlinx.coroutines.flow.* -import arrow.fx.coroutines.* +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.flow.collect +import arrow.fx.coroutines.parMap + suspend fun main(): Unit { - var counter = 0 - val flow = flow { - emit(counter) - if (++counter <= 5) throw RuntimeException("Bang!") - } - //sampleStart - val sum = flow.retry(Schedule.recurs(5)) - .reduce(Int::plus) - //sampleEnd - println(sum) + flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .parMap { a -> + delay(100) + a + }.toList() // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-02.kt index 5e3e0d32562..8f814f47bb1 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-02.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-02.kt @@ -1,16 +1,3 @@ // This file was automatically generated from flow.kt by Knit tool. Do not edit. package arrow.fx.coroutines.examples.exampleFlow02 -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.flowOf -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.flow.collect -import arrow.fx.coroutines.parMap - -suspend fun main(): Unit { - flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - .parMap { a -> - delay(100) - a - }.toList() // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-03.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-03.kt index ebed539d114..0f9ef5e5074 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-03.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-03.kt @@ -1,3 +1,16 @@ // This file was automatically generated from flow.kt by Knit tool. Do not edit. package arrow.fx.coroutines.examples.exampleFlow03 +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.toList +import kotlinx.coroutines.flow.collect +import arrow.fx.coroutines.parMapUnordered + +suspend fun main(): Unit { + flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + .parMapUnordered { a -> + delay(100) + a + }.toList() // [3, 5, 4, 6, 2, 8, 7, 1, 9, 10] +} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-04.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-04.kt index 683028839ba..8968edc20ad 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-04.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-flow-04.kt @@ -5,12 +5,12 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.toList import kotlinx.coroutines.flow.collect -import arrow.fx.coroutines.parMapUnordered +import arrow.fx.coroutines.parMapNotNullUnordered suspend fun main(): Unit { flowOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - .parMapUnordered { a -> + .parMapNotNullUnordered { a -> delay(100) - a - }.toList() // [3, 5, 4, 6, 2, 8, 7, 1, 9, 10] + a.takeIf { a % 2 == 0 } + }.toList() // [4, 6, 2, 8, 10] } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-01.kt deleted file mode 100644 index 8b827d4347f..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-01.kt +++ /dev/null @@ -1,18 +0,0 @@ -// This file was automatically generated from ParTraverse.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverse01 - -import arrow.fx.coroutines.* - -typealias Task = suspend () -> Unit - -suspend fun main(): Unit { - //sampleStart - fun getTask(id: Int): Task = - suspend { println("Working on task $id on ${Thread.currentThread().name}") } - - val res = listOf(1, 2, 3) - .map(::getTask) - .parSequence() - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-02.kt deleted file mode 100644 index dd18f44f71d..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-02.kt +++ /dev/null @@ -1,19 +0,0 @@ -// This file was automatically generated from ParTraverse.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverse02 - -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -typealias Task = suspend () -> Unit - -suspend fun main(): Unit { - //sampleStart - fun getTask(id: Int): Task = - suspend { println("Working on task $id on ${Thread.currentThread().name}") } - - val res = listOf(1, 2, 3) - .map(::getTask) - .parSequence(Dispatchers.IO) - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-03.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-03.kt deleted file mode 100644 index f6b891139bb..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-03.kt +++ /dev/null @@ -1,17 +0,0 @@ -// This file was automatically generated from ParTraverse.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverse03 - -import arrow.fx.coroutines.* - -data class User(val id: Int, val createdOn: String) - -suspend fun main(): Unit { - //sampleStart - suspend fun getUserById(id: Int): User = - User(id, Thread.currentThread().name) - - val res = listOf(1, 2, 3) - .parTraverse { getUserById(it) } - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-04.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-04.kt deleted file mode 100644 index adc3916bd35..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverse-04.kt +++ /dev/null @@ -1,18 +0,0 @@ -// This file was automatically generated from ParTraverse.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverse04 - -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -data class User(val id: Int, val createdOn: String) - -suspend fun main(): Unit { - //sampleStart - suspend fun getUserById(id: Int): User = - User(id, Thread.currentThread().name) - - val res = listOf(1, 2, 3) - .parTraverse(Dispatchers.IO) { getUserById(it) } - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-01.kt deleted file mode 100644 index 4c86a5c3f9d..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-01.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from ParTraverseEither.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverseeither01 - -import arrow.core.* -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -object Error -typealias Task = suspend () -> Either - -suspend fun main(): Unit { - //sampleStart - fun getTask(id: Int): Task = - suspend { Either.catch { println("Working on task $id on ${Thread.currentThread().name}") } } - - val res = listOf(1, 2, 3) - .map(::getTask) - .parSequenceEither(Dispatchers.IO) - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-02.kt deleted file mode 100644 index 0521cbd61bf..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraverseeither-02.kt +++ /dev/null @@ -1,25 +0,0 @@ -// This file was automatically generated from ParTraverseEither.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraverseeither02 - -import arrow.core.* -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -object Error -data class User(val id: Int, val createdOn: String) - -suspend fun main(): Unit { - //sampleStart - suspend fun getUserById(id: Int): Either = - if(id == 4) Error.left() - else User(id, Thread.currentThread().name).right() - - val res = listOf(1, 2, 3) - .parTraverseEither(Dispatchers.IO) { getUserById(it) } - - val res2 = listOf(1, 4, 2, 3) - .parTraverseEither(Dispatchers.IO) { getUserById(it) } - //sampleEnd - println(res) - println(res2) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-01.kt deleted file mode 100644 index dba6a9a37b4..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-01.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from ParTraverseValidated.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraversevalidated01 - -import arrow.core.* -import arrow.typeclasses.Semigroup -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -typealias Task = suspend () -> ValidatedNel - -suspend fun main(): Unit { - //sampleStart - fun getTask(id: Int): Task = - suspend { Validated.catchNel { println("Working on task $id on ${Thread.currentThread().name}") } } - - val res = listOf(1, 2, 3) - .map(::getTask) - .parSequenceValidated(Dispatchers.IO, Semigroup.nonEmptyList()) - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-02.kt deleted file mode 100644 index 50ec6bb74c4..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-partraversevalidated-02.kt +++ /dev/null @@ -1,26 +0,0 @@ -// This file was automatically generated from ParTraverseValidated.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.examplePartraversevalidated02 - -import arrow.core.* -import arrow.typeclasses.Semigroup -import arrow.fx.coroutines.* -import kotlinx.coroutines.Dispatchers - -object Error -data class User(val id: Int, val createdOn: String) - -suspend fun main(): Unit { - //sampleStart - suspend fun getUserById(id: Int): ValidatedNel = - if(id % 2 == 0) Error.invalidNel() - else User(id, Thread.currentThread().name).validNel() - - val res = listOf(1, 3, 5) - .parTraverseValidated(Dispatchers.IO, Semigroup.nonEmptyList()) { getUserById(it) } - - val res2 = listOf(1, 2, 3, 4, 5) - .parTraverseValidated(Dispatchers.IO, Semigroup.nonEmptyList()) { getUserById(it) } - //sampleEnd - println(res) - println(res2) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-01.kt index 82a8a5cc8b0..3715cc0cf35 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-01.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-01.kt @@ -3,11 +3,11 @@ package arrow.fx.coroutines.examples.exampleRace201 import arrow.core.Either import arrow.fx.coroutines.* -import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.awaitCancellation suspend fun main(): Unit { suspend fun loser(): Int = - guaranteeCase({ never() }) { exitCase -> + guaranteeCase({ awaitCancellation() }) { exitCase -> println("I can never win the race. Finished with $exitCase.") } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-02.kt index 4f7c2d89b94..56d84882932 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-02.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-race2-02.kt @@ -4,11 +4,11 @@ package arrow.fx.coroutines.examples.exampleRace202 import arrow.core.Either import arrow.fx.coroutines.* import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.awaitCancellation suspend fun main(): Unit { suspend fun loser(): Int = - guaranteeCase({ never() }) { exitCase -> + guaranteeCase({ awaitCancellation() }) { exitCase -> println("I can never win the race. Finished with $exitCase.") } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-04.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-04.kt index 8e192f4705d..aab22cf814e 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-04.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-04.kt @@ -30,3 +30,5 @@ val userProcessor: Resource = resource { val userProcessor2: Resource = resource({ UserProcessor().also { it.start() } }) { processor, _ -> processor.shutdown() } + +val userProcessor3: Resource = ResourceScope::userProcessor diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-06.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-06.kt index 68cae307ffe..9a1bd665e14 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-06.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-06.kt @@ -1,20 +1,20 @@ // This file was automatically generated from Resource.kt by Knit tool. Do not edit. package arrow.fx.coroutines.examples.exampleResource06 -import arrow.fx.coroutines.* +import arrow.fx.coroutines.resourceScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext class DataSource { - fun connect(): Unit = println("Connecting dataSource") - fun users(): List = listOf("User-1", "User-2", "User-3") - fun close(): Unit = println("Closed dataSource") + suspend fun connect(): Unit = withContext(Dispatchers.IO) { println("Connecting dataSource") } + suspend fun close(): Unit = withContext(Dispatchers.IO) { println("Closed dataSource") } + suspend fun users(): List = listOf("User-1", "User-2", "User-3") } -suspend fun main(): Unit { - val dataSource = resource { +suspend fun main(): Unit = resourceScope { + val dataSource = install({ DataSource().also { it.connect() } - } release DataSource::close + }) { ds, _ -> ds.close() } - val res = dataSource - .use { ds -> "Using data source: ${ds.users()}" } - .also(::println) + println("Using data source: ${dataSource.users()}") } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-07.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-07.kt index e272f9a54f5..161326cdab0 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-07.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-07.kt @@ -1,30 +1,16 @@ // This file was automatically generated from Resource.kt by Knit tool. Do not edit. package arrow.fx.coroutines.examples.exampleResource07 -import arrow.fx.coroutines.* +import arrow.fx.coroutines.resource +import arrow.fx.coroutines.resourceScope -object Connection -class DataSource { - fun connect(): Unit = println("Connecting dataSource") - fun connection(): Connection = Connection - fun close(): Unit = println("Closed dataSource") +val resource = resource { + install({ 42.also { println("Getting expensive resource") } }) { r, exitCase -> + println("Releasing expensive resource: $r, exit: $exitCase") + } } -class Database(private val database: DataSource) { - fun init(): Unit = println("Database initialising . . .") - fun shutdown(): Unit = println("Database shutting down . . .") -} - -suspend fun main(): Unit { - val dataSource = resource { - DataSource().also { it.connect() } - } release DataSource::close - - fun database(ds: DataSource): Resource = - resource { - Database(ds).also(Database::init) - } release Database::shutdown - - dataSource.flatMap(::database) - .use { println("Using database which uses dataSource") } +suspend fun main(): Unit = resourceScope { + val res = resource.bind() + println("Expensive resource under use! $res") } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-08.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-08.kt index fb14ed2cc30..75766ca0c09 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-08.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-08.kt @@ -2,34 +2,23 @@ package arrow.fx.coroutines.examples.exampleResource08 import arrow.fx.coroutines.* +import kotlinx.coroutines.* +import kotlinx.coroutines.flow.* +import java.nio.file.Path +import kotlin.io.path.* -class UserProcessor { - fun start(): Unit = println("Creating UserProcessor") - fun shutdown(): Unit = println("Shutting down UserProcessor") - fun process(ds: DataSource): List = - ds.users().map { "Processed $it" } -} - -class DataSource { - fun connect(): Unit = println("Connecting dataSource") - fun users(): List = listOf("User-1", "User-2", "User-3") - fun close(): Unit = println("Closed dataSource") -} +fun Flow.writeAll(path: Path): Flow = + closeable { path.toFile().outputStream() } + .asFlow() + .flatMapConcat { writer -> map { writer.write(it) } } + .flowOn(Dispatchers.IO) -class Service(val db: DataSource, val userProcessor: UserProcessor) { - suspend fun processData(): List = userProcessor.process(db) +fun Path.readAll(): Flow = flow { + useLines { lines -> emitAll(lines.asFlow()) } } -val userProcessor = resource { - UserProcessor().also(UserProcessor::start) -} release UserProcessor::shutdown - -val dataSource = resource { - DataSource().also { it.connect() } -} release DataSource::close - -suspend fun main(): Unit { - userProcessor.zip(dataSource) { userProcessor, ds -> - Service(ds, userProcessor) - }.use { service -> service.processData() } +suspend fun main() { + Path("example.kt") + .readAll() + .collect(::println) } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-09.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-09.kt index 6921b8e93cf..c2642bb90dd 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-09.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-09.kt @@ -2,35 +2,17 @@ package arrow.fx.coroutines.examples.exampleResource09 import arrow.fx.coroutines.* -import kotlinx.coroutines.delay +import arrow.fx.coroutines.ExitCase.Companion.ExitCase -class UserProcessor { - suspend fun start(): Unit { delay(750); println("Creating UserProcessor") } - fun shutdown(): Unit = println("Shutting down UserProcessor") - fun process(ds: DataSource): List = - ds.users().map { "Processed $it" } -} - -class DataSource { - suspend fun connect(): Unit { delay(1000); println("Connecting dataSource") } - fun users(): List = listOf("User-1", "User-2", "User-3") - fun close(): Unit = println("Closed dataSource") -} - -class Service(val db: DataSource, val userProcessor: UserProcessor) { - suspend fun processData(): List = userProcessor.process(db) -} - -val userProcessor = resource { - UserProcessor().also { it.start() } -} release UserProcessor::shutdown - -val dataSource = resource { - DataSource().also { it.connect() } -} release DataSource::close +val resource = + resource({ "Acquire" }) { _, exitCase -> println("Release $exitCase") } suspend fun main(): Unit { - userProcessor.parZip(dataSource) { userProcessor, ds -> - Service(ds, userProcessor) - }.use { service -> service.processData() } + val (acquired: String, release: suspend (ExitCase) -> Unit) = resource.allocated() + try { + /** Do something with A */ + release(ExitCase.Completed) + } catch(e: Throwable) { + release(ExitCase(e)) + } } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-10.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-10.kt deleted file mode 100644 index ffba3327d3d..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-10.kt +++ /dev/null @@ -1,18 +0,0 @@ -// This file was automatically generated from Resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResource10 - -import arrow.fx.coroutines.* -import arrow.fx.coroutines.ExitCase.Companion.ExitCase - -val resource = - resource({ "Acquire" }) { _, exitCase -> println("Release $exitCase") } - -suspend fun main(): Unit { - val (acquired: String, release: suspend (ExitCase) -> Unit) = resource.allocate() - try { - /** Do something with A */ - release(ExitCase.Completed) - } catch(e: Throwable) { - release(ExitCase(e)) - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-11.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-11.kt deleted file mode 100644 index b4370b2eedb..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-11.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResource11 - -import arrow.fx.coroutines.* - -suspend fun acquireResource(): Int = 42.also { println("Getting expensive resource") } -suspend fun releaseResource(r: Int, exitCase: ExitCase): Unit = println("Releasing expensive resource: $r, exit: $exitCase") - -suspend fun main(): Unit { - val resource = Resource(::acquireResource, ::releaseResource) - resource.use { - println("Expensive resource under use! $it") - } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-12.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-12.kt deleted file mode 100644 index 015eeff8196..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-12.kt +++ /dev/null @@ -1,26 +0,0 @@ -// This file was automatically generated from Resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResource12 - -import arrow.fx.coroutines.* - -class File(url: String) { - suspend fun open(): File = this - suspend fun close(): Unit {} - override fun toString(): String = "This file contains some interesting content!" -} - -suspend fun openFile(uri: String): File = File(uri).open() -suspend fun closeFile(file: File): Unit = file.close() -suspend fun fileToString(file: File): String = file.toString() - -suspend fun main(): Unit { - val res = resource { - openFile("data.json") - } release { file -> - closeFile(file) - } use { file -> - fileToString(file) - } - - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-13.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-13.kt deleted file mode 100644 index baa04722d84..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-13.kt +++ /dev/null @@ -1,31 +0,0 @@ -// This file was automatically generated from Resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResource13 - -import arrow.fx.coroutines.* - -class File(url: String) { - suspend fun open(): File = this - suspend fun close(): Unit {} - override fun toString(): String = "This file contains some interesting content!" -} - -suspend fun openFile(uri: String): File = File(uri).open() -suspend fun closeFile(file: File): Unit = file.close() -suspend fun fileToString(file: File): String = file.toString() - -suspend fun main(): Unit { - val res: List = listOf( - "data.json", - "user.json", - "resource.json" - ).traverse { uri -> - resource { - openFile(uri) - } release { file -> - closeFile(file) - } - }.use { files -> - files.map { fileToString(it) } - } - res.forEach(::println) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-14.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-14.kt deleted file mode 100644 index 582729f63ce..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-14.kt +++ /dev/null @@ -1,31 +0,0 @@ -// This file was automatically generated from Resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResource14 - -import arrow.fx.coroutines.* - -class File(url: String) { - suspend fun open(): File = this - suspend fun close(): Unit {} - override fun toString(): String = "This file contains some interesting content!" -} - -suspend fun openFile(uri: String): File = File(uri).open() -suspend fun closeFile(file: File): Unit = file.close() -suspend fun fileToString(file: File): String = file.toString() - -suspend fun main(): Unit { - val res: List = listOf( - "data.json", - "user.json", - "resource.json" - ).map { uri -> - resource { - openFile(uri) - } release { file -> - closeFile(file) - } - }.sequence().use { files -> - files.map { fileToString(it) } - } - res.forEach(::println) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-computations-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-computations-01.kt deleted file mode 100644 index 918baf6a9e3..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resource-computations-01.kt +++ /dev/null @@ -1,36 +0,0 @@ -// This file was automatically generated from resource.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleResourceComputations01 - -import arrow.fx.coroutines.continuations.resource -import arrow.fx.coroutines.release - -class UserProcessor { - fun start(): Unit = println("Creating UserProcessor") - fun shutdown(): Unit = println("Shutting down UserProcessor") - fun process(ds: DataSource): List = - ds.users().map { "Processed $it" } -} - -class DataSource { - fun connect(): Unit = println("Connecting dataSource") - fun users(): List = listOf("User-1", "User-2", "User-3") - fun close(): Unit = println("Closed dataSource") -} - -class Service(val db: DataSource, val userProcessor: UserProcessor) { - suspend fun processData(): List = userProcessor.process(db) -} - -val userProcessor = resource { - UserProcessor().also(UserProcessor::start) -} release UserProcessor::shutdown - -val dataSource = resource { - DataSource().also { it.connect() } -} release DataSource::close - -suspend fun main(): Unit { - resource { - Service(dataSource.bind(), userProcessor.bind()) - }.use { service -> service.processData() } -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resourceextensions-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resourceextensions-01.kt index 52ec46e1af5..ccbf303048e 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resourceextensions-01.kt +++ b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-resourceextensions-01.kt @@ -3,7 +3,7 @@ package arrow.fx.coroutines.examples.exampleResourceextensions01 import arrow.fx.coroutines.executor import arrow.fx.coroutines.resourceScope -import arrow.fx.coroutines.parTraverse +import arrow.fx.coroutines.parMap import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicInteger import kotlin.math.max @@ -19,7 +19,7 @@ suspend fun main(): Unit { } } - listOf(1, 2, 3, 4, 5).parTraverse(pool) { i -> + listOf(1, 2, 3, 4, 5).parMap(pool) { i -> println("#$i running on ${Thread.currentThread().name}") } } diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-01.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-01.kt deleted file mode 100644 index ba101e31302..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-01.kt +++ /dev/null @@ -1,6 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule01 - -import arrow.fx.coroutines.* - -fun recurTenTimes() = Schedule.recurs(10) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-02.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-02.kt deleted file mode 100644 index 59702329185..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-02.kt +++ /dev/null @@ -1,13 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule02 - -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -import arrow.fx.coroutines.* - -@ExperimentalTime -fun complexPolicy(): Schedule> = - Schedule.exponential(10.milliseconds).whileOutput { it < 60.seconds } - .andThen(Schedule.spaced(60.seconds) and Schedule.recurs(100)).jittered() - .zipRight(Schedule.identity().collect()) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-03.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-03.kt deleted file mode 100644 index 40d8293b7b0..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-03.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule03 - -import arrow.fx.coroutines.* - -suspend fun main(): Unit { - var counter = 0 - //sampleStart - val res = Schedule.recurs(3).repeat { - println("Run: ${counter++}") - } - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-04.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-04.kt deleted file mode 100644 index 706ed2a33b0..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-04.kt +++ /dev/null @@ -1,19 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule04 - -import arrow.fx.coroutines.* - -suspend fun main(): Unit { - var counter = 0 - //sampleStart - val res = (Schedule.unit() zipLeft Schedule.recurs(3)).repeat { - println("Run: ${counter++}") - } - // equal to - val res2 = (Schedule.recurs(3) zipRight Schedule.unit()).repeat { - println("Run: ${counter++}") - } - //sampleEnd - println(res) - println(res2) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-05.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-05.kt deleted file mode 100644 index 72babd0e323..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-05.kt +++ /dev/null @@ -1,19 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule05 - -import arrow.fx.coroutines.* - -suspend fun main(): Unit { - var counter = 0 - //sampleStart - val res = (Schedule.identity() zipLeft Schedule.recurs(3)).repeat { - println("Run: ${counter++}"); counter - } - // equal to - val res2 = (Schedule.recurs(3) zipRight Schedule.identity()).repeat { - println("Run: ${counter++}"); counter - } - //sampleEnd - println(res) - println(res2) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-06.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-06.kt deleted file mode 100644 index 395f5c98ca6..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-06.kt +++ /dev/null @@ -1,21 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule06 - -import arrow.fx.coroutines.* - -suspend fun main(): Unit { - var counter = 0 - //sampleStart - val res = (Schedule.collect() zipLeft Schedule.recurs(3)).repeat { - println("Run: ${counter++}") - counter - } - // equal to - val res2 = (Schedule.recurs(3) zipRight Schedule.collect()).repeat { - println("Run: ${counter++}") - counter - } - //sampleEnd - println(res) - println(res2) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-07.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-07.kt deleted file mode 100644 index 446ad2e940b..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-07.kt +++ /dev/null @@ -1,14 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule07 - -import arrow.fx.coroutines.* - -suspend fun main(): Unit { - var counter = 0 - //sampleStart - val res = Schedule.doWhile{ it <= 3 }.repeat { - println("Run: ${counter++}"); counter - } - //sampleEnd - println(res) -} diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-08.kt b/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-08.kt deleted file mode 100644 index c333ee73f87..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/jvmTest/kotlin/examples/example-schedule-08.kt +++ /dev/null @@ -1,9 +0,0 @@ -// This file was automatically generated from Schedule.kt by Knit tool. Do not edit. -package arrow.fx.coroutines.examples.exampleSchedule08 - -import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.ExperimentalTime -import arrow.fx.coroutines.* - -@ExperimentalTime -val exponential = Schedule.exponential(250.milliseconds) diff --git a/arrow-libs/fx/arrow-fx-coroutines/src/nativeMain/kotlin/arrow/fx/coroutines/predef.kt b/arrow-libs/fx/arrow-fx-coroutines/src/nativeMain/kotlin/arrow/fx/coroutines/predef.kt deleted file mode 100644 index 96685114130..00000000000 --- a/arrow-libs/fx/arrow-fx-coroutines/src/nativeMain/kotlin/arrow/fx/coroutines/predef.kt +++ /dev/null @@ -1,6 +0,0 @@ -package arrow.fx.coroutines - -import kotlin.system.getTimeMillis - -public actual fun timeInMillis(): Long = - getTimeMillis() diff --git a/arrow-libs/fx/arrow-fx-stm/build.gradle.kts b/arrow-libs/fx/arrow-fx-stm/build.gradle.kts index 0ebdae769aa..a44b7d98dbf 100644 --- a/arrow-libs/fx/arrow-fx-stm/build.gradle.kts +++ b/arrow-libs/fx/arrow-fx-stm/build.gradle.kts @@ -1,11 +1,13 @@ @file:Suppress("DSL_SCOPE_VIOLATION") +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + + plugins { id(libs.plugins.kotlin.multiplatform.get().pluginId) alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.spotless) } @@ -22,7 +24,6 @@ kotlin { commonMain { dependencies { api(projects.arrowCore) - compileOnly(libs.kotlin.stdlib) implementation(libs.coroutines.core) } } @@ -30,16 +31,12 @@ kotlin { commonTest { dependencies { implementation(projects.arrowFxCoroutines) - implementation(libs.kotest.frameworkEngine) + implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } } - jvmTest { - dependencies { - runtimeOnly(libs.kotest.runnerJUnit5) - } - } } jvm { @@ -50,3 +47,11 @@ kotlin { } } } + +tasks.withType().configureEach { + kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes" +} + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt index 9854ff8f9d1..5e4439a0509 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/STM.kt @@ -250,7 +250,7 @@ public interface STM { * suspend fun main() { * //sampleStart * val result = atomically { - * catch({ throw Throwable() }) { e -> "caught" } + * catch({ throw Throwable() }) { _ -> "caught" } * } * //sampleEnd * println("Result $result") @@ -1202,6 +1202,7 @@ public interface STM { * tarr.transform { it + 1 } * } * //sampleEnd + * println("Result $result") * } * ``` * @@ -1538,6 +1539,7 @@ public interface STM { * * Equal to [suspend] just with an [STM] receiver. */ +@Suppress("NOTHING_TO_INLINE") public inline fun stm(noinline f: STM.() -> A): STM.() -> A = f /** diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TArray.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TArray.kt index 0aa446ecd67..5cb8024f3bc 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TArray.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TArray.kt @@ -86,6 +86,7 @@ public fun STM.newTArray(xs: Iterable): TArray = * tarr.transform { it + 1 } * } * //sampleEnd + * println("Result $result") * } * ``` * diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TVar.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TVar.kt index b73791874a9..195c6b9f99e 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TVar.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/TVar.kt @@ -1,7 +1,8 @@ package arrow.fx.stm -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.update +import arrow.atomic.Atomic +import arrow.atomic.update +import arrow.atomic.value import arrow.fx.stm.internal.STMFrame import arrow.fx.stm.internal.STMTransaction import kotlin.coroutines.resume @@ -128,10 +129,10 @@ public class TVar internal constructor(a: A) { * This is used to implement locking. Reading threads have to loop until the value is released by a * transaction. */ - private val ref = AtomicRef(a as Any?) + private val ref = Atomic(a as Any?) internal val value - get() = ref.get() + get() = ref.value /** * Each TVar has a unique id which is used to get a total ordering of variables to ensure that locks @@ -147,7 +148,7 @@ public class TVar internal constructor(a: A) { * Changes are pushed to waiting transactions via [notify] */ // TODO Use a set here, and preferably something that uses sharing to avoid gc pressure from copying... - private val waiting = AtomicRef>>(emptyList()) + private val waiting = Atomic>>(emptyList()) override fun hashCode(): Int = id.hashCode() @@ -165,9 +166,10 @@ public class TVar internal constructor(a: A) { * Internal unsafe (non-suspend) version of read. Used by various other internals and [unsafeRead] to * read the current value respecting its state. */ + @Suppress("UNCHECKED_CAST") internal fun readI(): A { while (true) { - ref.get().let { a -> + ref.value.let { a -> if (a !is STMFrame) return@readI a as A } } diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt index d18312eaf09..ae77a42acd3 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Hamt.kt @@ -1,3 +1,5 @@ +@file:Suppress("UNCHECKED_CAST") + package arrow.fx.stm.internal import arrow.fx.stm.TVar diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt index 07e7e3aa063..c2d624ac7a3 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonMain/kotlin/arrow/fx/stm/internal/Impl.kt @@ -1,6 +1,9 @@ +@file:Suppress("UNCHECKED_CAST") + package arrow.fx.stm.internal -import arrow.core.continuations.AtomicRef +import arrow.atomic.Atomic +import arrow.atomic.value import arrow.fx.stm.STM import arrow.fx.stm.TVar import kotlinx.coroutines.suspendCancellableCoroutine @@ -13,14 +16,14 @@ import kotlin.coroutines.Continuation internal class STMFrame(private val parent: STMFrame? = null) : STM { class Entry(var initialVal: Any?, var newVal: Any?) { - object NO_CHANGE - object NOT_PRESENT + object NoChange + object NotPresent fun isWrite(): Boolean = - newVal !== NO_CHANGE + newVal !== NoChange fun update(v: Any?) { - newVal = if (initialVal === v) NO_CHANGE else v + newVal = if (initialVal === v) NoChange else v } fun getValue(): Any? = if (isWrite()) newVal else initialVal @@ -32,7 +35,7 @@ internal class STMFrame(private val parent: STMFrame? = null) : STM { * Helper to search the entire hierarchy for stored previous reads */ private fun readVar(v: TVar): Any = - accessMap[v]?.getValue() ?: parent?.readVar(v) ?: Entry.NOT_PRESENT + accessMap[v]?.getValue() ?: parent?.readVar(v) ?: Entry.NotPresent override fun retry(): Nothing = throw RetryException @@ -78,7 +81,7 @@ internal class STMFrame(private val parent: STMFrame? = null) : STM { */ override fun TVar.read(): A = when (val r = readVar(this as TVar)) { - Entry.NOT_PRESENT -> readI().also { accessMap[this] = Entry(it, Entry.NO_CHANGE) } + Entry.NotPresent -> readI().also { accessMap[this] = Entry(it, Entry.NoChange) } else -> r as A } @@ -166,7 +169,7 @@ public expect object RetryException : Throwable * Keeps the continuation that [TVar]'s use to resume this transaction. */ internal class STMTransaction(val f: STM.() -> A) { - private val cont = AtomicRef?>(null) + private val cont = Atomic?>(null) /** * Any one resumptions is enough, because we enqueue on all read variables this might be called multiple times. @@ -186,13 +189,13 @@ internal class STMTransaction(val f: STM.() -> A) { try { val res = frame.f() - if (frame.validateAndCommit()) return@commit res + if (frame.validateAndCommit()) return res } catch (ignored: RetryException) { if (frame.accessMap.isEmpty()) throw BlockedIndefinitely() val registered = mutableListOf>() suspendCancellableCoroutine susp@{ k -> - cont.set(k) + cont.value = k frame.accessMap .forEach { (tv, entry) -> diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/KotestConfig.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/KotestConfig.kt deleted file mode 100644 index ed1e6d93002..00000000000 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/KotestConfig.kt +++ /dev/null @@ -1,10 +0,0 @@ -package arrow.fx.stm - -import io.kotest.core.config.AbstractProjectConfig -import io.kotest.property.PropertyTesting - -class KotestConfig : AbstractProjectConfig() { - override suspend fun beforeProject() { - PropertyTesting.defaultIterationCount = 250 - } -} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/STMTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/STMTest.kt index 540772bb7ea..2623f4dace7 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/STMTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/STMTest.kt @@ -1,10 +1,9 @@ package arrow.fx.stm -import arrow.fx.coroutines.parTraverse +import arrow.fx.coroutines.parMap import arrow.fx.coroutines.parZip import arrow.fx.stm.internal.BlockedIndefinitely import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.ints.shouldBeInRange import io.kotest.matchers.shouldBe @@ -15,257 +14,278 @@ import io.kotest.property.checkAll import kotlinx.coroutines.async import kotlinx.coroutines.delay import kotlinx.coroutines.joinAll +import kotlinx.coroutines.test.runTest import kotlinx.coroutines.withTimeoutOrNull +import kotlin.test.Ignore +import kotlin.test.Test import kotlin.time.Duration.Companion.microseconds import kotlin.time.Duration.Companion.milliseconds import kotlin.time.ExperimentalTime @ExperimentalTime -class STMTest : StringSpec({ - "no-effects" { - atomically { 10 } shouldBeExactly 10 - } - "reading from vars" { - checkAll(Arb.int()) { i: Int -> - val tv = TVar.new(i) - atomically { - tv.read() - } shouldBeExactly i - tv.unsafeRead() shouldBeExactly i - } +class STMTest { + + @Test fun noEffects() = runTest { + atomically { 10 } shouldBeExactly 10 + } + + @Test fun readingFromVars() = runTest { + checkAll(Arb.int()) { i: Int -> + val tv = TVar.new(i) + atomically { + tv.read() + } shouldBeExactly i + tv.unsafeRead() shouldBeExactly i } - "reading and writing" { - checkAll(Arb.int(), Arb.int()) { i: Int, j: Int -> - val tv = TVar.new(i) - atomically { tv.write(j) } - tv.unsafeRead() shouldBeExactly j - } + } + + @Test fun readingAndWriting() = runTest { + checkAll(Arb.int(), Arb.int()) { i: Int, j: Int -> + val tv = TVar.new(i) + atomically { tv.write(j) } + tv.unsafeRead() shouldBeExactly j } - "read after a write should have the updated value" { - checkAll(Arb.int(), Arb.int()) { i: Int, j: Int -> - val tv = TVar.new(i) - atomically { tv.write(j); tv.read() } shouldBeExactly j - tv.unsafeRead() shouldBeExactly j - } + } + + @Test fun readAfterAWriteShouldHaveTheUpdatedValue() = runTest { + checkAll(Arb.int(), Arb.int()) { i: Int, j: Int -> + val tv = TVar.new(i) + atomically { tv.write(j); tv.read() } shouldBeExactly j + tv.unsafeRead() shouldBeExactly j } - "reading multiple variables" { - checkAll(Arb.int(), Arb.int(), Arb.int()) { i: Int, j: Int, k: Int -> - val v1 = TVar.new(i) - val v2 = TVar.new(j) - val v3 = TVar.new(k) - atomically { v1.read() + v2.read() + v3.read() } shouldBeExactly i + j + k - v1.unsafeRead() shouldBeExactly i - v2.unsafeRead() shouldBeExactly j - v3.unsafeRead() shouldBeExactly k - } + } + + @Test fun readingMultipleVariables() = runTest { + checkAll(Arb.int(), Arb.int(), Arb.int()) { i: Int, j: Int, k: Int -> + val v1 = TVar.new(i) + val v2 = TVar.new(j) + val v3 = TVar.new(k) + atomically { v1.read() + v2.read() + v3.read() } shouldBeExactly i + j + k + v1.unsafeRead() shouldBeExactly i + v2.unsafeRead() shouldBeExactly j + v3.unsafeRead() shouldBeExactly k } - "reading and writing multiple variables" { - checkAll(Arb.int(), Arb.int(), Arb.int()) { i: Int, j: Int, k: Int -> - val v1 = TVar.new(i) - val v2 = TVar.new(j) - val v3 = TVar.new(k) - val sum = TVar.new(0) - atomically { - val s = v1.read() + v2.read() + v3.read() - sum.write(s) - } - v1.unsafeRead() shouldBeExactly i - v2.unsafeRead() shouldBeExactly j - v3.unsafeRead() shouldBeExactly k - sum.unsafeRead() shouldBeExactly i + j + k + } + + @Test fun readingAndWritingMultipleVariables() = runTest { + checkAll(Arb.int(), Arb.int(), Arb.int()) { i: Int, j: Int, k: Int -> + val v1 = TVar.new(i) + val v2 = TVar.new(j) + val v3 = TVar.new(k) + val sum = TVar.new(0) + atomically { + val s = v1.read() + v2.read() + v3.read() + sum.write(s) } + v1.unsafeRead() shouldBeExactly i + v2.unsafeRead() shouldBeExactly j + v3.unsafeRead() shouldBeExactly k + sum.unsafeRead() shouldBeExactly i + j + k } - "retry without prior reads throws an exception" { - shouldThrow { atomically { retry() } } - } - "retry should suspend forever if no read variable changes" { - withTimeoutOrNull(500.milliseconds) { - val tv = TVar.new(0) - atomically { - if (tv.read() == 0) retry() - else 200 - } - } shouldBe null - } - "a suspended transaction will resume if a variable changes" { + } + + @Test fun retryWithoutPriorReadsThrowsAnException() = runTest { + shouldThrow { atomically { retry() } } + } + + @Test fun retryShouldSuspendForeverIfNoReadVariableChanges() = runTest { + withTimeoutOrNull(500.milliseconds) { val tv = TVar.new(0) - val f = async { - delay(500.milliseconds) - atomically { tv.modify { it + 1 } } - } atomically { - when (val i = tv.read()) { - 0 -> retry() - else -> i - } - } shouldBeExactly 1 - f.join() - } - "a suspended transaction will resume if any variable changes" { - val v1 = TVar.new(0) - val v2 = TVar.new(0) - val v3 = TVar.new(0) - val f = async { - delay(500.milliseconds) - atomically { v1.modify { it + 1 } } - delay(500.milliseconds) - atomically { v2.modify { it + 1 } } - delay(500.milliseconds) - atomically { v3.modify { it + 1 } } + if (tv.read() == 0) retry() + else 200 } - atomically { - val i = v1.read() + v2.read() + v3.read() - check(i >= 3) - i - } shouldBeExactly 3 - f.join() - } - "retry + orElse: retry orElse t1 = t1" { - atomically { - stm { retry() } orElse { 10 } - } shouldBeExactly 10 + } shouldBe null + } + + @Test fun aSuspendedTransactionWillResumeIfAVariableChanges() = runTest { + val tv = TVar.new(0) + val f = async { + delay(500.milliseconds) + atomically { tv.modify { it + 1 } } } - "retry + orElse: t1 orElse retry = t1" { - atomically { - stm { 10 } orElse { retry() } - } shouldBeExactly 10 + atomically { + when (val i = tv.read()) { + 0 -> retry() + else -> i + } + } shouldBeExactly 1 + f.join() + } + + @Test fun aSuspendedTransactionWillResumeIfAnyVariableChanges() = runTest { + val v1 = TVar.new(0) + val v2 = TVar.new(0) + val v3 = TVar.new(0) + val f = async { + delay(500.milliseconds) + atomically { v1.modify { it + 1 } } + delay(500.milliseconds) + atomically { v2.modify { it + 1 } } + delay(500.milliseconds) + atomically { v3.modify { it + 1 } } } - "retry + orElse: associativity" { - checkAll(Arb.boolean(), Arb.boolean(), Arb.boolean()) { b1: Boolean, b2: Boolean, b3: Boolean -> - if ((b1 || b2 || b3).not()) { - shouldThrow { - atomically { - stm { stm { check(b1) } orElse { check(b2) } } orElse { check(b3) } - } - } shouldBe shouldThrow { - atomically { - stm { check(b1) } orElse { stm { check(b2) } orElse { check(b3) } } - } - } - } else { + atomically { + val i = v1.read() + v2.read() + v3.read() + check(i >= 3) + i + } shouldBeExactly 3 + f.join() + } + + @Test fun retryOrElseRetryOrElseT1T1() = runTest { + atomically { + stm { retry() } orElse { 10 } + } shouldBeExactly 10 + } + + @Test fun retryOrElseT1OrElseRetryT1() = runTest { + atomically { + stm { 10 } orElse { retry() } + } shouldBeExactly 10 + } + + @Test fun retryOrElseAssociativity() = runTest { + checkAll(Arb.boolean(), Arb.boolean(), Arb.boolean()) { b1: Boolean, b2: Boolean, b3: Boolean -> + if ((b1 || b2 || b3).not()) { + shouldThrow { atomically { stm { stm { check(b1) } orElse { check(b2) } } orElse { check(b3) } - } shouldBe atomically { + } + } shouldBe shouldThrow { + atomically { stm { check(b1) } orElse { stm { check(b2) } orElse { check(b3) } } } } + } else { + atomically { + stm { stm { check(b1) } orElse { check(b2) } } orElse { check(b3) } + } shouldBe atomically { + stm { check(b1) } orElse { stm { check(b2) } orElse { check(b3) } } + } } } - "suspended transactions are resumed for variables accessed in orElse" { - val tv = TVar.new(0) - val f = async { - delay(10.microseconds) - atomically { tv.modify { it + 1 } } + } + + @Test fun suspendedTransactionsAreResumedForVariablesAccessedInOrElse() = runTest { + val tv = TVar.new(0) + val f = async { + delay(10.microseconds) + atomically { tv.modify { it + 1 } } + } + atomically { + stm { + when (val i = tv.read()) { + 0 -> retry() + else -> i } + } orElse { retry() } + } shouldBeExactly 1 + f.join() + } + + @Test fun onASingleVariableConcurrentTransactionsShouldBeLinear() = runTest { + val tv = TVar.new(0) + val res = TQueue.new() + + (0..100).map { + async { atomically { - stm { - when (val i = tv.read()) { - 0 -> retry() - else -> i - } - } orElse { retry() } - } shouldBeExactly 1 - f.join() - } - "on a single variable concurrent transactions should be linear" { - val tv = TVar.new(0) - val res = TQueue.new() + val r = tv.read().also { tv.write(it + 1) } + res.write(r) + } + } + }.joinAll() - (0..100).map { - async { - atomically { - val r = tv.read().also { tv.write(it + 1) } - res.write(r) - } - } - }.joinAll() + atomically { res.flush() } shouldBe (0..100).toList() + } - atomically { res.flush() } shouldBe (0..100).toList() - } - "atomically rethrows exceptions" { - shouldThrow { atomically { throw IllegalArgumentException("Test") } } + @Test fun atomicallyRethrowsExceptions() = runTest { + shouldThrow { atomically { throw IllegalArgumentException("Test") } } + } + + @Test fun throwingAnExceptionsShouldVoidAllStateChanges() = runTest { + val tv = TVar.new(10) + shouldThrow { + atomically { tv.write(30); throw IllegalArgumentException("test") } } - "throwing an exceptions should void all state changes" { - val tv = TVar.new(10) - shouldThrow { - atomically { tv.write(30); throw IllegalArgumentException("test") } + tv.unsafeRead() shouldBeExactly 10 + } + + @Test fun catchShouldWorkAsExcepted() = runTest { + val tv = TVar.new(10) + val ex = IllegalArgumentException("test") + atomically { + catch({ + tv.write(30) + throw ex + }) { e -> + e shouldBe ex } - tv.unsafeRead() shouldBeExactly 10 } - "catch should work as excepted" { - val tv = TVar.new(10) - val ex = IllegalArgumentException("test") - atomically { - catch({ - tv.write(30) - throw ex - }) { e -> - e shouldBe ex + tv.unsafeRead() shouldBeExactly 10 + } + + @Test fun concurrentExample1() = runTest { + val acc1 = TVar.new(100) + val acc2 = TVar.new(200) + parZip( + { + // transfer acc1 to acc2 + val amount = 50 + atomically { + val acc1Balance = acc1.read() + check(acc1Balance - amount >= 0) + acc1.write(acc1Balance - amount) + acc2.modify { it + 50 } } - } - tv.unsafeRead() shouldBeExactly 10 - } - "concurrent example 1" { - val acc1 = TVar.new(100) - val acc2 = TVar.new(200) - parZip( - { - // transfer acc1 to acc2 - val amount = 50 - atomically { - val acc1Balance = acc1.read() - check(acc1Balance - amount >= 0) - acc1.write(acc1Balance - amount) - acc2.modify { it + 50 } - } - }, - { - atomically { acc1.modify { it - 60 } } - delay(20.milliseconds) - atomically { acc1.modify { it + 60 } } - }, - { _, _ -> Unit } - ) - acc1.unsafeRead() shouldBeExactly 50 - acc2.unsafeRead() shouldBeExactly 250 - } + }, + { + atomically { acc1.modify { it - 60 } } + delay(20.milliseconds) + atomically { acc1.modify { it + 60 } } + }, + { _, _ -> Unit } + ) + acc1.unsafeRead() shouldBeExactly 50 + acc2.unsafeRead() shouldBeExactly 250 + } - // TypeError: Cannot read property 'toString' of undefined - // at ObjectLiteral_0.test(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:3661) - // at .invokeMatcher(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:19216) - // at .should(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:19212) - // at .shouldBeInRange(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:3652) - // at STMTransaction.f(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:261217) - // at commit.doResume(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:270552) - // at commit.CoroutineImpl.resumeWith(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:118697) - // at CancellableContinuationImpl.DispatchedTask.run(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:174593) - // at WindowMessageQueue.MessageQueue.process(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:177985) - // at .(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:177940) - "concurrent example 2".config(enabled = false) { - val tq = TQueue.new() - parZip( - { - // producers - (0..4).parTraverse { - for (i in (it * 20 + 1)..(it * 20 + 20)) { - atomically { tq.write(i) } - } - } - }, - { - val collected = mutableSetOf() - for (i in 1..100) { - // consumer - atomically { - tq.read().also { it shouldBeInRange (1..100) } - }.also { collected.add(it) } - } - // verify that we got 100 unique numbers - collected.size shouldBeExactly 100 + // TypeError: Cannot read property 'toString' of undefined + // at ObjectLiteral_0.test(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:3661) + // at .invokeMatcher(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:19216) + // at .should(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:19212) + // at .shouldBeInRange(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:3652) + // at STMTransaction.f(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:261217) + // at commit.doResume(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:270552) + // at commit.CoroutineImpl.resumeWith(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:118697) + // at CancellableContinuationImpl.DispatchedTask.run(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:174593) + // at WindowMessageQueue.MessageQueue.process(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:177985) + // at .(/var/folders/x5/6r18d9w52c7czy6zh5m1spvw0000gn/T/_karma_webpack_624630/commons.js:177940) + @Test @Ignore fun concurrentExample2ConfigEnabledFalse() = runTest { + val tq = TQueue.new() + parZip( + { + // producers + (0..4).parMap { + for (i in (it * 20 + 1)..(it * 20 + 20)) { + atomically { tq.write(i) } } - ) { _, _ -> Unit } - // the above only finishes if the consumer reads at least 100 values, this here is just to make sure there are no leftovers - atomically { tq.flush() } shouldBe emptyList() - } + } + }, + { + val collected = mutableSetOf() + for (i in 1..100) { + // consumer + atomically { + tq.read().also { it shouldBeInRange (1..100) } + }.also { collected.add(it) } + } + // verify that we got 100 unique numbers + collected.size shouldBeExactly 100 + } + ) { _, _ -> Unit } + // the above only finishes if the consumer reads at least 100 values, this here is just to make sure there are no leftovers + atomically { tq.flush() } shouldBe emptyList() } -) +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TArrayTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TArrayTest.kt index c8bf40ebad2..3bb492174ff 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TArrayTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TArrayTest.kt @@ -1,35 +1,39 @@ package arrow.fx.stm -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class TArrayTest : StringSpec({ - "creating an array" { - val t1 = TArray.new(10) { it } - t1.size() shouldBeExactly 10 - atomically { t1.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..9).sum() - atomically { (0..9).fold(true) { acc, v -> t1.get(v) == v && acc } } shouldBe true +class TArrayTest { - val t2 = atomically { newTArray(10) { it } } - t2.size() shouldBeExactly 10 - atomically { t2.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..9).sum() - atomically { (0..9).fold(true) { acc, v -> t2.get(v) == v && acc } } shouldBe true - } - "get should get the correct value" { - val t2 = atomically { newTArray(20) { it } } - atomically { (0..19).fold(true) { acc, v -> t2.get(v) == v && acc } } shouldBe true - } - "write should write to the correct value" { - val t2 = atomically { newTArray(20) { it } } - atomically { t2.get(5) } shouldBeExactly 5 - atomically { t2[5] = 2 } - atomically { t2.get(5) } shouldBeExactly 2 - } - "transform should perform an operation on each element" { - val t2 = atomically { newTArray(20) { it } } - atomically { t2.transform { it * 2 } } - atomically { t2.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..19).sum() * 2 - } + @Test fun creatingAnArray() = runTest { + val t1 = TArray.new(10) { it } + t1.size() shouldBeExactly 10 + atomically { t1.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..9).sum() + atomically { (0..9).fold(true) { acc, v -> t1.get(v) == v && acc } } shouldBe true + + val t2 = atomically { newTArray(10) { it } } + t2.size() shouldBeExactly 10 + atomically { t2.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..9).sum() + atomically { (0..9).fold(true) { acc, v -> t2.get(v) == v && acc } } shouldBe true + } + + @Test fun getShouldGetTheCorrectValue() = runTest { + val t2 = atomically { newTArray(20) { it } } + atomically { (0..19).fold(true) { acc, v -> t2.get(v) == v && acc } } shouldBe true + } + + @Test fun writeShouldWriteToTheCorrectValue() = runTest { + val t2 = atomically { newTArray(20) { it } } + atomically { t2.get(5) } shouldBeExactly 5 + atomically { t2[5] = 2 } + atomically { t2.get(5) } shouldBeExactly 2 + } + + @Test fun transformShouldPerformAnOperationOnEachElement() = runTest { + val t2 = atomically { newTArray(20) { it } } + atomically { t2.transform { it * 2 } } + atomically { t2.fold(0) { acc, v -> acc + v } } shouldBeExactly (0..19).sum() * 2 } -) +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMVarTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMVarTest.kt index eac2389e97b..4e23fd65780 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMVarTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMVarTest.kt @@ -1,140 +1,158 @@ package arrow.fx.stm -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.orNull import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class TMVarTest : StringSpec({ - "empty creates an empty TMVar" { - val t1 = TMVar.empty() - atomically { t1.tryTake() } shouldBe null - val t2 = atomically { newEmptyTMVar() } - atomically { t2.tryTake() } shouldBe null - } - "new creates a filled TMVar" { - val t1 = TMVar.new(100) - atomically { t1.take() } shouldBe 100 - val t2 = atomically { newTMVar(10) } - atomically { t2.take() } shouldBe 10 - } - "take leaves the TMVar empty" { - val tm = TMVar.new(500) - atomically { tm.take() } shouldBeExactly 500 - atomically { tm.tryTake() } shouldBe null - } - "isEmpty = tryRead == null" { - checkAll(Arb.int().orNull()) { i -> - val tm = when (i) { - null -> TMVar.empty() - else -> TMVar.new(i) - } - atomically { tm.isEmpty() } shouldBe - atomically { tm.tryRead() == null } - atomically { tm.isEmpty() } shouldBe - (i == null) - } - } - "isEmpty = tryRead != null" { - checkAll(Arb.int().orNull()) { i -> - val tm = when (i) { - null -> TMVar.empty() - else -> TMVar.new(i) - } - atomically { tm.isNotEmpty() } shouldBe - atomically { tm.tryRead() != null } - atomically { tm.isNotEmpty() } shouldBe - (i != null) +class TMVarTest { + + @Test fun emptyCreatesAnEmptyTMVar() = runTest { + val t1 = TMVar.empty() + atomically { t1.tryTake() } shouldBe null + val t2 = atomically { newEmptyTMVar() } + atomically { t2.tryTake() } shouldBe null + } + + @Test fun newCreatesAFilledTMVar() = runTest { + val t1 = TMVar.new(100) + atomically { t1.take() } shouldBe 100 + val t2 = atomically { newTMVar(10) } + atomically { t2.take() } shouldBe 10 + } + + @Test fun takeLeavesTheTMVarEmpty() = runTest { + val tm = TMVar.new(500) + atomically { tm.take() } shouldBeExactly 500 + atomically { tm.tryTake() } shouldBe null + } + + @Test fun isEmptyIsTryReadEqualsNull() = runTest { + checkAll(Arb.int().orNull()) { i -> + val tm = when (i) { + null -> TMVar.empty() + else -> TMVar.new(i) } + atomically { tm.isEmpty() } shouldBe + atomically { tm.tryRead() == null } + atomically { tm.isEmpty() } shouldBe + (i == null) } - "take retries on empty" { - val tm = TMVar.empty() - atomically { - stm { tm.take().let { true } } orElse { false } - } shouldBe false - atomically { tm.tryTake() } shouldBe null - } - "tryTake behaves like take if there is a value" { - val tm = TMVar.new(100) - atomically { - tm.tryTake() - } shouldBe 100 - atomically { tm.tryTake() } shouldBe null - } - "tryTake returns null on empty" { - val tm = TMVar.empty() - atomically { tm.tryTake() } shouldBe null - } - "read retries on empty" { - val tm = TMVar.empty() - atomically { - stm { tm.read().let { true } } orElse { false } - } shouldBe false - atomically { tm.tryTake() } shouldBe null - } - "read returns the value if not empty and does not remove it" { - val tm = TMVar.new(10) - atomically { - tm.read() - } shouldBe 10 - atomically { tm.tryTake() } shouldBe 10 - } - "tryRead behaves like read if there is a value" { - val tm = TMVar.new(100) - atomically { tm.tryRead() } shouldBe - atomically { tm.read() } - atomically { tm.tryTake() } shouldBe 100 - } - "tryRead returns null if there is no value" { - val tm = TMVar.empty() - atomically { tm.tryRead() } shouldBe null - atomically { tm.tryTake() } shouldBe null - } - "put retries if there is already a value" { - val tm = TMVar.new(5) - atomically { - stm { tm.put(100).let { true } } orElse { false } - } shouldBe false - atomically { tm.tryTake() } shouldBe 5 - } - "put replaces the value if it was empty" { - val tm = TMVar.empty() - atomically { - tm.put(100) - tm.tryTake() - } shouldBe 100 - } - "tryPut behaves like put if there is no value" { - val tm = TMVar.empty() - atomically { - tm.tryPut(100) - tm.tryTake() - } shouldBe atomically { - tm.put(100) - tm.tryTake() + } + + @Test fun isEmptyIsTryReadUnequalsNull() = runTest { + checkAll(Arb.int().orNull()) { i -> + val tm = when (i) { + null -> TMVar.empty() + else -> TMVar.new(i) } - atomically { tm.tryPut(30) } shouldBe true - atomically { tm.tryTake() } shouldBe 30 - } - "tryPut returns false if there is already a value" { - val tm = TMVar.new(30) - atomically { tm.tryPut(20) } shouldBe false - atomically { tm.tryTake() } shouldBe 30 - } - "swap replaces the current value only if it is not null" { - val tm = TMVar.new(30) - atomically { tm.swap(25) } shouldBeExactly 30 - atomically { tm.take() } shouldBeExactly 25 - } - "swap should retry if there is no value" { - val tm = TMVar.empty() - atomically { - stm { tm.swap(10).let { true } } orElse { false } - } shouldBe false - atomically { tm.tryTake() } shouldBe null + atomically { tm.isNotEmpty() } shouldBe + atomically { tm.tryRead() != null } + atomically { tm.isNotEmpty() } shouldBe + (i != null) } } -) + + @Test fun takeRetriesOnEmpty() = runTest { + val tm = TMVar.empty() + atomically { + stm { tm.take().let { true } } orElse { false } + } shouldBe false + atomically { tm.tryTake() } shouldBe null + } + + @Test fun tryTakeBehavesLikeTakeIfThereIsAValue() = runTest { + val tm = TMVar.new(100) + atomically { + tm.tryTake() + } shouldBe 100 + atomically { tm.tryTake() } shouldBe null + } + + @Test fun tryTakeReturnsNullOnEmpty() = runTest { + val tm = TMVar.empty() + atomically { tm.tryTake() } shouldBe null + } + + @Test fun readRetriesOnEmpty() = runTest { + val tm = TMVar.empty() + atomically { + stm { tm.read().let { true } } orElse { false } + } shouldBe false + atomically { tm.tryTake() } shouldBe null + } + + @Test fun readReturnsTheValueIfNotEmptyAndDoesNotRemoveIt() = runTest { + val tm = TMVar.new(10) + atomically { + tm.read() + } shouldBe 10 + atomically { tm.tryTake() } shouldBe 10 + } + + @Test fun tryReadBehavesLikeReadIfThereIsAValue() = runTest { + val tm = TMVar.new(100) + atomically { tm.tryRead() } shouldBe + atomically { tm.read() } + atomically { tm.tryTake() } shouldBe 100 + } + + @Test fun tryReadReturnsNullIfThereIsNoValue() = runTest { + val tm = TMVar.empty() + atomically { tm.tryRead() } shouldBe null + atomically { tm.tryTake() } shouldBe null + } + + @Test fun putRetriesIfThereIsAlreadyAValue() = runTest { + val tm = TMVar.new(5) + atomically { + stm { tm.put(100).let { true } } orElse { false } + } shouldBe false + atomically { tm.tryTake() } shouldBe 5 + } + + @Test fun putReplacesTheValueIfItWasEmpty() = runTest { + val tm = TMVar.empty() + atomically { + tm.put(100) + tm.tryTake() + } shouldBe 100 + } + + @Test fun tryPutBehavesLikePutIfThereIsNoValue() = runTest { + val tm = TMVar.empty() + atomically { + tm.tryPut(100) + tm.tryTake() + } shouldBe atomically { + tm.put(100) + tm.tryTake() + } + atomically { tm.tryPut(30) } shouldBe true + atomically { tm.tryTake() } shouldBe 30 + } + + @Test fun tryPutReturnsFalseIfThereIsAlreadyAValue() = runTest { + val tm = TMVar.new(30) + atomically { tm.tryPut(20) } shouldBe false + atomically { tm.tryTake() } shouldBe 30 + } + + @Test fun swapReplacesTheCurrentValueOnlyIfItIsNotNull() = runTest { + val tm = TMVar.new(30) + atomically { tm.swap(25) } shouldBeExactly 30 + atomically { tm.take() } shouldBeExactly 25 + } + + @Test fun swapShouldRetryIfThereIsNoValue() = runTest { + val tm = TMVar.empty() + atomically { + stm { tm.swap(10).let { true } } orElse { false } + } shouldBe false + atomically { tm.tryTake() } shouldBe null + } +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMapTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMapTest.kt index a88c750fe9a..e7ea5776ddc 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMapTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TMapTest.kt @@ -1,59 +1,64 @@ package arrow.fx.stm -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.map import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class TMapTest : StringSpec({ - "insert values" { - checkAll(Arb.int(), Arb.int()) { k, v -> - val map = TMap.new() - atomically { map.insert(k, v) } - atomically { map.lookup(k) } shouldBe v - } +class TMapTest { + + @Test fun insertValues() = runTest { + checkAll(Arb.int(), Arb.int()) { k, v -> + val map = TMap.new() + atomically { map.insert(k, v) } + atomically { map.lookup(k) } shouldBe v } - "insert multiple values" { - checkAll(Arb.map(Arb.int(), Arb.int())) { pairs -> - val map = TMap.new() - atomically { - for ((k, v) in pairs) map.insert(k, v) - } - atomically { - for ((k, v) in pairs) map.lookup(k) shouldBe v - } + } + + @Test fun insertMultipleValues() = runTest { + checkAll(Arb.map(Arb.int(), Arb.int())) { pairs -> + val map = TMap.new() + atomically { + for ((k, v) in pairs) map.insert(k, v) } - } - "insert multiple colliding values" { - checkAll(Arb.map(Arb.int(), Arb.int())) { pairs -> - val map = TMap.new { 0 } // hash function that always returns 0 - atomically { - for ((k, v) in pairs) map.insert(k, v) - } - atomically { - for ((k, v) in pairs) map.lookup(k) shouldBe v - } + atomically { + for ((k, v) in pairs) map.lookup(k) shouldBe v } } - "insert and remove" { - checkAll(Arb.int(), Arb.int()) { k, v -> - val map = TMap.new() - atomically { map.insert(k, v) } - atomically { map.lookup(k) } shouldBe v - atomically { map.remove(k) } - atomically { map.lookup(k) } shouldBe null + } + + @Test fun insertMultipleCollidingValues() = runTest { + checkAll(Arb.map(Arb.int(), Arb.int())) { pairs -> + val map = TMap.new { 0 } // hash function that always returns 0 + atomically { + for ((k, v) in pairs) map.insert(k, v) } - } - "update" { - checkAll(Arb.int(), Arb.int(), Arb.int()) { k, v, g -> - val map = TMap.new() - atomically { map.insert(k, v) } - atomically { map.lookup(k) } shouldBe v - atomically { map.update(k) { v + g } } - atomically { map.lookup(k) } shouldBe v + g + atomically { + for ((k, v) in pairs) map.lookup(k) shouldBe v } } } -) + + @Test fun insertAndRemove() = runTest { + checkAll(Arb.int(), Arb.int()) { k, v -> + val map = TMap.new() + atomically { map.insert(k, v) } + atomically { map.lookup(k) } shouldBe v + atomically { map.remove(k) } + atomically { map.lookup(k) } shouldBe null + } + } + + @Test fun update() = runTest { + checkAll(Arb.int(), Arb.int(), Arb.int()) { k, v, g -> + val map = TMap.new() + atomically { map.insert(k, v) } + atomically { map.lookup(k) } shouldBe v + atomically { map.update(k) { v + g } } + atomically { map.lookup(k) } shouldBe v + g + } + } +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TQueueTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TQueueTest.kt index d55545e0329..8444f6e8518 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TQueueTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TQueueTest.kt @@ -1,124 +1,139 @@ package arrow.fx.stm -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest import kotlin.random.Random +import kotlin.test.Test -class TQueueTest : StringSpec({ - "writing to a queue adds an element" { - val tq = TQueue.new() - atomically { tq.write(10) } - atomically { tq.flush() } shouldBe listOf(10) - } - "reading from a queue should retry if the queue is empty" { - val tq = TQueue.new() - atomically { - stm { tq.read().let { true } } orElse { false } - } shouldBe false - } - "reading from a queue should remove that value" { - val tq = TQueue.new() - atomically { tq.write(10); tq.write(20) } - atomically { tq.read() } shouldBe 10 - atomically { tq.flush() } shouldBe listOf(20) - } - "tryRead behaves like read if there are values to read" { - val tq = TQueue.new() - atomically { tq.write(10) } - atomically { tq.tryRead() } shouldBe 10 - atomically { tq.flush() } shouldBe emptyList() - } - "tryRead returns null if the queue is empty" { - val tq = TQueue.new() - atomically { tq.tryRead() } shouldBe null - } - "flush empties the entire queue and returns it" { - val tq = TQueue.new() - atomically { tq.write(20); tq.write(30); tq.write(40) } - atomically { tq.flush() } shouldBe listOf(20, 30, 40) - atomically { tq.flush() } shouldBe emptyList() - } - "reading/flushing should work after mixed reads/writes" { - val tq = TQueue.new() - atomically { tq.write(20); tq.write(30); tq.peek(); tq.write(40) } - atomically { tq.read() } shouldBe 20 - atomically { tq.flush() } shouldBe listOf(30, 40) +class TQueueTest { - atomically { tq.write(20); tq.write(30); tq.peek(); tq.write(40) } - atomically { tq.flush() } shouldBe listOf(20, 30, 40) - atomically { tq.flush() } shouldBe emptyList() - } - "peek should leave the queue unchanged" { - val tq = TQueue.new() - atomically { tq.write(20); tq.write(30); tq.write(40) } - atomically { tq.peek() } shouldBeExactly 20 - atomically { tq.flush() } shouldBe listOf(20, 30, 40) - } - "peek should retry if the queue is empty" { + @Test fun writingToAQueueAddsAnElement() = runTest { + val tq = TQueue.new() + atomically { tq.write(10) } + atomically { tq.flush() } shouldBe listOf(10) + } + + @Test fun readingFromAQueueShouldRetryIfTheQueueIsEmpty() = runTest { + val tq = TQueue.new() + atomically { + stm { tq.read().let { true } } orElse { false } + } shouldBe false + } + + @Test fun readingFromAQueueShouldRemoveThatValue() = runTest { + val tq = TQueue.new() + atomically { tq.write(10); tq.write(20) } + atomically { tq.read() } shouldBe 10 + atomically { tq.flush() } shouldBe listOf(20) + } + + @Test fun tryReadBehavesLikeReadIfThereAreValuesToRead() = runTest { + val tq = TQueue.new() + atomically { tq.write(10) } + atomically { tq.tryRead() } shouldBe 10 + atomically { tq.flush() } shouldBe emptyList() + } + + @Test fun tryReadReturnsNullIfTheQueueIsEmpty() = runTest { + val tq = TQueue.new() + atomically { tq.tryRead() } shouldBe null + } + + @Test fun flushEmptiesTheEntireQueueAndReturnsIt() = runTest { + val tq = TQueue.new() + atomically { tq.write(20); tq.write(30); tq.write(40) } + atomically { tq.flush() } shouldBe listOf(20, 30, 40) + atomically { tq.flush() } shouldBe emptyList() + } + + @Test fun readingFlushingShouldWorkAfterMixedReadsWrites() = runTest { + val tq = TQueue.new() + atomically { tq.write(20); tq.write(30); tq.peek(); tq.write(40) } + atomically { tq.read() } shouldBe 20 + atomically { tq.flush() } shouldBe listOf(30, 40) + + atomically { tq.write(20); tq.write(30); tq.peek(); tq.write(40) } + atomically { tq.flush() } shouldBe listOf(20, 30, 40) + atomically { tq.flush() } shouldBe emptyList() + } + + @Test fun peekShouldLeaveTheQueueUnchanged() = runTest { + val tq = TQueue.new() + atomically { tq.write(20); tq.write(30); tq.write(40) } + atomically { tq.peek() } shouldBeExactly 20 + atomically { tq.flush() } shouldBe listOf(20, 30, 40) + } + + @Test fun peekShouldRetryIfTheQueueIsEmpty() = runTest { + val tq = TQueue.new() + atomically { + stm { tq.peek().let { true } } orElse { false } + } shouldBe false + } + + @Test fun tryPeekShouldBehaveLikePeekIfThereAreElements() = runTest { + val tq = TQueue.new() + atomically { tq.write(20); tq.write(30); tq.write(40) } + atomically { tq.peek() } shouldBeExactly + atomically { tq.tryPeek()!! } + atomically { tq.flush() } shouldBe listOf(20, 30, 40) + } + + @Test fun tryPeekShouldReturnNullIfTheQueueIsEmpty() = runTest { + val tq = TQueue.new() + atomically { tq.tryPeek() } shouldBe null + } + + @Test fun isEmptyAndIsNotEmptyShouldWorkCorrectly() = runTest { + val tq = TQueue.new() + atomically { tq.isEmpty() } shouldBe true + atomically { tq.isNotEmpty() } shouldBe false + atomically { tq.write(20) } + atomically { tq.isEmpty() } shouldBe false + atomically { tq.isNotEmpty() } shouldBe true + atomically { tq.peek(); tq.write(30) } + atomically { tq.isEmpty() } shouldBe false + atomically { tq.isNotEmpty() } shouldBe true + } + + @Test fun sizeShouldReturnTheCorrectAmount() = runTest { + checkAll(Arb.int(0..50)) { i -> val tq = TQueue.new() atomically { - stm { tq.peek().let { true } } orElse { false } - } shouldBe false - } - "tryPeek should behave like peek if there are elements" { - val tq = TQueue.new() - atomically { tq.write(20); tq.write(30); tq.write(40) } - atomically { tq.peek() } shouldBeExactly - atomically { tq.tryPeek()!! } - atomically { tq.flush() } shouldBe listOf(20, 30, 40) - } - "tryPeek should return null if the queue is empty" { - val tq = TQueue.new() - atomically { tq.tryPeek() } shouldBe null - } - "isEmpty and isNotEmpty should work correctly" { - val tq = TQueue.new() - atomically { tq.isEmpty() } shouldBe true - atomically { tq.isNotEmpty() } shouldBe false - atomically { tq.write(20) } - atomically { tq.isEmpty() } shouldBe false - atomically { tq.isNotEmpty() } shouldBe true - atomically { tq.peek(); tq.write(30) } - atomically { tq.isEmpty() } shouldBe false - atomically { tq.isNotEmpty() } shouldBe true - } - "size should return the correct amount" { - checkAll(Arb.int(0..50)) { i -> - val tq = TQueue.new() - atomically { - for (j in 0..i) { - // read to swap read and write lists randomly - if (Random.nextFloat() > 0.9) tq.tryPeek() - tq.write(j) - } + for (j in 0..i) { + // read to swap read and write lists randomly + if (Random.nextFloat() > 0.9) tq.tryPeek() + tq.write(j) } - atomically { tq.size() } shouldBeExactly i + 1 } + atomically { tq.size() } shouldBeExactly i + 1 } - "writeFront should work correctly" { - val tq = TQueue.new() - atomically { tq.writeFront(203) } - atomically { tq.peek() } shouldBeExactly 203 - atomically { tq.writeFront(50) } - atomically { tq.peek() } shouldBeExactly 50 - atomically { tq.flush() } shouldBe listOf(50, 203) - } - "removeAll should work" { - val tq = TQueue.new() - atomically { tq.removeAll { true } } - atomically { tq.flush() } shouldBe emptyList() + } - atomically { - for (i in 0..100) { - tq.write(i) - } - tq.removeAll { it.rem(2) == 0 } - tq.flush() - } shouldBe (0..100).filter { it.rem(2) == 0 } - } + @Test fun writeFrontShouldWorkCorrectly() = runTest { + val tq = TQueue.new() + atomically { tq.writeFront(203) } + atomically { tq.peek() } shouldBeExactly 203 + atomically { tq.writeFront(50) } + atomically { tq.peek() } shouldBeExactly 50 + atomically { tq.flush() } shouldBe listOf(50, 203) + } + + @Test fun removeAllShouldWork() = runTest { + val tq = TQueue.new() + atomically { tq.removeAll { true } } + atomically { tq.flush() } shouldBe emptyList() + + atomically { + for (i in 0..100) { + tq.write(i) + } + tq.removeAll { it.rem(2) == 0 } + tq.flush() + } shouldBe (0..100).filter { it.rem(2) == 0 } } -) +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TSemaphoreTest.kt b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TSemaphoreTest.kt index f0ace0450da..60ebee46b08 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TSemaphoreTest.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/commonTest/kotlin/arrow/fx/stm/TSemaphoreTest.kt @@ -1,80 +1,93 @@ package arrow.fx.stm import io.kotest.assertions.throwables.shouldThrow -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.ints.shouldBeExactly import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class TSemaphoreTest : StringSpec({ - "creating a semaphore with a negative number of permits fails" { - shouldThrow { TSemaphore.new(-1) } - shouldThrow { atomically { newTSem(-1) } } - } - "available reads the correct amount" { - val ts = TSemaphore.new(10) - atomically { ts.available() } shouldBeExactly 10 - } - "acquire removes one permit" { - val ts = TSemaphore.new(8) - atomically { ts.acquire(); ts.available() } shouldBeExactly 7 - } - "acquire retries if no permits are available" { - val ts = TSemaphore.new(0) - atomically { - stm { ts.acquire().let { true } } orElse { false } - } shouldBe false - } - "acquire(n) should take n permits" { - val ts = TSemaphore.new(10) - atomically { - ts.acquire(5); ts.available() - } shouldBeExactly 5 - } - "acquire(n) should retry if not enough permits are available" { - val ts = TSemaphore.new(10) - atomically { - stm { ts.acquire(100).let { true } } orElse { false } - } shouldBe false - } - "tryAcquire should behave like acquire if enough permits are available" { - val ts = TSemaphore.new(11) - val ts2 = TSemaphore.new(11) - atomically { ts.tryAcquire() } shouldBe - atomically { ts2.acquire().let { true } } - atomically { ts.available() } shouldBeExactly - atomically { ts2.available() } - } - "tryAcquire should not retry if not enough permits are available" { - val ts = TSemaphore.new(0) - atomically { - ts.tryAcquire() - } shouldBe false - } - "tryAcquire(n) should behave like acquire(n) if enough permits are available" { - val ts = TSemaphore.new(11) - val ts2 = TSemaphore.new(11) - atomically { ts.tryAcquire(4) } shouldBe - atomically { ts2.acquire(4).let { true } } - atomically { ts.available() } shouldBeExactly - atomically { ts2.available() } - } - "tryAcquire(n) should not retry if not enough permits are available" { - val ts = TSemaphore.new(3) - atomically { - ts.tryAcquire(10) - } shouldBe false - } - "release should add one permit" { - val ts = TSemaphore.new(0) - atomically { ts.release(); ts.available() } shouldBeExactly 1 - } - "release(n) should throw if given a negative number" { - val ts = TSemaphore.new(1) - shouldThrow { atomically { ts.release(-1) } } - } - "release(n) should add n permits" { - val ts = TSemaphore.new(3) - atomically { ts.release(6); ts.available() } shouldBe 9 - } +class TSemaphoreTest { + + @Test fun creatingASemaphoreWithANegativeNumberOfPermitsFails() = runTest { + shouldThrow { TSemaphore.new(-1) } + shouldThrow { atomically { newTSem(-1) } } + } + + @Test fun availableReadsTheCorrectAmount() = runTest { + val ts = TSemaphore.new(10) + atomically { ts.available() } shouldBeExactly 10 + } + + @Test fun acquireRemovesOnePermit() = runTest { + val ts = TSemaphore.new(8) + atomically { ts.acquire(); ts.available() } shouldBeExactly 7 + } + + @Test fun acquireRetriesIfNoPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(0) + atomically { + stm { ts.acquire().let { true } } orElse { false } + } shouldBe false + } + + @Test fun acquireNShouldTakeNPermits() = runTest { + val ts = TSemaphore.new(10) + atomically { + ts.acquire(5); ts.available() + } shouldBeExactly 5 + } + + @Test fun acquireNShouldRetryIfNotEnoughPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(10) + atomically { + stm { ts.acquire(100).let { true } } orElse { false } + } shouldBe false + } + + @Test fun tryAcquireShouldBehaveLikeAcquireIfEnoughPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(11) + val ts2 = TSemaphore.new(11) + atomically { ts.tryAcquire() } shouldBe + atomically { ts2.acquire().let { true } } + atomically { ts.available() } shouldBeExactly + atomically { ts2.available() } + } + + @Test fun tryAcquireShouldNotRetryIfNotEnoughPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(0) + atomically { + ts.tryAcquire() + } shouldBe false + } + + @Test fun tryAcquireNShouldBehaveLikeAcquireNIfEnoughPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(11) + val ts2 = TSemaphore.new(11) + atomically { ts.tryAcquire(4) } shouldBe + atomically { ts2.acquire(4).let { true } } + atomically { ts.available() } shouldBeExactly + atomically { ts2.available() } + } + + @Test fun tryAcquireNShouldNotRetryIfNotEnoughPermitsAreAvailable() = runTest { + val ts = TSemaphore.new(3) + atomically { + ts.tryAcquire(10) + } shouldBe false + } + + @Test fun releaseShouldAddOnePermit() = runTest { + val ts = TSemaphore.new(0) + atomically { ts.release(); ts.available() } shouldBeExactly 1 + } + + @Test fun releaseNShouldThrowIfGivenANegativeNumber() = runTest { + val ts = TSemaphore.new(1) + shouldThrow { atomically { ts.release(-1) } } + } + + @Test fun releaseNShouldAddNPermits() = runTest { + val ts = TSemaphore.new(3) + atomically { ts.release(6); ts.available() } shouldBe 9 } -) +} diff --git a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-06.kt b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-06.kt index 8c59628188e..fdd248d9144 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-06.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-06.kt @@ -6,7 +6,7 @@ import arrow.fx.stm.atomically suspend fun main() { //sampleStart val result = atomically { - catch({ throw Throwable() }) { e -> "caught" } + catch({ throw Throwable() }) { _ -> "caught" } } //sampleEnd println("Result $result") diff --git a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-41.kt b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-41.kt index 1f2ef07826f..6402fe8de66 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-41.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-stm-41.kt @@ -11,4 +11,5 @@ suspend fun main() { tarr.transform { it + 1 } } //sampleEnd + println("Result $result") } diff --git a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-tarray-04.kt b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-tarray-04.kt index 5af06152e32..6e2bb9b5e56 100644 --- a/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-tarray-04.kt +++ b/arrow-libs/fx/arrow-fx-stm/src/jvmTest/kotlin/examples/example-tarray-04.kt @@ -11,4 +11,5 @@ suspend fun main() { tarr.transform { it + 1 } } //sampleEnd + println("Result $result") } diff --git a/arrow-libs/optics/arrow-optics-compose/api/android/arrow-optics-compose.api b/arrow-libs/optics/arrow-optics-compose/api/android/arrow-optics-compose.api index 31d871ddeda..42c944cec77 100644 --- a/arrow-libs/optics/arrow-optics-compose/api/android/arrow-optics-compose.api +++ b/arrow-libs/optics/arrow-optics-compose/api/android/arrow-optics-compose.api @@ -6,12 +6,12 @@ public final class arrow/optics/CopyKt { public final class arrow/optics/FlowKt { public static final fun optic (Lkotlinx/coroutines/flow/MutableStateFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/MutableStateFlow; - public static final fun optic (Lkotlinx/coroutines/flow/SharedFlow;Larrow/optics/Getter;)Lkotlinx/coroutines/flow/SharedFlow; - public static final fun optic (Lkotlinx/coroutines/flow/StateFlow;Larrow/optics/Getter;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun optic (Lkotlinx/coroutines/flow/SharedFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/SharedFlow; + public static final fun optic (Lkotlinx/coroutines/flow/StateFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/StateFlow; } public final class arrow/optics/StateKt { public static final fun optic (Landroidx/compose/runtime/MutableState;Larrow/optics/PLens;)Landroidx/compose/runtime/MutableState; - public static final fun optic (Landroidx/compose/runtime/State;Larrow/optics/Getter;)Landroidx/compose/runtime/State; + public static final fun optic (Landroidx/compose/runtime/State;Larrow/optics/PLens;)Landroidx/compose/runtime/State; } diff --git a/arrow-libs/optics/arrow-optics-compose/api/jvm/arrow-optics-compose.api b/arrow-libs/optics/arrow-optics-compose/api/jvm/arrow-optics-compose.api index 31d871ddeda..42c944cec77 100644 --- a/arrow-libs/optics/arrow-optics-compose/api/jvm/arrow-optics-compose.api +++ b/arrow-libs/optics/arrow-optics-compose/api/jvm/arrow-optics-compose.api @@ -6,12 +6,12 @@ public final class arrow/optics/CopyKt { public final class arrow/optics/FlowKt { public static final fun optic (Lkotlinx/coroutines/flow/MutableStateFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/MutableStateFlow; - public static final fun optic (Lkotlinx/coroutines/flow/SharedFlow;Larrow/optics/Getter;)Lkotlinx/coroutines/flow/SharedFlow; - public static final fun optic (Lkotlinx/coroutines/flow/StateFlow;Larrow/optics/Getter;)Lkotlinx/coroutines/flow/StateFlow; + public static final fun optic (Lkotlinx/coroutines/flow/SharedFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/SharedFlow; + public static final fun optic (Lkotlinx/coroutines/flow/StateFlow;Larrow/optics/PLens;)Lkotlinx/coroutines/flow/StateFlow; } public final class arrow/optics/StateKt { public static final fun optic (Landroidx/compose/runtime/MutableState;Larrow/optics/PLens;)Landroidx/compose/runtime/MutableState; - public static final fun optic (Landroidx/compose/runtime/State;Larrow/optics/Getter;)Landroidx/compose/runtime/State; + public static final fun optic (Landroidx/compose/runtime/State;Larrow/optics/PLens;)Landroidx/compose/runtime/State; } diff --git a/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/Flow.kt b/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/Flow.kt index 30902538cca..7d58bc73ba2 100644 --- a/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/Flow.kt +++ b/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/Flow.kt @@ -9,7 +9,7 @@ import kotlinx.coroutines.flow.StateFlow /** * Exposes the values of [this] through the optic. */ -public fun SharedFlow.optic(g: Getter): SharedFlow = object : SharedFlow { +public fun SharedFlow.optic(g: Lens): SharedFlow = object : SharedFlow { override suspend fun collect(collector: FlowCollector): Nothing = this@optic.collect { collector.emit(g.get(it)) } @@ -20,7 +20,7 @@ public fun SharedFlow.optic(g: Getter): SharedFlow = object : /** * Exposes the values of [this] through the optic. */ -public fun StateFlow.optic(g: Getter): StateFlow = object : StateFlow { +public fun StateFlow.optic(g: Lens): StateFlow = object : StateFlow { override val value: A get() = g.get(this@optic.value) diff --git a/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/State.kt b/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/State.kt index 9fc93058b31..23b681ebefe 100644 --- a/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/State.kt +++ b/arrow-libs/optics/arrow-optics-compose/src/commonMain/kotlin/arrow/optics/State.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.State /** * Exposes the value of [this] through the optic. */ -public fun State.optic(g: Getter): State = object : State { +public fun State.optic(g: Lens): State = object : State { override val value: A get() = g.get(this@optic.value) } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts b/arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts index be7c960620a..fc326c9f5d4 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/build.gradle.kts @@ -24,9 +24,8 @@ dependencies { implementation(libs.ksp) testImplementation(libs.kotlin.stdlib) - testImplementation(libs.junitJupiter) - testImplementation(libs.junitJupiterEngine) - testImplementation(libs.assertj) + testImplementation(libs.kotlin.test) + testImplementation(libs.kotest.assertionsCore) testImplementation(libs.classgraph) testImplementation(libs.kotlinCompileTesting) { exclude( @@ -45,8 +44,7 @@ dependencies { testRuntimeOnly(projects.arrowOptics) } -tasks { - withType().configureEach { - maxParallelForks = 1 - } +tasks.withType().configureEach { + maxParallelForks = 1 + useJUnitPlatform() } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt index ddd9734cddc..e7aec76af32 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/domain.kt @@ -41,7 +41,6 @@ enum class OpticsTarget { ISO, LENS, PRISM, - OPTIONAL, DSL, } @@ -51,8 +50,6 @@ typealias PrismTarget = Target.Prism typealias LensTarget = Target.Lens -typealias OptionalTarget = Target.Optional - typealias SealedClassDsl = Target.SealedClassDsl typealias DataClassDsl = Target.DataClassDsl @@ -62,10 +59,9 @@ typealias ValueClassDsl = Target.ValueClassDsl sealed class Target { abstract val foci: List - data class Iso(override val foci: List) : Target() data class Prism(override val foci: List) : Target() data class Lens(override val foci: List) : Target() - data class Optional(override val foci: List) : Target() + data class Iso(override val foci: List) : Target() data class SealedClassDsl(override val foci: List) : Target() data class DataClassDsl(override val foci: List) : Target() data class ValueClassDsl(val focus: Focus) : Target() { @@ -73,102 +69,29 @@ sealed class Target { } } -typealias NonNullFocus = Focus.NonNull - -typealias OptionFocus = Focus.Option - -typealias NullableFocus = Focus.Nullable - -sealed class Focus { - - companion object { - operator fun invoke( - fullName: String, - paramName: String, - refinedType: KSType? = null, - onlyOneSealedSubclass: Boolean = false, - subclasses: List = emptyList(), - ): Focus = - when { - fullName.endsWith("?") -> Nullable( - className = fullName, - paramName = paramName, - refinedType = refinedType, - onlyOneSealedSubclass = onlyOneSealedSubclass, - subclasses = subclasses, - ) - fullName.startsWith("`arrow`.`core`.`Option`") -> Option( - className = fullName, - paramName = paramName, - refinedType = refinedType, - onlyOneSealedSubclass = onlyOneSealedSubclass, - subclasses = subclasses, - ) - else -> NonNull( - className = fullName, - paramName = paramName, - refinedType = refinedType, - onlyOneSealedSubclass = onlyOneSealedSubclass, - subclasses = subclasses, - ) - } - } - - abstract val className: String - abstract val paramName: String - - // only used for type-refining prisms - abstract val refinedType: KSType? - abstract val subclasses: List - abstract val onlyOneSealedSubclass: Boolean - +data class Focus( + val className: String, + val paramName: String, + val refinedType: KSType?, + val onlyOneSealedSubclass: Boolean = false, + val subclasses: List = emptyList(), +) { val refinedArguments: List get() = refinedType?.arguments?.filter { it.type?.resolve()?.declaration is KSTypeParameter }?.map { it.qualifiedString() }.orEmpty() - data class Nullable( - override val className: String, - override val paramName: String, - override val refinedType: KSType?, - override val onlyOneSealedSubclass: Boolean, - override val subclasses: List, - ) : Focus() { - val nonNullClassName = className.dropLast(1) - } - - data class Option( - override val className: String, - override val paramName: String, - override val refinedType: KSType?, - override val onlyOneSealedSubclass: Boolean, - override val subclasses: List, - ) : Focus() { - val nestedClassName = - Regex("`arrow`.`core`.`Option`<(.*)>$").matchEntire(className)!!.groupValues[1] + companion object { + operator fun invoke(fullName: String, paramName: String, subclasses: List = emptyList()): Focus = + Focus(fullName, paramName, null, subclasses = subclasses) } - - data class NonNull( - override val className: String, - override val paramName: String, - override val refinedType: KSType?, - override val onlyOneSealedSubclass: Boolean, - override val subclasses: List, - ) : Focus() } const val Lens = "arrow.optics.Lens" const val Iso = "arrow.optics.Iso" const val Optional = "arrow.optics.Optional" const val Prism = "arrow.optics.Prism" -const val Getter = "arrow.optics.Getter" -const val Setter = "arrow.optics.Setter" const val Traversal = "arrow.optics.Traversal" -const val Fold = "arrow.optics.Fold" -const val Every = "arrow.optics.Every" -const val Tuple = "arrow.core.Tuple" -const val Pair = "kotlin.Pair" -const val Triple = "kotlin.Triple" data class Snippet( val `package`: String, diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt index e7e4cc32273..042e982f2b0 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/dsl.kt @@ -12,16 +12,6 @@ fun generateLensDsl(ele: ADT, optic: DataClassDsl): Snippet { ) } -fun generateOptionalDsl(ele: ADT, optic: DataClassDsl): Snippet { - val (className, import) = resolveClassName(ele) - return Snippet( - `package` = ele.packageName, - name = ele.simpleName, - content = processOptionalSyntax(ele, optic, className), - imports = setOf(import), - ) -} - fun generatePrismDsl(ele: ADT, isoOptic: SealedClassDsl): Snippet { val (className, import) = resolveClassName(ele) return Snippet( @@ -46,15 +36,9 @@ private fun processLensSyntax(ele: ADT, foci: List, className: String): S return if (ele.typeParameters.isEmpty()) { foci.joinToString(separator = "\n") { focus -> """ - |${ele.visibilityModifierName} inline val $Iso.${focus.lensParamName()}: $Lens inline get() = this + $className.${focus.lensParamName()} |${ele.visibilityModifierName} inline val $Lens.${focus.lensParamName()}: $Lens inline get() = this + $className.${focus.lensParamName()} |${ele.visibilityModifierName} inline val $Optional.${focus.lensParamName()}: $Optional inline get() = this + $className.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Prism.${focus.lensParamName()}: $Optional inline get() = this + $className.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Getter.${focus.lensParamName()}: $Getter inline get() = this + $className.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Setter.${focus.lensParamName()}: $Setter inline get() = this + $className.${focus.lensParamName()} |${ele.visibilityModifierName} inline val $Traversal.${focus.lensParamName()}: $Traversal inline get() = this + $className.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Fold.${focus.lensParamName()}: $Fold inline get() = this + $className.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Every.${focus.lensParamName()}: $Every inline get() = this + $className.${focus.lensParamName()} | """.trimMargin() } @@ -63,71 +47,22 @@ private fun processLensSyntax(ele: ADT, foci: List, className: String): S val joinedTypeParams = ele.typeParameters.joinToString(separator = ",") foci.joinToString(separator = "\n") { focus -> """ - |${ele.visibilityModifierName} inline fun $Iso.${focus.lensParamName()}(): $Lens = this + $className.${focus.lensParamName()}() |${ele.visibilityModifierName} inline fun $Lens.${focus.lensParamName()}(): $Lens = this + $className.${focus.lensParamName()}() |${ele.visibilityModifierName} inline fun $Optional.${focus.lensParamName()}(): $Optional = this + $className.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Prism.${focus.lensParamName()}(): $Optional = this + $className.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Getter.${focus.lensParamName()}(): $Getter = this + $className.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.lensParamName()}(): $Setter = this + $className.${focus.lensParamName()}() |${ele.visibilityModifierName} inline fun $Traversal.${focus.lensParamName()}(): $Traversal = this + $className.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.lensParamName()}(): $Fold = this + $className.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Every.${focus.lensParamName()}(): $Every = this + $className.${focus.lensParamName()}() - | - """.trimMargin() - } - } -} - -private fun processOptionalSyntax(ele: ADT, optic: DataClassDsl, className: String): String { - val sourceClassNameWithParams = "${ele.sourceClassName}${ele.angledTypeParameters}" - val joinedTypeParams = ele.typeParameters.joinToString(separator = ",") - return optic.foci.filterNot { it is NonNullFocus }.joinToString(separator = "\n") { focus -> - val targetClassName = - when (focus) { - is Focus.Nullable -> focus.nonNullClassName - is Focus.Option -> focus.nestedClassName - is Focus.NonNull -> "" - } - if (ele.typeParameters.isEmpty()) { - """ - |${ele.visibilityModifierName} inline val $Iso.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Lens.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Optional.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Prism.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Setter.${focus.paramName}: $Setter inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Traversal.${focus.paramName}: $Traversal inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Fold.${focus.paramName}: $Fold inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Every.${focus.paramName}: $Every inline get() = this + $className.${focus.paramName} - | - """.trimMargin() - } else { - """ - |${ele.visibilityModifierName} inline fun $Iso.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Lens.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Optional.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Prism.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.paramName}(): $Setter = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Traversal.${focus.paramName}(): $Traversal = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.paramName}(): $Fold = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Every.${focus.paramName}(): $Every = this + $className.${focus.paramName}() | """.trimMargin() } } } -private fun processPrismSyntax(ele: ADT, dsl: SealedClassDsl, className: String): String { - return if (ele.typeParameters.isEmpty()) { +private fun processPrismSyntax(ele: ADT, dsl: SealedClassDsl, className: String): String = + if (ele.typeParameters.isEmpty()) { dsl.foci.joinToString(separator = "\n\n") { focus -> """ - |${ele.visibilityModifierName} inline val $Iso.${focus.paramName}: $Prism inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Lens.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Optional.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Prism.${focus.paramName}: $Prism inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Setter.${focus.paramName}: $Setter inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Traversal.${focus.paramName}: $Traversal inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Fold.${focus.paramName}: $Fold inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Every.${focus.paramName}: $Every inline get() = this + $className.${focus.paramName} | """.trimMargin() } @@ -139,19 +74,13 @@ private fun processPrismSyntax(ele: ADT, dsl: SealedClassDsl, className: String) else -> focus.refinedArguments.joinToString(separator = ",") } """ - |${ele.visibilityModifierName} inline fun $Iso.${focus.paramName}(): $Prism = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Lens.${focus.paramName}(): $Optional = this + ${ele.sourceClassName}.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Optional.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Prism.${focus.paramName}(): $Prism = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.paramName}(): $Setter = this + $className.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Traversal.${focus.paramName}(): $Traversal = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.paramName}(): $Fold = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Every.${focus.paramName}(): $Every = this + $className.${focus.paramName}() | """.trimMargin() } } -} private fun processIsoSyntax(ele: ADT, dsl: ValueClassDsl, className: String): String = if (ele.typeParameters.isEmpty()) { @@ -161,10 +90,7 @@ private fun processIsoSyntax(ele: ADT, dsl: ValueClassDsl, className: String): S |${ele.visibilityModifierName} inline val $Lens.${focus.paramName}: $Lens inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Optional.${focus.paramName}: $Optional inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Prism.${focus.paramName}: $Prism inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Setter.${focus.paramName}: $Setter inline get() = this + $className.${focus.paramName} |${ele.visibilityModifierName} inline val $Traversal.${focus.paramName}: $Traversal inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Fold.${focus.paramName}: $Fold inline get() = this + $className.${focus.paramName} - |${ele.visibilityModifierName} inline val $Every.${focus.paramName}: $Every inline get() = this + $className.${focus.paramName} | """.trimMargin() } @@ -180,10 +106,7 @@ private fun processIsoSyntax(ele: ADT, dsl: ValueClassDsl, className: String): S |${ele.visibilityModifierName} inline fun $Lens.${focus.paramName}(): $Lens = this + $className.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Optional.${focus.paramName}(): $Optional = this + $className.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Prism.${focus.paramName}(): $Prism = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.paramName}(): $Setter = this + $className.${focus.paramName}() |${ele.visibilityModifierName} inline fun $Traversal.${focus.paramName}(): $Traversal = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.paramName}(): $Fold = this + $className.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Every.${focus.paramName}(): $Every = this + $className.${focus.paramName}() | """.trimMargin() } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/errors.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/errors.kt index 7dc4a0bd138..f3cf8d5950c 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/errors.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/errors.kt @@ -8,14 +8,6 @@ val String.otherClassTypeErrorMessage |Only data, sealed, and value classes can be annotated with @optics """.trimMargin() -val String.typeParametersErrorMessage - get() = - """ - |$this cannot be annotated with @optics - | ^ - |Only classes with no type parameters can be annotated with @optics - """.trimMargin() - val String.lensErrorMessage get() = """ @@ -25,15 +17,6 @@ val String.lensErrorMessage |It is only valid for data classes. """.trimMargin() -val String.optionalErrorMessage - get() = - """ - |Cannot generate arrow.optics.Optional for $this - | ^ - |arrow.optics.OpticsTarget.OPTIONAL is an invalid @optics argument for $this. - |It is only valid for data classes. - """.trimMargin() - val String.prismErrorMessage get() = """ diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/iso.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/iso.kt new file mode 100644 index 00000000000..fd15d46fb34 --- /dev/null +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/iso.kt @@ -0,0 +1,27 @@ +package arrow.optics.plugin.internals + +import arrow.optics.plugin.OpticsProcessorOptions + +internal fun OpticsProcessorOptions.generateIsos(ele: ADT, target: IsoTarget) = + Snippet(`package` = ele.packageName, name = ele.simpleName, content = processElement(ele, target.foci.first())) + +private fun OpticsProcessorOptions.processElement(adt: ADT, focus: Focus): String { + val sourceClassNameWithParams = "${adt.sourceClassName}${adt.angledTypeParameters}" + val firstLine = when { + adt.typeParameters.isEmpty() -> + "${adt.visibilityModifierName} $inlineText val ${adt.sourceClassName}.Companion.${focus.paramName}: $Iso<${adt.sourceClassName}, ${focus.className}> $inlineText get()" + else -> + "${adt.visibilityModifierName} $inlineText fun ${adt.angledTypeParameters} ${adt.sourceClassName}.Companion.${focus.paramName}(): $Iso<$sourceClassNameWithParams, ${focus.className}>" + } + val fineParamName = focus.paramName.plusIfNotBlank( + prefix = "`", + postfix = "`", + ) + return """ + |$firstLine = $Iso( + | get = { ${adt.sourceName}: $sourceClassNameWithParams -> ${adt.sourceName}.$fineParamName }, + | reverseGet = { $fineParamName: ${focus.className} -> ${adt.sourceClassName}($fineParamName) } + |) + | + """.trimMargin() +} diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt deleted file mode 100644 index 2fe4e693835..00000000000 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/isos.kt +++ /dev/null @@ -1,85 +0,0 @@ -package arrow.optics.plugin.internals - -import arrow.optics.plugin.OpticsProcessorOptions -import arrow.optics.plugin.isValue - -internal fun OpticsProcessorOptions.generateIsos(ele: ADT, target: IsoTarget) = - Snippet(`package` = ele.packageName, name = ele.simpleName, content = processElement(ele, target)) - -inline val Target.targetNames - inline get() = foci.map(Focus::className) - -private fun OpticsProcessorOptions.processElement(iso: ADT, target: Target): String { - val foci = target.foci - val letters = listOf( - "first", - "second", - "third", - "fourth", - "fifth", - "sixth", - "seventh", - "eighth", - "ninth", - "tenth", - "eleventh", - "twelfth", - "thirteenth", - "fourteenth", - "fifteenth", - "sixteenth", - "seventeenth", - "eighteenth", - "nineteenth", - "twentieth", - "twentyFirst", - "twentySecond", - ) - - fun Focus.format(): String = - "${iso.sourceName}.${paramName.plusIfNotBlank(prefix = "`", postfix = "`")}" - - fun tupleConstructor() = - when (foci.size) { - 1 -> "${iso.sourceName}.${foci.first().paramName}" - 2 -> "$Pair(${foci[0].format()}, ${foci[1].format()})" - 3 -> "$Triple(${foci[0].format()}, ${foci[1].format()}, ${foci[2].format()})" - else -> - foci.joinToString(prefix = "$Tuple${foci.size}(", postfix = ")", transform = Focus::format) - } - - fun focusType() = - when (foci.size) { - 1 -> target.targetNames.first() - 2 -> target.targetNames.joinToString(prefix = "$Pair<", postfix = ">") - 3 -> target.targetNames.joinToString(prefix = "$Triple<", postfix = ">") - else -> target.targetNames.joinToString(prefix = "$Tuple${foci.size}<", postfix = ">") - } - - fun classConstructorFromTuple() = - when (foci.size) { - 1 -> "${iso.sourceClassName}(it)" - 2 -> "pair: ${focusType()} -> ${iso.sourceClassName}(pair.first, pair.second)" - 3 -> - "triple: ${focusType()} -> ${iso.sourceClassName}(triple.first, triple.second, triple.third)" - else -> - "tuple: ${focusType()} -> ${(foci.indices).joinToString(prefix = "${iso.sourceClassName}(", postfix = ")", transform = { "tuple.${letters[it]}" })}" - } - - val isoName = if (iso.declaration.isValue) target.foci.first().paramName else "iso" - val sourceClassNameWithParams = "${iso.sourceClassName}${iso.angledTypeParameters}" - val firstLine = when { - iso.typeParameters.isEmpty() -> - "${iso.visibilityModifierName} $inlineText val ${iso.sourceClassName}.Companion.$isoName: $Iso<${iso.sourceClassName}, ${focusType()}> $inlineText get()" - else -> - "${iso.visibilityModifierName} $inlineText fun ${iso.angledTypeParameters} ${iso.sourceClassName}.Companion.$isoName(): $Iso<$sourceClassNameWithParams, ${focusType()}>" - } - - return """ - |$firstLine = $Iso( - | get = { ${iso.sourceName}: $sourceClassNameWithParams -> ${tupleConstructor()} }, - | reverseGet = { ${classConstructorFromTuple()} } - |) - | - """.trimMargin() -} diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt index 37bd7d0f97e..40b5905c4a0 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/lenses.kt @@ -1,7 +1,6 @@ package arrow.optics.plugin.internals import arrow.optics.plugin.OpticsProcessorOptions -import java.util.Locale internal fun OpticsProcessorOptions.generateLenses(ele: ADT, target: LensTarget) = Snippet( @@ -10,17 +9,6 @@ internal fun OpticsProcessorOptions.generateLenses(ele: ADT, target: LensTarget) content = processElement(ele, target.foci), ) -private fun String.toUpperCamelCase(): String = - split(" ") - .joinToString( - "", - transform = { - it.replaceFirstChar { - if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() - } - }, - ) - private fun OpticsProcessorOptions.processElement(adt: ADT, foci: List): String { val sourceClassNameWithParams = "${adt.sourceClassName}${adt.angledTypeParameters}" @@ -67,9 +55,4 @@ private fun OpticsProcessorOptions.processElement(adt: ADT, foci: List): } } -fun Focus.lensParamName(): String = - when (this) { - is NullableFocus -> "nullable${paramName.toUpperCamelCase()}" - is OptionFocus -> "option${paramName.toUpperCamelCase()}" - is NonNullFocus -> paramName - } +fun Focus.lensParamName(): String = paramName diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt deleted file mode 100644 index 5b49f783f54..00000000000 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/optional.kt +++ /dev/null @@ -1,55 +0,0 @@ -package arrow.optics.plugin.internals - -import arrow.optics.plugin.OpticsProcessorOptions - -internal fun OpticsProcessorOptions.generateOptionals(ele: ADT, target: OptionalTarget) = - Snippet( - `package` = ele.packageName, - name = ele.simpleName, - imports = - setOf("import arrow.core.left", "import arrow.core.right", "import arrow.core.toOption"), - content = processElement(ele, target.foci), - ) - -private fun OpticsProcessorOptions.processElement(ele: ADT, foci: List): String = - foci.joinToString(separator = "\n") { focus -> - - val targetClassName = when (focus) { - is NullableFocus -> focus.nonNullClassName - is OptionFocus -> focus.nestedClassName - is NonNullFocus -> return@joinToString "" - } - - val sourceClassNameWithParams = "${ele.sourceClassName}${ele.angledTypeParameters}" - val firstLine = when { - ele.typeParameters.isEmpty() -> - "${ele.visibilityModifierName} $inlineText val ${ele.sourceClassName}.Companion.${focus.paramName}: $Optional<${ele.sourceClassName}, $targetClassName> $inlineText get()" - else -> - "${ele.visibilityModifierName} $inlineText fun ${ele.angledTypeParameters} ${ele.sourceClassName}.Companion.${focus.paramName}(): $Optional<$sourceClassNameWithParams, $targetClassName>" - } - - fun getOrModifyF(toNullable: String = "") = - "{ ${ele.sourceName}: $sourceClassNameWithParams -> ${ele.sourceName}.${ - focus.paramName.plusIfNotBlank( - prefix = "`", - postfix = "`", - ) - }$toNullable?.right() ?: ${ele.sourceName}.left() }" - fun setF(fromNullable: String = "") = - "${ele.sourceName}.copy(${focus.paramName.plusIfNotBlank(prefix = "`", postfix = "`")} = value$fromNullable)" - - val (getOrModify, set) = - when (focus) { - is NullableFocus -> Pair(getOrModifyF(), setF()) - is OptionFocus -> Pair(getOrModifyF(".orNull()"), setF(".toOption()")) - is NonNullFocus -> return@joinToString "" - } - - """ - |$firstLine = $Optional( - | getOrModify = $getOrModify, - | set = { ${ele.sourceName}: $sourceClassNameWithParams, value: $targetClassName -> $set } - |) - | - """.trimMargin() - } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt index db697683b31..0426ef26475 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/processor.kt @@ -20,20 +20,21 @@ internal fun adt(c: KSClassDeclaration, logger: KSPLogger): ADT = ADT( c.packageName, c, - c.targets().mapNotNull { target -> + c.targets().map { target -> when (target) { OpticsTarget.LENS -> - evalAnnotatedClass(c, c.qualifiedNameOrSimpleName.lensErrorMessage, logger) - ?.let(::LensTarget) - OpticsTarget.OPTIONAL -> - evalAnnotatedClass(c, c.qualifiedNameOrSimpleName.optionalErrorMessage, logger) - ?.let(::OptionalTarget) + evalAnnotatedDataClass(c, c.qualifiedNameOrSimpleName.lensErrorMessage, logger) + .orEmpty() + .let(::LensTarget) + OpticsTarget.ISO -> - evalAnnotatedIsoElement(c, c.qualifiedNameOrSimpleName.isoErrorMessage, logger) + evalAnnotatedValueClass(c, c.qualifiedNameOrSimpleName.isoErrorMessage, logger) .let(::IsoTarget) + OpticsTarget.PRISM -> evalAnnotatedPrismElement(c, c.qualifiedNameOrSimpleName.prismErrorMessage, logger) .let(::PrismTarget) + OpticsTarget.DSL -> evalAnnotatedDslElement(c, logger) } }, @@ -58,7 +59,6 @@ internal fun KSClassDeclaration.targetsFromOpticsAnnotation(): Set "arrow.optics.OpticsTarget.ISO" -> OpticsTarget.ISO "arrow.optics.OpticsTarget.LENS" -> OpticsTarget.LENS "arrow.optics.OpticsTarget.PRISM" -> OpticsTarget.PRISM - "arrow.optics.OpticsTarget.OPTIONAL" -> OpticsTarget.OPTIONAL "arrow.optics.OpticsTarget.DSL" -> OpticsTarget.DSL else -> null } @@ -90,10 +90,7 @@ internal fun evalAnnotatedPrismElement( internal val KSDeclaration.qualifiedNameOrSimpleName: String get() = (qualifiedName ?: simpleName).asSanitizedString() -internal fun KSClassDeclaration.sealedSubclassFqNameList(): List = - getSealedSubclasses().mapNotNull { it.qualifiedName?.asString() }.toList() - -internal fun evalAnnotatedClass( +internal fun evalAnnotatedDataClass( element: KSClassDeclaration, errorMessage: String, logger: KSPLogger, @@ -167,6 +164,20 @@ fun KSPropertyDeclaration.sameInChildren(subclasses: Sequence = + when { + element.isValue -> + listOf(Focus(element.getConstructorTypesNames().first(), element.getConstructorParamNames().first())) + else -> { + logger.error(errorMessage, element) + emptyList() + } + } + internal fun evalAnnotatedDslElement(element: KSClassDeclaration, logger: KSPLogger): Target = when { element.isDataClass -> @@ -184,29 +195,6 @@ internal fun evalAnnotatedDslElement(element: KSClassDeclaration, logger: KSPLog else -> throw IllegalStateException("should only be sealed, data, or value by now") } -internal fun evalAnnotatedIsoElement( - element: KSClassDeclaration, - errorMessage: String, - logger: KSPLogger, -): List = - when { - element.isDataClass -> - element - .getConstructorTypesNames() - .zip(element.getConstructorParamNames(), Focus.Companion::invoke) - .takeIf { it.size <= 22 } - ?: run { - logger.error(element.qualifiedNameOrSimpleName.isoTooBigErrorMessage, element) - emptyList() - } - element.isValue -> - listOf(Focus(element.getConstructorTypesNames().first(), element.getConstructorParamNames().first())) - else -> { - logger.error(errorMessage, element) - emptyList() - } - } - internal fun KSClassDeclaration.getConstructorTypesNames(): List = primaryConstructor?.parameters?.map { it.type.resolve().qualifiedString() }.orEmpty() diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/snippets.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/snippets.kt index 0c8b94ea509..89dd95adebc 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/snippets.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/snippets.kt @@ -8,9 +8,8 @@ internal fun ADT.snippets(options: OpticsProcessorOptions): List = is IsoTarget -> options.generateIsos(this, it) is PrismTarget -> options.generatePrisms(this, it) is LensTarget -> options.generateLenses(this, it) - is OptionalTarget -> options.generateOptionals(this, it) is SealedClassDsl -> generatePrismDsl(this, it) - is DataClassDsl -> generateOptionalDsl(this, it) + generateLensDsl(this, it) + is DataClassDsl -> generateLensDsl(this, it) is ValueClassDsl -> generateIsoDsl(this, it) } } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/targets.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/targets.kt index ecc290f9213..8418198188b 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/targets.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/main/kotlin/arrow/optics/plugin/internals/targets.kt @@ -3,4 +3,4 @@ package arrow.optics.plugin.internals internal val ALL_TARGETS = OpticsTarget.entries internal val SEALED_TARGETS = setOf(OpticsTarget.PRISM, OpticsTarget.LENS, OpticsTarget.DSL) internal val VALUE_TARGETS = setOf(OpticsTarget.ISO, OpticsTarget.DSL) -internal val OTHER_TARGETS = setOf(OpticsTarget.ISO, OpticsTarget.LENS, OpticsTarget.OPTIONAL, OpticsTarget.DSL) +internal val OTHER_TARGETS = setOf(OpticsTarget.LENS, OpticsTarget.DSL) diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Compilation.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Compilation.kt index 4d664acb102..08b4121a479 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Compilation.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/Compilation.kt @@ -8,7 +8,11 @@ import com.tschuchort.compiletesting.SourceFile import com.tschuchort.compiletesting.kspSourcesDir import com.tschuchort.compiletesting.symbolProcessorProviders import io.github.classgraph.ClassGraph -import org.assertj.core.api.Assertions +import io.kotest.assertions.withClue +import io.kotest.matchers.booleans.shouldBeTrue +import io.kotest.matchers.nulls.shouldNotBeNull +import io.kotest.matchers.shouldBe +import io.kotest.matchers.shouldNotBe import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import java.io.File import java.net.URLClassLoader @@ -21,26 +25,30 @@ const val CLASS_FILENAME = "SourceKt" fun String.failsWith(check: (String) -> Boolean) { val compilationResult = compile(this) - Assertions.assertThat(compilationResult.exitCode).isNotEqualTo(KotlinCompilation.ExitCode.OK) - Assertions.assertThat(check(compilationResult.messages)).isTrue + compilationResult.exitCode shouldNotBe KotlinCompilation.ExitCode.OK + check(compilationResult.messages).shouldBeTrue() } fun String.compilationFails() { val compilationResult = compile(this) - Assertions.assertThat(compilationResult.exitCode).isNotEqualTo(KotlinCompilation.ExitCode.OK) + compilationResult.exitCode shouldNotBe KotlinCompilation.ExitCode.OK } fun String.compilationSucceeds(allWarningsAsErrors: Boolean = false) { val compilationResult = compile(this, allWarningsAsErrors = allWarningsAsErrors) - Assertions.assertThat(compilationResult.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + withClue(compilationResult.messages) { + compilationResult.exitCode shouldBe KotlinCompilation.ExitCode.OK + } } fun String.evals(thing: Pair) { val compilationResult = compile(this) - Assertions.assertThat(compilationResult.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + withClue(compilationResult.messages) { + compilationResult.exitCode shouldBe KotlinCompilation.ExitCode.OK + } val classesDirectory = compilationResult.outputDirectory val (variable, output) = thing - Assertions.assertThat(eval(variable, classesDirectory)).isEqualTo(output) + eval(variable, classesDirectory) shouldBe output } // UTILITY FUNCTIONS COPIED FROM META-TEST @@ -79,10 +87,9 @@ private fun classpathOf(dependency: String): File { ClassGraph().classpathFiles.firstOrNull { classpath -> dependenciesMatch(classpath, dependency) } -// println("classpath: ${ClassGraph().classpathFiles}") - Assertions.assertThat(file) - .`as`("$dependency not found in test runtime. Check your build configuration.") - .isNotNull + withClue("$dependency not found in test runtime. Check your build configuration.") { + file.shouldNotBeNull() + } return file!! } @@ -94,7 +101,7 @@ private fun dependenciesMatch(classpath: File, dependency: String): Boolean { } private fun sanitizeClassPathFileName(dep: String): String = - buildList { + buildList { var skip = false add(dep.first()) dep.reduce { a, b -> diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/CopyTest.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/CopyTest.kt index b9cf3ef208d..76084dd7ff9 100644 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/CopyTest.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/CopyTest.kt @@ -1,6 +1,6 @@ package arrow.optics.plugin -import org.junit.jupiter.api.Test +import kotlin.test.Test // from https://kotlinlang.slack.com/archives/C5UPMM0A0/p1688822411819599 // and https://github.com/overfullstack/my-lab/blob/master/arrow/src/test/kotlin/ga/overfullstack/optics/OpticsLab.kt diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt index c7b1857b3a8..076c439e094 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/DSLTests.kt @@ -1,6 +1,6 @@ package arrow.optics.plugin -import org.junit.jupiter.api.Test +import kotlin.test.Test class DSLTests { @@ -11,7 +11,7 @@ class DSLTests { |$imports |$dslModel |$dslValues - |val modify = Employees.employees.every(Every.list()).company.address + |val modify = Employees.employees.every(Every.list()).company.notNull.address | .street.name.modify(employees, String::toUpperCase) |val r = modify.employees.map { it.company?.address?.street?.name }.toString() """.evals("r" to "[LAMBDA STREET, LAMBDA STREET]") diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/IsoTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/IsoTests.kt old mode 100755 new mode 100644 index 3c4885a69b6..0abf877cc4a --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/IsoTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/IsoTests.kt @@ -1,105 +1,10 @@ package arrow.optics.plugin -import arrow.optics.plugin.internals.isoTooBigErrorMessage import arrow.optics.plugin.internals.noCompanion -import org.junit.jupiter.api.Test +import kotlin.test.Test class IsoTests { - @Test - fun `Isos will be generated for data class`() { - """ - |$`package` - |$imports - |@optics - |data class IsoData( - | val field1: String - |) { companion object } - | - |val i: Iso = IsoData.iso - |val r = i != null - """.evals("r" to true) - } - - @Test - fun `Isos will be generated for generic data class`() { - """ - |$`package` - |$imports - |@optics - |data class IsoData( - | val field1: A - |) { companion object } - | - |val i: Iso, String> = IsoData.iso() - |val r = i != null - """.evals("r" to true) - } - - @Test - fun `Isos will be generated for data class with secondary constructors`() { - """ - |$`package` - |$imports - |@optics - |data class IsoSecondaryConstructor(val fieldNumber: Int, val fieldString: String) { - | constructor(number: Int) : this(number, number.toString()) - | companion object - |} - | - |val i: Iso> = IsoSecondaryConstructor.iso - |val r = i != null - """.evals("r" to true) - } - - @Test - fun `Iso generation requires companion object declaration`() { - """ - |$`package` - |$imports - |@optics - |data class IsoNoCompanion( - | val field1: String - |) - """.failsWith { it.contains("IsoNoCompanion".noCompanion) } - } - - @Test - fun `Isos cannot be generated for huge classes`() { - """ - |$`package` - |$imports - |@optics - |data class IsoXXL( - | val field1: String, - | val field2: String, - | val field3: String, - | val field4: String, - | val field5: String, - | val field6: String, - | val field7: String, - | val field8: String, - | val field9: String, - | val field10: String, - | val field11: String, - | val field12: String, - | val field13: String, - | val field14: String, - | val field15: String, - | val field16: String, - | val field17: String, - | val field18: String, - | val field19: String, - | val field20: String, - | val field21: String, - | val field22: String, - | val field23: String - |) { - | companion object - |} - """.failsWith { it.contains("${`package`.removePrefix("package ")}.IsoXXL".isoTooBigErrorMessage) } - } - @Test fun `Isos will be generated for value class`() { """ @@ -116,7 +21,7 @@ class IsoTests { } @Test - fun `Iso generation requires companion object declaration, value class`() { + fun `Iso generation requires companion object declaration`() { """ |$`package` |$imports diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt index bcbeb87d7b0..d2de3cbb89e 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/LensTests.kt @@ -1,6 +1,6 @@ package arrow.optics.plugin -import org.junit.jupiter.api.Test +import kotlin.test.Test class LensTests { diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/OptionalTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/OptionalTests.kt index 6d78de9996e..5aa64d19b23 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/OptionalTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/OptionalTests.kt @@ -1,6 +1,6 @@ package arrow.optics.plugin -import org.junit.jupiter.api.Test +import kotlin.test.Test class OptionalTests { @@ -14,8 +14,9 @@ class OptionalTests { | val field1: String? |) { companion object } | - |val i: Optional = OptionalData.field1 - |val r = i != null + |val i: Lens = OptionalData.field1 + |val j: Optional = OptionalData.field1.notNull + |val r = i != null && j != null """.evals("r" to true) } @@ -29,8 +30,9 @@ class OptionalTests { | val field1: A? |) { companion object } | - |val i: Optional, String> = OptionalData.field1() - |val r = i != null + |val i: Lens, String?> = OptionalData.field1() + |val j: Optional, String> = OptionalData.field1().notNull + |val r = i != null && j != null """.evals("r" to true) } @@ -45,8 +47,9 @@ class OptionalTests { | companion object |} | - |val i: Optional = OptionalSecondaryConstructor.fieldString - |val r = i != null + |val i: Lens = OptionalSecondaryConstructor.fieldString + |val j: Optional = OptionalSecondaryConstructor.fieldString.notNull + |val r = i != null && j != null """.evals("r" to true) } } diff --git a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/PrismTests.kt b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/PrismTests.kt index 084865f0045..1b5dcec76d6 100755 --- a/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/PrismTests.kt +++ b/arrow-libs/optics/arrow-optics-ksp-plugin/src/test/kotlin/arrow/optics/plugin/PrismTests.kt @@ -1,6 +1,6 @@ package arrow.optics.plugin -import org.junit.jupiter.api.Test +import kotlin.test.Test class PrismTests { diff --git a/arrow-libs/optics/arrow-optics-reflect/api/arrow-optics-reflect.api b/arrow-libs/optics/arrow-optics-reflect/api/arrow-optics-reflect.api index d5a82f85bcd..440ead51bc1 100644 --- a/arrow-libs/optics/arrow-optics-reflect/api/arrow-optics-reflect.api +++ b/arrow-libs/optics/arrow-optics-reflect/api/arrow-optics-reflect.api @@ -1,10 +1,8 @@ public final class arrow/optics/ReflectionKt { - public static final fun getEvery (Lkotlin/reflect/KProperty1;)Larrow/optics/PEvery; - public static final fun getIter (Lkotlin/jvm/functions/Function1;)Larrow/optics/Fold; + public static final fun getEvery (Lkotlin/reflect/KProperty1;)Larrow/optics/PTraversal; public static final fun getLens (Lkotlin/reflect/KProperty1;)Larrow/optics/PLens; - public static final fun getOgetter (Lkotlin/jvm/functions/Function1;)Larrow/optics/Getter; public static final fun getOptional (Lkotlin/reflect/KProperty1;)Larrow/optics/POptional; - public static final fun getValues (Lkotlin/reflect/KProperty1;)Larrow/optics/PEvery; + public static final fun getValues (Lkotlin/reflect/KProperty1;)Larrow/optics/PTraversal; public static final fun instance (Lkotlin/reflect/KClass;)Larrow/optics/PPrism; } diff --git a/arrow-libs/optics/arrow-optics-reflect/build.gradle.kts b/arrow-libs/optics/arrow-optics-reflect/build.gradle.kts index 13e73874df1..34c9a211738 100644 --- a/arrow-libs/optics/arrow-optics-reflect/build.gradle.kts +++ b/arrow-libs/optics/arrow-optics-reflect/build.gradle.kts @@ -23,13 +23,11 @@ dependencies { implementation(libs.kotlin.stdlib) testImplementation(libs.kotlin.stdlib) - testImplementation(libs.junitJupiterEngine) + testImplementation(libs.kotlin.test) + testImplementation(libs.coroutines.test) testImplementation(libs.kotlin.reflect) - - testImplementation(libs.kotest.frameworkEngine) testImplementation(libs.kotest.assertionsCore) testImplementation(libs.kotest.property) - testRuntimeOnly(libs.kotest.runnerJUnit5) } tasks.jar { @@ -37,3 +35,7 @@ tasks.jar { attributes["Automatic-Module-Name"] = "arrow.optics.reflect" } } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/optics/arrow-optics-reflect/src/main/kotlin/arrow/optics/Reflection.kt b/arrow-libs/optics/arrow-optics-reflect/src/main/kotlin/arrow/optics/Reflection.kt index 3ac44751968..dffe8763eab 100644 --- a/arrow-libs/optics/arrow-optics-reflect/src/main/kotlin/arrow/optics/Reflection.kt +++ b/arrow-libs/optics/arrow-optics-reflect/src/main/kotlin/arrow/optics/Reflection.kt @@ -27,10 +27,6 @@ public inline fun instance(): Prism = override fun reverseGet(focus: A): S = focus } -/** Focuses on a given field */ -public val ((S) -> A).ogetter: Getter - get() = Getter { s -> this(s) } - /** * [Lens] that focuses on a field in a data class * @@ -48,13 +44,10 @@ public val KProperty1.lens: Lens public val KProperty1.optional: Optional get() = lens compose Optional.nullable() -public val ((S) -> Iterable).iter: Fold - get() = ogetter compose Fold.iterable() - -public val KProperty1>.every: Every +public val KProperty1>.every: Traversal get() = lens compose Every.list() -public val KProperty1>.values: Every +public val KProperty1>.values: Traversal get() = lens compose Every.map() private val KProperty1.reflectiveCopy: (S, A) -> S get() { diff --git a/arrow-libs/optics/arrow-optics-reflect/src/test/kotlin/arrow/optics/ReflectionTest.kt b/arrow-libs/optics/arrow-optics-reflect/src/test/kotlin/arrow/optics/ReflectionTest.kt index bb6533c76a6..78deb285ca4 100644 --- a/arrow-libs/optics/arrow-optics-reflect/src/test/kotlin/arrow/optics/ReflectionTest.kt +++ b/arrow-libs/optics/arrow-optics-reflect/src/test/kotlin/arrow/optics/ReflectionTest.kt @@ -1,56 +1,52 @@ package arrow.optics -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb -import io.kotest.property.arbitrary.int +import io.kotest.property.arbitrary.Codepoint +import io.kotest.property.arbitrary.ascii import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test data class Person(val name: String, val friends: List) sealed interface Cutlery -object Fork : Cutlery -object Spoon : Cutlery +data object Fork : Cutlery +data object Spoon : Cutlery -object ReflectionTest : StringSpec({ +class ReflectionTest { + private val asciiString: Arb = Arb.string(codepoints = Codepoint.ascii()) - "optional for function" { - checkAll(Arb.list(Arb.int())) { ints -> - val firsty = { it: List -> it.firstOrNull() } - firsty.ogetter.get(ints) shouldBe ints.firstOrNull() - } - } - - "lenses for field, get" { - checkAll(Arb.string(), Arb.list(Arb.string())) { nm, fs -> + @Test fun lensesForFieldGet() = runTest { + checkAll(asciiString, Arb.list(asciiString, 1..20)) { nm, fs -> val p = Person(nm, fs.toMutableList()) Person::name.lens.get(p) shouldBe nm } } - "lenses for field, set" { - checkAll(Arb.string(), Arb.list(Arb.string())) { nm, fs -> + @Test fun lensesForFieldSet() = runTest { + checkAll(asciiString, Arb.list(asciiString, 1..20)) { nm, fs -> val p = Person(nm, fs.toMutableList()) - val m = Person::name.lens.modify(p) { it.capitalize() } - m shouldBe Person(nm.capitalize(), fs) + val m = Person::name.lens.modify(p) { it.lowercase() } + m shouldBe Person(nm.lowercase(), fs) } } - "traversal for list, set" { - checkAll(Arb.string(), Arb.list(Arb.string())) { nm, fs -> + @Test fun traversalForListSet() = runTest { + checkAll(asciiString, Arb.list(asciiString, 1..20)) { nm, fs -> val p = Person(nm, fs) - val m = Person::friends.every.modify(p) { it.capitalize() } - m shouldBe Person(nm, fs.map { it.capitalize() }) + val m = Person::friends.every.modify(p) { it.lowercase() } + m shouldBe Person(nm, fs.map { it.lowercase() }) } } - "instances" { + @Test fun instances() = runTest { val things = listOf(Fork, Spoon, Fork) val forks = Every.list() compose instance() val spoons = Every.list() compose instance() forks.size(things) shouldBe 2 spoons.size(things) shouldBe 1 } -}) +} diff --git a/arrow-libs/optics/arrow-optics/api/arrow-optics.api b/arrow-libs/optics/arrow-optics/api/arrow-optics.api index bf78e859048..cd3a6020a8b 100644 --- a/arrow-libs/optics/arrow-optics/api/arrow-optics.api +++ b/arrow-libs/optics/arrow-optics/api/arrow-optics.api @@ -1,6 +1,6 @@ public abstract interface class arrow/optics/Copy { public abstract fun inside (Larrow/optics/PTraversal;Lkotlin/jvm/functions/Function1;)V - public abstract fun set (Larrow/optics/PSetter;Ljava/lang/Object;)V + public abstract fun set (Larrow/optics/PTraversal;Ljava/lang/Object;)V public abstract fun transform (Larrow/optics/PTraversal;Lkotlin/jvm/functions/Function1;)V } @@ -12,141 +12,23 @@ public final class arrow/optics/CopyKt { public static final fun copy (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } -public abstract interface class arrow/optics/Fold { - public static final field Companion Larrow/optics/Fold$Companion; - public abstract fun all (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public abstract fun any (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public abstract fun choice (Larrow/optics/Fold;)Larrow/optics/Fold; - public abstract fun combineAll (Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun compose (Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun either ()Larrow/optics/Fold; - public abstract fun exists (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public abstract fun findOrNull (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun firstOrNull (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun fold (Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun getAll (Ljava/lang/Object;)Ljava/util/List; - public abstract fun isEmpty (Ljava/lang/Object;)Z - public abstract fun isNotEmpty (Ljava/lang/Object;)Z - public static fun iterable ()Larrow/optics/Fold; - public abstract fun lastOrNull (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun left ()Larrow/optics/Fold; - public static fun list ()Larrow/optics/Fold; - public static fun map ()Larrow/optics/Fold; - public static fun nonEmptyList ()Larrow/optics/Fold; - public static fun option ()Larrow/optics/Fold; - public static fun pair ()Larrow/optics/Fold; - public abstract fun plus (Larrow/optics/Fold;)Larrow/optics/Fold; - public abstract fun right ()Larrow/optics/Fold; - public static fun sequence ()Larrow/optics/Fold; - public abstract fun size (Ljava/lang/Object;)I - public static fun string ()Larrow/optics/Fold; - public static fun triple ()Larrow/optics/Fold; - public static fun tuple10 ()Larrow/optics/Fold; - public static fun tuple4 ()Larrow/optics/Fold; - public static fun tuple5 ()Larrow/optics/Fold; - public static fun tuple6 ()Larrow/optics/Fold; - public static fun tuple7 ()Larrow/optics/Fold; - public static fun tuple8 ()Larrow/optics/Fold; - public static fun tuple9 ()Larrow/optics/Fold; -} - -public final class arrow/optics/Fold$Companion { - public final fun codiagonal ()Larrow/optics/Fold; - public final fun either ()Larrow/optics/Fold; - public final fun id ()Larrow/optics/Fold; - public final fun iterable ()Larrow/optics/Fold; - public final fun list ()Larrow/optics/Fold; - public final fun map ()Larrow/optics/Fold; - public final fun nonEmptyList ()Larrow/optics/Fold; - public final fun option ()Larrow/optics/Fold; - public final fun pair ()Larrow/optics/Fold; - public final fun select (Lkotlin/jvm/functions/Function1;)Larrow/optics/Fold; - public final fun sequence ()Larrow/optics/Fold; - public final fun string ()Larrow/optics/Fold; - public final fun triple ()Larrow/optics/Fold; - public final fun tuple10 ()Larrow/optics/Fold; - public final fun tuple4 ()Larrow/optics/Fold; - public final fun tuple5 ()Larrow/optics/Fold; - public final fun tuple6 ()Larrow/optics/Fold; - public final fun tuple7 ()Larrow/optics/Fold; - public final fun tuple8 ()Larrow/optics/Fold; - public final fun tuple9 ()Larrow/optics/Fold; - public final fun void ()Larrow/optics/Fold; -} - -public final class arrow/optics/Fold$DefaultImpls { - public static fun all (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun any (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/Fold;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun combineAll (Larrow/optics/Fold;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/Fold;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun exists (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun findOrNull (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun firstOrNull (Larrow/optics/Fold;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/Fold;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/Fold;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun getAll (Larrow/optics/Fold;Ljava/lang/Object;)Ljava/util/List; - public static fun isEmpty (Larrow/optics/Fold;Ljava/lang/Object;)Z - public static fun isNotEmpty (Larrow/optics/Fold;Ljava/lang/Object;)Z - public static fun lastOrNull (Larrow/optics/Fold;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/Fold;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun right (Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun size (Larrow/optics/Fold;Ljava/lang/Object;)I -} - -public abstract interface class arrow/optics/Getter : arrow/optics/Fold { - public static final field Companion Larrow/optics/Getter$Companion; - public abstract fun choice (Larrow/optics/Getter;)Larrow/optics/Getter; - public abstract fun compose (Larrow/optics/Getter;)Larrow/optics/Getter; - public abstract fun first ()Larrow/optics/Getter; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun get (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun left ()Larrow/optics/Getter; - public abstract fun plus (Larrow/optics/Getter;)Larrow/optics/Getter; - public abstract fun right ()Larrow/optics/Getter; - public abstract fun second ()Larrow/optics/Getter; - public abstract fun split (Larrow/optics/Getter;)Larrow/optics/Getter; - public abstract fun zip (Larrow/optics/Getter;)Larrow/optics/Getter; -} - -public final class arrow/optics/Getter$Companion { - public final fun codiagonal ()Larrow/optics/Getter; - public final fun id ()Larrow/optics/Getter; -} - -public final class arrow/optics/Getter$DefaultImpls { - public static fun all (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun any (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/Getter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun choice (Larrow/optics/Getter;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun combineAll (Larrow/optics/Getter;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/Getter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/Getter;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun exists (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun findOrNull (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun first (Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun firstOrNull (Larrow/optics/Getter;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/Getter;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/Getter;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/Getter;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun getAll (Larrow/optics/Getter;Ljava/lang/Object;)Ljava/util/List; - public static fun isEmpty (Larrow/optics/Getter;Ljava/lang/Object;)Z - public static fun isNotEmpty (Larrow/optics/Getter;Ljava/lang/Object;)Z - public static fun lastOrNull (Larrow/optics/Getter;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun plus (Larrow/optics/Getter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/Getter;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun right (Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun second (Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun size (Larrow/optics/Getter;Ljava/lang/Object;)I - public static fun split (Larrow/optics/Getter;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun zip (Larrow/optics/Getter;Larrow/optics/Getter;)Larrow/optics/Getter; +public final class arrow/optics/Every { + public static final field INSTANCE Larrow/optics/Every; + public static final fun either ()Larrow/optics/PTraversal; + public static final fun list ()Larrow/optics/PTraversal; + public static final fun map ()Larrow/optics/PTraversal; + public static final fun nonEmptyList ()Larrow/optics/PTraversal; + public static final fun option ()Larrow/optics/PTraversal; + public static final fun pair ()Larrow/optics/PTraversal; + public static final fun sequence ()Larrow/optics/PTraversal; + public static final fun string ()Larrow/optics/PTraversal; + public static final fun triple ()Larrow/optics/PTraversal; + public static final fun tuple4 ()Larrow/optics/PTraversal; + public static final fun tuple5 ()Larrow/optics/PTraversal; + public static final fun tuple6 ()Larrow/optics/PTraversal; + public static final fun tuple7 ()Larrow/optics/PTraversal; + public static final fun tuple8 ()Larrow/optics/PTraversal; + public static final fun tuple9 ()Larrow/optics/PTraversal; } public final class arrow/optics/ListKt { @@ -160,97 +42,15 @@ public final class arrow/optics/ListKt { public abstract interface annotation class arrow/optics/OpticsCopyMarker : java/lang/annotation/Annotation { } -public final class arrow/optics/OptionalGetterKt { - public static final fun OptionalGetter (Lkotlin/jvm/functions/Function1;)Larrow/optics/POptionalGetter; -} - public final class arrow/optics/OptionalKt { public static final fun Optional (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/optics/POptional; } -public abstract interface class arrow/optics/PEvery : arrow/optics/Fold, arrow/optics/PSetter, arrow/optics/PTraversal { - public static final field Companion Larrow/optics/PEvery$Companion; - public abstract fun compose (Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static fun either ()Larrow/optics/PEvery; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun list ()Larrow/optics/PEvery; - public static fun map ()Larrow/optics/PEvery; - public abstract fun modify (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun nonEmptyList ()Larrow/optics/PEvery; - public static fun option ()Larrow/optics/PEvery; - public static fun pair ()Larrow/optics/PEvery; - public abstract fun plus (Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static fun sequence ()Larrow/optics/PEvery; - public static fun string ()Larrow/optics/PEvery; - public static fun triple ()Larrow/optics/PEvery; - public static fun tuple10 ()Larrow/optics/PEvery; - public static fun tuple4 ()Larrow/optics/PEvery; - public static fun tuple5 ()Larrow/optics/PEvery; - public static fun tuple6 ()Larrow/optics/PEvery; - public static fun tuple7 ()Larrow/optics/PEvery; - public static fun tuple8 ()Larrow/optics/PEvery; - public static fun tuple9 ()Larrow/optics/PEvery; -} - -public final class arrow/optics/PEvery$Companion { - public final fun either ()Larrow/optics/PEvery; - public final fun from (Larrow/optics/PTraversal;Larrow/optics/Fold;)Larrow/optics/PEvery; - public final fun list ()Larrow/optics/PEvery; - public final fun map ()Larrow/optics/PEvery; - public final fun nonEmptyList ()Larrow/optics/PEvery; - public final fun option ()Larrow/optics/PEvery; - public final fun pair ()Larrow/optics/PEvery; - public final fun sequence ()Larrow/optics/PEvery; - public final fun string ()Larrow/optics/PEvery; - public final fun triple ()Larrow/optics/PEvery; - public final fun tuple10 ()Larrow/optics/PEvery; - public final fun tuple4 ()Larrow/optics/PEvery; - public final fun tuple5 ()Larrow/optics/PEvery; - public final fun tuple6 ()Larrow/optics/PEvery; - public final fun tuple7 ()Larrow/optics/PEvery; - public final fun tuple8 ()Larrow/optics/PEvery; - public final fun tuple9 ()Larrow/optics/PEvery; -} - -public final class arrow/optics/PEvery$DefaultImpls { - public static fun all (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun any (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/PEvery;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun choice (Larrow/optics/PEvery;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun choice (Larrow/optics/PEvery;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun combineAll (Larrow/optics/PEvery;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/PEvery;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/PEvery;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static fun compose (Larrow/optics/PEvery;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun compose (Larrow/optics/PEvery;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun exists (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun findOrNull (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun firstOrNull (Larrow/optics/PEvery;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/PEvery;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/PEvery;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun getAll (Larrow/optics/PEvery;Ljava/lang/Object;)Ljava/util/List; - public static fun isEmpty (Larrow/optics/PEvery;Ljava/lang/Object;)Z - public static fun isNotEmpty (Larrow/optics/PEvery;Ljava/lang/Object;)Z - public static fun lastOrNull (Larrow/optics/PEvery;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/PEvery;)Larrow/optics/Fold; - public static fun lift (Larrow/optics/PEvery;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static fun plus (Larrow/optics/PEvery;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/PEvery;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static fun plus (Larrow/optics/PEvery;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun plus (Larrow/optics/PEvery;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun right (Larrow/optics/PEvery;)Larrow/optics/Fold; - public static fun set (Larrow/optics/PEvery;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public static fun size (Larrow/optics/PEvery;Ljava/lang/Object;)I -} - -public abstract interface class arrow/optics/PIso : arrow/optics/Fold, arrow/optics/Getter, arrow/optics/PEvery, arrow/optics/PLens, arrow/optics/POptional, arrow/optics/PPrism, arrow/optics/PSetter, arrow/optics/PTraversal { +public abstract interface class arrow/optics/PIso : arrow/optics/PLens, arrow/optics/PPrism { public static final field Companion Larrow/optics/PIso$Companion; public abstract fun compose (Larrow/optics/PIso;)Larrow/optics/PIso; - public static fun eitherToPValidated ()Larrow/optics/PIso; - public static fun eitherToValidated ()Larrow/optics/PIso; public abstract fun first ()Larrow/optics/PIso; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun get (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getOrModify (Ljava/lang/Object;)Larrow/core/Either; public abstract fun left ()Larrow/optics/PIso; @@ -273,13 +73,9 @@ public abstract interface class arrow/optics/PIso : arrow/optics/Fold, arrow/opt public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun split (Larrow/optics/PIso;)Larrow/optics/PIso; public static fun stringToList ()Larrow/optics/PIso; - public static fun validatedToEither ()Larrow/optics/PIso; - public static fun validatedToPEither ()Larrow/optics/PIso; } public final class arrow/optics/PIso$Companion { - public final fun eitherToPValidated ()Larrow/optics/PIso; - public final fun eitherToValidated ()Larrow/optics/PIso; public final fun id ()Larrow/optics/PIso; public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Larrow/optics/PIso; public final fun listToOptionNel ()Larrow/optics/PIso; @@ -292,38 +88,24 @@ public final class arrow/optics/PIso$Companion { public final fun optionToPEither ()Larrow/optics/PIso; public final fun optionToPNullable ()Larrow/optics/PIso; public final fun stringToList ()Larrow/optics/PIso; - public final fun validatedToEither ()Larrow/optics/PIso; - public final fun validatedToPEither ()Larrow/optics/PIso; } public final class arrow/optics/PIso$DefaultImpls { public static fun all (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun any (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/PIso;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun choice (Larrow/optics/PIso;Larrow/optics/Getter;)Larrow/optics/Getter; public static fun choice (Larrow/optics/PIso;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun choice (Larrow/optics/PIso;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun choice (Larrow/optics/PIso;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun choice (Larrow/optics/PIso;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun choice (Larrow/optics/PIso;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun combineAll (Larrow/optics/PIso;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/PIso;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/PIso;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun compose (Larrow/optics/PIso;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun compose (Larrow/optics/PIso;Larrow/optics/PIso;)Larrow/optics/PIso; public static fun compose (Larrow/optics/PIso;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun compose (Larrow/optics/PIso;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun compose (Larrow/optics/PIso;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; public static fun compose (Larrow/optics/PIso;Larrow/optics/PPrism;)Larrow/optics/PPrism; - public static fun compose (Larrow/optics/PIso;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun compose (Larrow/optics/PIso;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun exists (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun findOrNull (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun first (Larrow/optics/PIso;)Larrow/optics/PIso; public static fun firstOrNull (Larrow/optics/PIso;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/PIso;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; public static fun fold (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/PIso;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun foldMap (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun getAll (Larrow/optics/PIso;Ljava/lang/Object;)Ljava/util/List; public static fun getOrModify (Larrow/optics/PIso;Ljava/lang/Object;)Larrow/core/Either; @@ -336,15 +118,10 @@ public final class arrow/optics/PIso$DefaultImpls { public static fun liftNullable (Larrow/optics/PIso;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static fun modify (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun modifyNullable (Larrow/optics/PIso;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun plus (Larrow/optics/PIso;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/PIso;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun plus (Larrow/optics/PIso;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun plus (Larrow/optics/PIso;Larrow/optics/PIso;)Larrow/optics/PIso; public static fun plus (Larrow/optics/PIso;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun plus (Larrow/optics/PIso;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun plus (Larrow/optics/PIso;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; public static fun plus (Larrow/optics/PIso;Larrow/optics/PPrism;)Larrow/optics/PPrism; - public static fun plus (Larrow/optics/PIso;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun plus (Larrow/optics/PIso;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun reverse (Larrow/optics/PIso;)Larrow/optics/PIso; public static fun right (Larrow/optics/PIso;)Larrow/optics/PIso; @@ -353,18 +130,16 @@ public final class arrow/optics/PIso$DefaultImpls { public static fun set (Larrow/optics/PIso;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun setNullable (Larrow/optics/PIso;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun size (Larrow/optics/PIso;Ljava/lang/Object;)I - public static fun split (Larrow/optics/PIso;Larrow/optics/Getter;)Larrow/optics/Getter; public static fun split (Larrow/optics/PIso;Larrow/optics/PIso;)Larrow/optics/PIso; public static fun split (Larrow/optics/PIso;Larrow/optics/PLens;)Larrow/optics/PLens; - public static fun zip (Larrow/optics/PIso;Larrow/optics/Getter;)Larrow/optics/Getter; } -public abstract interface class arrow/optics/PLens : arrow/optics/Getter, arrow/optics/PEvery, arrow/optics/POptional, arrow/optics/PSetter, arrow/optics/PTraversal { +public abstract interface class arrow/optics/PLens : arrow/optics/POptional { public static final field Companion Larrow/optics/PLens$Companion; public abstract fun choice (Larrow/optics/PLens;)Larrow/optics/PLens; public abstract fun compose (Larrow/optics/PLens;)Larrow/optics/PLens; public abstract fun first ()Larrow/optics/PLens; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun get (Ljava/lang/Object;)Ljava/lang/Object; public abstract fun getOrModify (Ljava/lang/Object;)Larrow/core/Either; public static fun nonEmptyListHead ()Larrow/optics/PLens; @@ -377,6 +152,7 @@ public abstract interface class arrow/optics/PLens : arrow/optics/Getter, arrow/ public abstract fun second ()Larrow/optics/PLens; public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public abstract fun split (Larrow/optics/PLens;)Larrow/optics/PLens; + public static fun stringToList ()Larrow/optics/PLens; public static fun tripleFirst ()Larrow/optics/PLens; public static fun triplePFirst ()Larrow/optics/PLens; public static fun triplePSecond ()Larrow/optics/PLens; @@ -395,6 +171,7 @@ public final class arrow/optics/PLens$Companion { public final fun pairPFirst ()Larrow/optics/PLens; public final fun pairPSecond ()Larrow/optics/PLens; public final fun pairSecond ()Larrow/optics/PLens; + public final fun stringToList ()Larrow/optics/PLens; public final fun tripleFirst ()Larrow/optics/PLens; public final fun triplePFirst ()Larrow/optics/PLens; public final fun triplePSecond ()Larrow/optics/PLens; @@ -406,29 +183,17 @@ public final class arrow/optics/PLens$Companion { public final class arrow/optics/PLens$DefaultImpls { public static fun all (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun any (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/PLens;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun choice (Larrow/optics/PLens;Larrow/optics/Getter;)Larrow/optics/Getter; public static fun choice (Larrow/optics/PLens;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun choice (Larrow/optics/PLens;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun choice (Larrow/optics/PLens;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun choice (Larrow/optics/PLens;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun choice (Larrow/optics/PLens;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun combineAll (Larrow/optics/PLens;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/PLens;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/PLens;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun compose (Larrow/optics/PLens;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun compose (Larrow/optics/PLens;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun compose (Larrow/optics/PLens;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun compose (Larrow/optics/PLens;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun compose (Larrow/optics/PLens;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun compose (Larrow/optics/PLens;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun exists (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun findOrNull (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun first (Larrow/optics/PLens;)Larrow/optics/PLens; public static fun firstOrNull (Larrow/optics/PLens;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/PLens;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; public static fun fold (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/PLens;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun foldMap (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun getAll (Larrow/optics/PLens;Ljava/lang/Object;)Ljava/util/List; public static fun getOrModify (Larrow/optics/PLens;Ljava/lang/Object;)Larrow/core/Either; @@ -436,38 +201,31 @@ public final class arrow/optics/PLens$DefaultImpls { public static fun isEmpty (Larrow/optics/PLens;Ljava/lang/Object;)Z public static fun isNotEmpty (Larrow/optics/PLens;Ljava/lang/Object;)Z public static fun lastOrNull (Larrow/optics/PLens;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/PLens;)Larrow/optics/Getter; public static fun lift (Larrow/optics/PLens;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static fun modify (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun modifyNullable (Larrow/optics/PLens;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun plus (Larrow/optics/PLens;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/PLens;Larrow/optics/Getter;)Larrow/optics/Getter; - public static fun plus (Larrow/optics/PLens;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun plus (Larrow/optics/PLens;Larrow/optics/PLens;)Larrow/optics/PLens; public static fun plus (Larrow/optics/PLens;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun plus (Larrow/optics/PLens;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun plus (Larrow/optics/PLens;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun plus (Larrow/optics/PLens;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun right (Larrow/optics/PLens;)Larrow/optics/Getter; public static fun second (Larrow/optics/PLens;)Larrow/optics/PLens; public static fun setNullable (Larrow/optics/PLens;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun size (Larrow/optics/PLens;Ljava/lang/Object;)I - public static fun split (Larrow/optics/PLens;Larrow/optics/Getter;)Larrow/optics/Getter; public static fun split (Larrow/optics/PLens;Larrow/optics/PLens;)Larrow/optics/PLens; - public static fun zip (Larrow/optics/PLens;Larrow/optics/Getter;)Larrow/optics/Getter; } -public abstract interface class arrow/optics/POptional : arrow/optics/PEvery, arrow/optics/POptionalGetter, arrow/optics/PSetter, arrow/optics/PTraversal { +public abstract interface class arrow/optics/POptional : arrow/optics/PTraversal { public static final field Companion Larrow/optics/POptional$Companion; public abstract fun choice (Larrow/optics/POptional;)Larrow/optics/POptional; public abstract fun compose (Larrow/optics/POptional;)Larrow/optics/POptional; public abstract fun first ()Larrow/optics/POptional; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun getOrModify (Ljava/lang/Object;)Larrow/core/Either; + public abstract fun getOrNull (Ljava/lang/Object;)Ljava/lang/Object; public static fun listHead ()Larrow/optics/POptional; public static fun listTail ()Larrow/optics/POptional; public abstract fun modify (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun modifyNullable (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static fun notNull ()Larrow/optics/POptional; public static fun nullable ()Larrow/optics/POptional; public abstract fun plus (Larrow/optics/POptional;)Larrow/optics/POptional; public abstract fun second ()Larrow/optics/POptional; @@ -481,6 +239,7 @@ public final class arrow/optics/POptional$Companion { public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Larrow/optics/POptional; public final fun listHead ()Larrow/optics/POptional; public final fun listTail ()Larrow/optics/POptional; + public final fun notNull ()Larrow/optics/POptional; public final fun nullable ()Larrow/optics/POptional; public final fun void ()Larrow/optics/POptional; } @@ -488,102 +247,38 @@ public final class arrow/optics/POptional$Companion { public final class arrow/optics/POptional$DefaultImpls { public static fun all (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun any (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/POptional;Larrow/optics/Fold;)Larrow/optics/Fold; public static fun choice (Larrow/optics/POptional;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun choice (Larrow/optics/POptional;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun choice (Larrow/optics/POptional;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun choice (Larrow/optics/POptional;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun combineAll (Larrow/optics/POptional;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/POptional;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/POptional;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun compose (Larrow/optics/POptional;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun compose (Larrow/optics/POptional;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun compose (Larrow/optics/POptional;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun compose (Larrow/optics/POptional;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun exists (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun findOrNull (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun first (Larrow/optics/POptional;)Larrow/optics/POptional; public static fun firstOrNull (Larrow/optics/POptional;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/POptional;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; public static fun fold (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/POptional;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun foldMap (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun getAll (Larrow/optics/POptional;Ljava/lang/Object;)Ljava/util/List; public static fun getOrNull (Larrow/optics/POptional;Ljava/lang/Object;)Ljava/lang/Object; public static fun isEmpty (Larrow/optics/POptional;Ljava/lang/Object;)Z public static fun isNotEmpty (Larrow/optics/POptional;Ljava/lang/Object;)Z public static fun lastOrNull (Larrow/optics/POptional;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/POptional;)Larrow/optics/Fold; public static fun lift (Larrow/optics/POptional;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static fun modify (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun modifyNullable (Larrow/optics/POptional;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun plus (Larrow/optics/POptional;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/POptional;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun plus (Larrow/optics/POptional;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun plus (Larrow/optics/POptional;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun plus (Larrow/optics/POptional;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun plus (Larrow/optics/POptional;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun right (Larrow/optics/POptional;)Larrow/optics/Fold; public static fun second (Larrow/optics/POptional;)Larrow/optics/POptional; public static fun setNullable (Larrow/optics/POptional;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; public static fun size (Larrow/optics/POptional;Ljava/lang/Object;)I } -public abstract interface class arrow/optics/POptionalGetter : arrow/optics/Fold { - public static final field Companion Larrow/optics/POptionalGetter$Companion; - public abstract fun choice (Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public abstract fun compose (Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun filter (Lkotlin/jvm/functions/Function1;)Larrow/optics/POptionalGetter; - public abstract fun first ()Larrow/optics/POptionalGetter; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun getOrModify (Ljava/lang/Object;)Larrow/core/Either; - public abstract fun getOrNull (Ljava/lang/Object;)Ljava/lang/Object; - public abstract fun plus (Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public abstract fun second ()Larrow/optics/POptionalGetter; -} - -public final class arrow/optics/POptionalGetter$Companion { - public final fun filter (Lkotlin/jvm/functions/Function1;)Larrow/optics/POptionalGetter; - public final fun id ()Larrow/optics/PIso; - public final fun invoke (Lkotlin/jvm/functions/Function1;)Larrow/optics/POptionalGetter; -} - -public final class arrow/optics/POptionalGetter$DefaultImpls { - public static fun all (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun any (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/POptionalGetter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun choice (Larrow/optics/POptionalGetter;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun combineAll (Larrow/optics/POptionalGetter;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/POptionalGetter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/POptionalGetter;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun exists (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun findOrNull (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun first (Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun firstOrNull (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/POptionalGetter;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/POptionalGetter;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/POptionalGetter;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun getAll (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Ljava/util/List; - public static fun getOrNull (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Ljava/lang/Object; - public static fun isEmpty (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Z - public static fun isNotEmpty (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Z - public static fun lastOrNull (Larrow/optics/POptionalGetter;Ljava/lang/Object;)Ljava/lang/Object; - public static fun left (Larrow/optics/POptionalGetter;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/POptionalGetter;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/POptionalGetter;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun right (Larrow/optics/POptionalGetter;)Larrow/optics/Fold; - public static fun second (Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun size (Larrow/optics/POptionalGetter;Ljava/lang/Object;)I -} - -public abstract interface class arrow/optics/PPrism : arrow/optics/PEvery, arrow/optics/POptional, arrow/optics/POptionalGetter, arrow/optics/PSetter, arrow/optics/PTraversal { +public abstract interface class arrow/optics/PPrism : arrow/optics/POptional { public static final field Companion Larrow/optics/PPrism$Companion; public abstract fun compose (Larrow/optics/PPrism;)Larrow/optics/PPrism; public static fun eitherLeft ()Larrow/optics/PPrism; public static fun eitherRight ()Larrow/optics/PPrism; public abstract fun first ()Larrow/optics/PPrism; - public abstract fun foldMap (Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public abstract fun getOrModify (Ljava/lang/Object;)Larrow/core/Either; public abstract fun left ()Larrow/optics/PPrism; public abstract fun liftNullable (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; @@ -617,26 +312,16 @@ public final class arrow/optics/PPrism$Companion { public final class arrow/optics/PPrism$DefaultImpls { public static fun all (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun any (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z - public static fun choice (Larrow/optics/PPrism;Larrow/optics/Fold;)Larrow/optics/Fold; public static fun choice (Larrow/optics/PPrism;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun choice (Larrow/optics/PPrism;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; - public static fun choice (Larrow/optics/PPrism;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun choice (Larrow/optics/PPrism;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun combineAll (Larrow/optics/PPrism;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; - public static fun compose (Larrow/optics/PPrism;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun compose (Larrow/optics/PPrism;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun compose (Larrow/optics/PPrism;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun compose (Larrow/optics/PPrism;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; public static fun compose (Larrow/optics/PPrism;Larrow/optics/PPrism;)Larrow/optics/PPrism; - public static fun compose (Larrow/optics/PPrism;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun compose (Larrow/optics/PPrism;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun exists (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun findOrNull (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun first (Larrow/optics/PPrism;)Larrow/optics/PPrism; public static fun firstOrNull (Larrow/optics/PPrism;Ljava/lang/Object;)Ljava/lang/Object; - public static fun fold (Larrow/optics/PPrism;Larrow/typeclasses/Monoid;Ljava/lang/Object;)Ljava/lang/Object; public static fun fold (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; - public static fun foldMap (Larrow/optics/PPrism;Larrow/typeclasses/Monoid;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun foldMap (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun getAll (Larrow/optics/PPrism;Ljava/lang/Object;)Ljava/util/List; public static fun getOrNull (Larrow/optics/PPrism;Ljava/lang/Object;)Ljava/lang/Object; @@ -648,12 +333,8 @@ public final class arrow/optics/PPrism$DefaultImpls { public static fun liftNullable (Larrow/optics/PPrism;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static fun modify (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun modifyNullable (Larrow/optics/PPrism;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static fun plus (Larrow/optics/PPrism;Larrow/optics/Fold;)Larrow/optics/Fold; - public static fun plus (Larrow/optics/PPrism;Larrow/optics/PEvery;)Larrow/optics/PEvery; public static fun plus (Larrow/optics/PPrism;Larrow/optics/POptional;)Larrow/optics/POptional; - public static fun plus (Larrow/optics/PPrism;Larrow/optics/POptionalGetter;)Larrow/optics/POptionalGetter; public static fun plus (Larrow/optics/PPrism;Larrow/optics/PPrism;)Larrow/optics/PPrism; - public static fun plus (Larrow/optics/PPrism;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun plus (Larrow/optics/PPrism;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun right (Larrow/optics/PPrism;)Larrow/optics/PPrism; public static fun second (Larrow/optics/PPrism;)Larrow/optics/PPrism; @@ -662,34 +343,23 @@ public final class arrow/optics/PPrism$DefaultImpls { public static fun size (Larrow/optics/PPrism;Ljava/lang/Object;)I } -public abstract interface class arrow/optics/PSetter { - public static final field Companion Larrow/optics/PSetter$Companion; - public abstract fun choice (Larrow/optics/PSetter;)Larrow/optics/PSetter; - public abstract fun compose (Larrow/optics/PSetter;)Larrow/optics/PSetter; - public abstract fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public abstract fun modify (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public abstract fun plus (Larrow/optics/PSetter;)Larrow/optics/PSetter; - public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class arrow/optics/PSetter$Companion { - public final fun codiagonal ()Larrow/optics/PSetter; - public final fun id ()Larrow/optics/PSetter; -} - -public final class arrow/optics/PSetter$DefaultImpls { - public static fun choice (Larrow/optics/PSetter;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun compose (Larrow/optics/PSetter;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun lift (Larrow/optics/PSetter;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static fun plus (Larrow/optics/PSetter;Larrow/optics/PSetter;)Larrow/optics/PSetter; - public static fun set (Larrow/optics/PSetter;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; -} - -public abstract interface class arrow/optics/PTraversal : arrow/optics/PSetter { +public abstract interface class arrow/optics/PTraversal { public static final field Companion Larrow/optics/PTraversal$Companion; + public abstract fun all (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public abstract fun any (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public abstract fun choice (Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public abstract fun compose (Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun either ()Larrow/optics/PTraversal; + public abstract fun exists (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public abstract fun findOrNull (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun firstOrNull (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun fold (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun foldMap (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun getAll (Ljava/lang/Object;)Ljava/util/List; + public abstract fun isEmpty (Ljava/lang/Object;)Z + public abstract fun isNotEmpty (Ljava/lang/Object;)Z + public abstract fun lastOrNull (Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun lift (Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; public static fun list ()Larrow/optics/PTraversal; public static fun map ()Larrow/optics/PTraversal; public abstract fun modify (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; @@ -697,7 +367,6 @@ public abstract interface class arrow/optics/PTraversal : arrow/optics/PSetter { public static fun option ()Larrow/optics/PTraversal; public static fun pPair ()Larrow/optics/PTraversal; public static fun pTriple ()Larrow/optics/PTraversal; - public static fun pTuple10 ()Larrow/optics/PTraversal; public static fun pTuple4 ()Larrow/optics/PTraversal; public static fun pTuple5 ()Larrow/optics/PTraversal; public static fun pTuple6 ()Larrow/optics/PTraversal; @@ -707,9 +376,10 @@ public abstract interface class arrow/optics/PTraversal : arrow/optics/PSetter { public static fun pair ()Larrow/optics/PTraversal; public abstract fun plus (Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun sequence ()Larrow/optics/PTraversal; + public abstract fun set (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public abstract fun size (Ljava/lang/Object;)I public static fun string ()Larrow/optics/PTraversal; public static fun triple ()Larrow/optics/PTraversal; - public static fun tuple10 ()Larrow/optics/PTraversal; public static fun tuple4 ()Larrow/optics/PTraversal; public static fun tuple5 ()Larrow/optics/PTraversal; public static fun tuple6 ()Larrow/optics/PTraversal; @@ -721,7 +391,7 @@ public abstract interface class arrow/optics/PTraversal : arrow/optics/PSetter { public final class arrow/optics/PTraversal$Companion { public final fun codiagonal ()Larrow/optics/PTraversal; public final fun either ()Larrow/optics/PTraversal; - public final fun id ()Larrow/optics/PTraversal; + public final fun id ()Larrow/optics/PIso; public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function10;)Larrow/optics/PTraversal; public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function11;)Larrow/optics/PTraversal; public final fun invoke (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function9;)Larrow/optics/PTraversal; @@ -737,7 +407,6 @@ public final class arrow/optics/PTraversal$Companion { public final fun option ()Larrow/optics/PTraversal; public final fun pPair ()Larrow/optics/PTraversal; public final fun pTriple ()Larrow/optics/PTraversal; - public final fun pTuple10 ()Larrow/optics/PTraversal; public final fun pTuple4 ()Larrow/optics/PTraversal; public final fun pTuple5 ()Larrow/optics/PTraversal; public final fun pTuple6 ()Larrow/optics/PTraversal; @@ -748,7 +417,6 @@ public final class arrow/optics/PTraversal$Companion { public final fun sequence ()Larrow/optics/PTraversal; public final fun string ()Larrow/optics/PTraversal; public final fun triple ()Larrow/optics/PTraversal; - public final fun tuple10 ()Larrow/optics/PTraversal; public final fun tuple4 ()Larrow/optics/PTraversal; public final fun tuple5 ()Larrow/optics/PTraversal; public final fun tuple6 ()Larrow/optics/PTraversal; @@ -759,14 +427,22 @@ public final class arrow/optics/PTraversal$Companion { } public final class arrow/optics/PTraversal$DefaultImpls { - public static fun choice (Larrow/optics/PTraversal;Larrow/optics/PSetter;)Larrow/optics/PSetter; + public static fun all (Larrow/optics/PTraversal;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static fun any (Larrow/optics/PTraversal;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z public static fun choice (Larrow/optics/PTraversal;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; - public static fun compose (Larrow/optics/PTraversal;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun compose (Larrow/optics/PTraversal;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; + public static fun exists (Larrow/optics/PTraversal;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Z + public static fun findOrNull (Larrow/optics/PTraversal;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static fun firstOrNull (Larrow/optics/PTraversal;Ljava/lang/Object;)Ljava/lang/Object; + public static fun fold (Larrow/optics/PTraversal;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;Ljava/lang/Object;)Ljava/lang/Object; + public static fun getAll (Larrow/optics/PTraversal;Ljava/lang/Object;)Ljava/util/List; + public static fun isEmpty (Larrow/optics/PTraversal;Ljava/lang/Object;)Z + public static fun isNotEmpty (Larrow/optics/PTraversal;Ljava/lang/Object;)Z + public static fun lastOrNull (Larrow/optics/PTraversal;Ljava/lang/Object;)Ljava/lang/Object; public static fun lift (Larrow/optics/PTraversal;Lkotlin/jvm/functions/Function1;)Lkotlin/jvm/functions/Function1; - public static fun plus (Larrow/optics/PTraversal;Larrow/optics/PSetter;)Larrow/optics/PSetter; public static fun plus (Larrow/optics/PTraversal;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; public static fun set (Larrow/optics/PTraversal;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public static fun size (Larrow/optics/PTraversal;Ljava/lang/Object;)I } public final class arrow/optics/PrismKt { @@ -774,13 +450,8 @@ public final class arrow/optics/PrismKt { } public final class arrow/optics/dsl/AtKt { - public static final fun at (Larrow/optics/Fold;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/Fold; - public static final fun at (Larrow/optics/Getter;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/Getter; - public static final fun at (Larrow/optics/PIso;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/PLens; public static final fun at (Larrow/optics/PLens;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/PLens; public static final fun at (Larrow/optics/POptional;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/POptional; - public static final fun at (Larrow/optics/PPrism;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/POptional; - public static final fun at (Larrow/optics/PSetter;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/PSetter; public static final fun at (Larrow/optics/PTraversal;Larrow/optics/typeclasses/At;Ljava/lang/Object;)Larrow/optics/PTraversal; } @@ -794,44 +465,28 @@ public final class arrow/optics/dsl/EitherKt { } public final class arrow/optics/dsl/EveryKt { - public static final fun every (Larrow/optics/Fold;Larrow/optics/PEvery;)Larrow/optics/Fold; - public static final fun every (Larrow/optics/PIso;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static final fun every (Larrow/optics/PLens;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static final fun every (Larrow/optics/POptional;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static final fun every (Larrow/optics/PPrism;Larrow/optics/PEvery;)Larrow/optics/PEvery; - public static final fun every (Larrow/optics/PSetter;Larrow/optics/PEvery;)Larrow/optics/PSetter; - public static final fun every (Larrow/optics/PTraversal;Larrow/optics/PEvery;)Larrow/optics/PTraversal; + public static final fun every (Larrow/optics/PTraversal;Larrow/optics/PTraversal;)Larrow/optics/PTraversal; } public final class arrow/optics/dsl/IndexKt { - public static final fun index (Larrow/optics/Fold;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/Fold; - public static final fun index (Larrow/optics/PIso;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/POptional; - public static final fun index (Larrow/optics/PLens;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/POptional; public static final fun index (Larrow/optics/POptional;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/POptional; - public static final fun index (Larrow/optics/PPrism;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/POptional; - public static final fun index (Larrow/optics/PSetter;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/PSetter; public static final fun index (Larrow/optics/PTraversal;Larrow/optics/typeclasses/Index;Ljava/lang/Object;)Larrow/optics/PTraversal; } +public final class arrow/optics/dsl/NullableKt { + public static final fun getNotNull (Larrow/optics/POptional;)Larrow/optics/POptional; + public static final fun getNotNull (Larrow/optics/PTraversal;)Larrow/optics/PTraversal; +} + public final class arrow/optics/dsl/OptionKt { - public static final fun getSome (Larrow/optics/Fold;)Larrow/optics/Fold; - public static final fun getSome (Larrow/optics/PIso;)Larrow/optics/PPrism; - public static final fun getSome (Larrow/optics/PLens;)Larrow/optics/POptional; public static final fun getSome (Larrow/optics/POptional;)Larrow/optics/POptional; - public static final fun getSome (Larrow/optics/PPrism;)Larrow/optics/PPrism; - public static final fun getSome (Larrow/optics/PSetter;)Larrow/optics/PSetter; public static final fun getSome (Larrow/optics/PTraversal;)Larrow/optics/PTraversal; } public abstract interface class arrow/optics/typeclasses/At { public static final field Companion Larrow/optics/typeclasses/At$Companion; - public abstract fun at (Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public abstract fun at (Larrow/optics/Getter;Ljava/lang/Object;)Larrow/optics/Getter; - public abstract fun at (Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/PLens; public abstract fun at (Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/PLens; public abstract fun at (Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun at (Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun at (Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public abstract fun at (Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; public abstract fun at (Ljava/lang/Object;)Larrow/optics/PLens; public static fun map ()Larrow/optics/typeclasses/At; @@ -839,19 +494,13 @@ public abstract interface class arrow/optics/typeclasses/At { } public final class arrow/optics/typeclasses/At$Companion { - public final fun fromIso (Larrow/optics/typeclasses/At;Larrow/optics/PIso;)Larrow/optics/typeclasses/At; public final fun map ()Larrow/optics/typeclasses/At; public final fun set ()Larrow/optics/typeclasses/At; } public final class arrow/optics/typeclasses/At$DefaultImpls { - public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/Getter;Ljava/lang/Object;)Larrow/optics/Getter; - public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/PLens; public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/PLens; public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public static fun at (Larrow/optics/typeclasses/At;Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; } @@ -872,7 +521,6 @@ public abstract interface class arrow/optics/typeclasses/Cons { } public final class arrow/optics/typeclasses/Cons$Companion { - public final fun fromIso (Larrow/optics/typeclasses/Cons;Larrow/optics/PIso;)Larrow/optics/typeclasses/Cons; public final fun invoke (Larrow/optics/PPrism;)Larrow/optics/typeclasses/Cons; public final fun list ()Larrow/optics/typeclasses/Cons; public final fun string ()Larrow/optics/typeclasses/Cons; @@ -887,7 +535,7 @@ public final class arrow/optics/typeclasses/Cons$DefaultImpls { public abstract interface class arrow/optics/typeclasses/FilterIndex { public static final field Companion Larrow/optics/typeclasses/FilterIndex$Companion; - public abstract fun filter (Lkotlin/jvm/functions/Function1;)Larrow/optics/PEvery; + public abstract fun filter (Lkotlin/jvm/functions/Function1;)Larrow/optics/PTraversal; public static fun list ()Larrow/optics/typeclasses/FilterIndex; public static fun map ()Larrow/optics/typeclasses/FilterIndex; public static fun nonEmptyList ()Larrow/optics/typeclasses/FilterIndex; @@ -896,7 +544,6 @@ public abstract interface class arrow/optics/typeclasses/FilterIndex { } public final class arrow/optics/typeclasses/FilterIndex$Companion { - public final fun fromIso (Larrow/optics/typeclasses/FilterIndex;Larrow/optics/PIso;)Larrow/optics/typeclasses/FilterIndex; public final fun list ()Larrow/optics/typeclasses/FilterIndex; public final fun map ()Larrow/optics/typeclasses/FilterIndex; public final fun nonEmptyList ()Larrow/optics/typeclasses/FilterIndex; @@ -906,19 +553,9 @@ public final class arrow/optics/typeclasses/FilterIndex$Companion { public abstract interface class arrow/optics/typeclasses/Index { public static final field Companion Larrow/optics/typeclasses/Index$Companion; - public abstract fun get (Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public abstract fun get (Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun get (Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/POptional; public abstract fun get (Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun get (Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun get (Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public abstract fun get (Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; - public abstract fun index (Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public abstract fun index (Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun index (Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/POptional; public abstract fun index (Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun index (Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public abstract fun index (Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public abstract fun index (Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; public abstract fun index (Ljava/lang/Object;)Larrow/optics/POptional; public static fun list ()Larrow/optics/typeclasses/Index; @@ -929,7 +566,6 @@ public abstract interface class arrow/optics/typeclasses/Index { } public final class arrow/optics/typeclasses/Index$Companion { - public final fun fromIso (Larrow/optics/typeclasses/Index;Larrow/optics/PIso;)Larrow/optics/typeclasses/Index; public final fun list ()Larrow/optics/typeclasses/Index; public final fun map ()Larrow/optics/typeclasses/Index; public final fun nonEmptyList ()Larrow/optics/typeclasses/Index; @@ -938,19 +574,9 @@ public final class arrow/optics/typeclasses/Index$Companion { } public final class arrow/optics/typeclasses/Index$DefaultImpls { - public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/POptional; public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public static fun get (Larrow/optics/typeclasses/Index;Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; - public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/Fold;Ljava/lang/Object;)Larrow/optics/Fold; - public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/PIso;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/PLens;Ljava/lang/Object;)Larrow/optics/POptional; public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/POptional;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/PPrism;Ljava/lang/Object;)Larrow/optics/POptional; - public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/PSetter;Ljava/lang/Object;)Larrow/optics/PSetter; public static fun index (Larrow/optics/typeclasses/Index;Larrow/optics/PTraversal;Ljava/lang/Object;)Larrow/optics/PTraversal; } @@ -967,7 +593,6 @@ public abstract interface class arrow/optics/typeclasses/Snoc { } public final class arrow/optics/typeclasses/Snoc$Companion { - public final fun fromIso (Larrow/optics/typeclasses/Snoc;Larrow/optics/PIso;)Larrow/optics/typeclasses/Snoc; public final fun invoke (Larrow/optics/PPrism;)Larrow/optics/typeclasses/Snoc; public final fun list ()Larrow/optics/typeclasses/Snoc; public final fun string ()Larrow/optics/typeclasses/Snoc; diff --git a/arrow-libs/optics/arrow-optics/build.gradle.kts b/arrow-libs/optics/arrow-optics/build.gradle.kts index 333180b9b54..55ad127fd24 100644 --- a/arrow-libs/optics/arrow-optics/build.gradle.kts +++ b/arrow-libs/optics/arrow-optics/build.gradle.kts @@ -5,7 +5,6 @@ plugins { alias(libs.plugins.arrowGradleConfig.kotlin) alias(libs.plugins.arrowGradleConfig.publish) alias(libs.plugins.kotlinx.kover) - alias(libs.plugins.kotest.multiplatform) alias(libs.plugins.spotless) } @@ -28,25 +27,12 @@ kotlin { commonTest { dependencies { - implementation(libs.kotest.frameworkEngine) + implementation(libs.kotlin.test) + implementation(libs.coroutines.test) implementation(libs.kotest.assertionsCore) implementation(libs.kotest.property) } } - jvmTest { - dependencies { - implementation(libs.kotlin.stdlib) - implementation(libs.junitJupiterEngine) - implementation(libs.kotlin.reflect) - } - } - - jvmMain { - dependencies { - implementation(libs.kotlin.stdlib) - api(libs.kotlin.reflect) - } - } } jvm { @@ -58,19 +44,6 @@ kotlin { } } -//fun DependencyHandlerScope.kspTest(dependencyNotation: Any): Unit { -// val exclude = setOf("commonTest", "nativeTest") -// add("kspMetadata", dependencyNotation) -// kotlin.sourceSets -// .filter { it.name !in exclude && it.name.contains("Test") } -// .forEach { -// val task = "ksp${it.name.capitalize()}" -// configurations.findByName(task)?.let { -// add(task, dependencyNotation) -// } -// } -//} - -//dependencies { -// kspTest(projects.arrowOpticsKspPlugin) -//} +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Copy.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Copy.kt index 87a21dfd257..3bfa3fd8e6a 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Copy.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Copy.kt @@ -8,9 +8,9 @@ public annotation class OpticsCopyMarker @OpticsCopyMarker public interface Copy { /** - * Changes the value of the element(s) pointed by the [Setter]. + * Changes the value of the element(s) pointed by the [Traversal]. */ - public infix fun Setter.set(b: B) + public infix fun Traversal.set(b: B) /** * Transforms the value of the element(s) pointed by the [Traversal]. @@ -46,7 +46,7 @@ public interface Copy { // mutable builder of copies private class CopyImpl(var current: A): Copy { - override fun Setter.set(b: B) { + override fun Traversal.set(b: B) { current = this.set(current, b) } override fun Traversal.transform(f: (B) -> B) { diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Every.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Every.kt index 561f6774b1c..cb772845b37 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Every.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Every.kt @@ -3,7 +3,6 @@ package arrow.optics import arrow.core.Either import arrow.core.NonEmptyList import arrow.core.Option -import arrow.core.Tuple10 import arrow.core.Tuple4 import arrow.core.Tuple5 import arrow.core.Tuple6 @@ -11,323 +10,316 @@ import arrow.core.Tuple7 import arrow.core.Tuple8 import arrow.core.Tuple9 import arrow.core.fold -import arrow.core.foldMap -import arrow.typeclasses.Monoid import kotlin.jvm.JvmStatic -public typealias Every = PEvery - -/** - * Composition of Fold and Traversal - * It combines their powers - */ -public interface PEvery : PTraversal, Fold, PSetter { - +public object Every { /** - * Map each target to a type R and use a Monoid to fold the results + * [Traversal] for [List] that focuses in each [A] of the source [List]. */ - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R + @JvmStatic + public fun list(): Traversal, A> = object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: List, map: (focus: A) -> R): R = + source.fold(initial) { acc, a -> combine(acc, map(a)) } - override fun modify(source: S, map: (focus: A) -> B): T + override fun modify(source: List, map: (focus: A) -> A): List = + source.map(map) + } /** - * Compose a [PEvery] with a [PEvery] + * [Traversal] for [Either] that has focus in each [Either.Right]. + * + * @receiver [PTraversal.Companion] to make it statically available. + * @return [Traversal] with source [Either] and focus every [Either.Right] of the source. */ - public infix fun compose(other: PEvery): PEvery = - object : PEvery { - override fun foldMap(M: Monoid, source: S, map: (C) -> R): R = - this@PEvery.foldMap(M, source) { c -> other.foldMap(M, c, map) } - - override fun modify(source: S, map: (focus: C) -> D): T = - this@PEvery.modify(source) { b -> other.modify(b, map) } - } - - public operator fun plus(other: PEvery): PEvery = - this compose other - - public companion object { - public fun from(T: Traversal, F: Fold): Every = - object : Every { - override fun foldMap(M: Monoid, source: S, map: (A) -> R): R = F.foldMap(M, source, map) - override fun modify(source: S, map: (focus: A) -> A): S = T.modify(source, map) - } - - /** - * [Traversal] for [List] that focuses in each [A] of the source [List]. - */ - @JvmStatic - public fun list(): Every, A> = - object : Every, A> { - override fun modify(source: List, map: (focus: A) -> A): List = - source.map(map) - - override fun foldMap(M: Monoid, source: List, map: (focus: A) -> R): R = - source.foldMap(M, map) - } - - /** - * [Traversal] for [Either] that has focus in each [Either.Right]. - * - * @return [Traversal] with source [Either] and focus every [Either.Right] of the source. - */ - @JvmStatic - public fun either(): Every, R> = - object : Every, R> { - override fun modify(source: Either, map: (focus: R) -> R): Either = - source.map(map) - - override fun foldMap(M: Monoid, source: Either, map: (focus: R) -> A): A = - source.fold({ M.empty() }, map) - } - - @JvmStatic - public fun map(): Every, V> = - object : Every, V> { - override fun modify(source: Map, map: (focus: V) -> V): Map = - source.mapValues { (_, v) -> map(v) } - - override fun foldMap(M: Monoid, source: Map, map: (focus: V) -> R): R = M.run { - source.fold(empty()) { acc, (_, v) -> acc.combine(map(v)) } - } - } - - /** - * [Traversal] for [NonEmptyList] that has focus in each [A]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [NonEmptyList] and focus every [A] of the source. - */ - @JvmStatic - public fun nonEmptyList(): Every, A> = - object : Every, A> { - override fun modify(source: NonEmptyList, map: (focus: A) -> A): NonEmptyList = - source.map(map) + @JvmStatic + public fun either(): Traversal, A> = object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Either, map: (focus: A) -> R): R = + source.fold({ initial }) { combine(initial, map(it)) } - override fun foldMap(M: Monoid, source: NonEmptyList, map: (focus: A) -> R): R = - source.foldMap(M, map) - } - - /** - * [Traversal] for [Option] that has focus in each [arrow.core.Some]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [Option] and focus in every [arrow.core.Some] of the source. - */ - @JvmStatic - public fun option(): Every, A> = - object : Every, A> { - override fun modify(source: Option, map: (focus: A) -> A): Option = - source.map(map) - - override fun foldMap(M: Monoid, source: Option, map: (focus: A) -> R): R = - source.fold({ M.empty() }, map) - } - - @JvmStatic - public fun sequence(): Every, A> = - object : Every, A> { - override fun modify(source: Sequence, map: (focus: A) -> A): Sequence = - source.map(map) - - override fun foldMap(M: Monoid, source: Sequence, map: (focus: A) -> R): R = - source.foldMap(M, map) - } - - /** - * [Traversal] for [String] that focuses in each [Char] of the source [String]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [String] and foci every [Char] in the source. - */ - @JvmStatic - public fun string(): Every = - object : Every { - override fun modify(source: String, map: (focus: Char) -> Char): String = - source.map(map).joinToString(separator = "") + override fun modify(source: Either, map: (focus: A) -> A): Either = + source.map(map) + } - override fun foldMap(M: Monoid, source: String, map: (focus: Char) -> R): R = M.run { - source.fold(empty()) { acc, char -> acc.combine(map(char)) } - } + @JvmStatic + public fun map(): Traversal, V> = object : Traversal, V> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Map, map: (focus: V) -> R): R = + source.fold(initial) { acc, (_, v) -> + combine(acc, map(v)) } - /** - * [Traversal] to focus into the first and second value of a [Pair] - */ - @JvmStatic - public fun pair(): Every, A> = - object : Every, A> { - override fun modify(source: Pair, map: (focus: A) -> A): Pair = - Pair(map(source.first), map(source.second)) + override fun modify(source: Map, map: (focus: V) -> V): Map = + source.mapValues { (_, v) -> map(v) } + } - override fun foldMap(M: Monoid, source: Pair, map: (focus: A) -> R): R = - listOf(source.first, source.second) - .foldMap(M, map) + /** + * [Traversal] for [NonEmptyList] that has focus in each [A]. + * + * @receiver [PTraversal.Companion] to make it statically available. + * @return [Traversal] with source [NonEmptyList] and focus every [A] of the source. + */ + @JvmStatic + public fun nonEmptyList(): Traversal, A> = object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: NonEmptyList, map: (focus: A) -> R): R = + source.fold(initial) { acc, a -> + combine(acc, map(a)) } - /** - * [Traversal] to focus into the first, second and third value of a [Triple] - */ - @JvmStatic - public fun triple(): Every, A> = - object : Every, A> { - override fun modify(source: Triple, map: (focus: A) -> A): Triple = - Triple(map(source.first), map(source.second), map(source.third)) + override fun modify(source: NonEmptyList, map: (focus: A) -> A): NonEmptyList = + source.map(map) + } - override fun foldMap(M: Monoid, source: Triple, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third) - .foldMap(M, map) - } + /** + * [Traversal] for [Option] that has focus in each [arrow.core.Some]. + * + * @receiver [PTraversal.Companion] to make it statically available. + * @return [Traversal] with source [Option] and focus in every [arrow.core.Some] of the source. + */ + @JvmStatic + public fun option(): Traversal, A> = object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Option, map: (focus: A) -> R): R = + source.fold({ initial }) { combine(initial, map(it)) } - /** - * [Traversal] to focus into the first, second, third and fourth value of a [arrow.core.Tuple4] - */ - @JvmStatic - public fun tuple4(): Every, A> = - object : Every, A> { - override fun modify(source: Tuple4, map: (focus: A) -> A): Tuple4 = - Tuple4(map(source.first), map(source.second), map(source.third), map(source.fourth)) + override fun modify(source: Option, map: (focus: A) -> A): Option = + source.map(map) + } - override fun foldMap(M: Monoid, source: Tuple4, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth) - .foldMap(M, map) + @JvmStatic + public fun sequence(): Traversal, A> = object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Sequence, map: (focus: A) -> R): R = + source.fold(initial) { acc, a -> + combine(acc, map(a)) } - /** - * [PTraversal] to focus into the first, second, third, fourth and fifth value of a [arrow.core.Tuple5] - */ - @JvmStatic - public fun tuple5(): Every, A> = - object : Every, A> { - override fun modify(source: Tuple5, map: (focus: A) -> A): Tuple5 = - Tuple5(map(source.first), map(source.second), map(source.third), map(source.fourth), map(source.fifth)) + override fun modify(source: Sequence, map: (focus: A) -> A): Sequence = + source.map(map) + } - override fun foldMap(M: Monoid, source: Tuple5, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth) - .foldMap(M, map) + /** + * [Traversal] for [String] that focuses in each [Char] of the source [String]. + * + * @receiver [PTraversal.Companion] to make it statically available. + * @return [Traversal] with source [String] and foci every [Char] in the source. + */ + @JvmStatic + public fun string(): Traversal = object : Traversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: String, map: (focus: Char) -> R): R = + source.fold(initial) { acc, a -> + combine(acc, map(a)) } - /** - * [Traversal] to focus into the first, second, third, fourth, fifth and sixth value of a [arrow.core.Tuple6] - */ - @JvmStatic - public fun tuple6(): Every, A> = - object : Every, A> { - override fun modify(source: Tuple6, map: (focus: A) -> A): Tuple6 = - Tuple6( - map(source.first), - map(source.second), - map(source.third), - map(source.fourth), - map(source.fifth), - map(source.sixth) - ) - - override fun foldMap(M: Monoid, source: Tuple6, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth, source.sixth) - .foldMap(M, map) - } + override fun modify(source: String, map: (focus: Char) -> Char): String = + source.map(map).joinToString(separator = "") + } - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth and seventh value of a [arrow.core.Tuple7] - */ - @JvmStatic - public fun tuple7(): Every, A> = - object : Every, A> { - override fun modify(source: Tuple7, map: (focus: A) -> A): Tuple7 = - Tuple7( - map(source.first), - map(source.second), - map(source.third), - map(source.fourth), - map(source.fifth), - map(source.sixth), - map(source.seventh) - ) + /** + * [Traversal] to focus into the first and second value of a [Pair] + */ + @JvmStatic + public fun pair(): Traversal, A> = + object : Traversal, A> { + override fun modify(source: Pair, map: (focus: A) -> A): Pair = + Pair(map(source.first), map(source.second)) + + override fun foldMap(initial: R, combine: (R, R) -> R, source: Pair, map: (focus: A) -> R): R = + combine(map(source.first), map(source.second)) + } - override fun foldMap(M: Monoid, source: Tuple7, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth, source.sixth, source.seventh) - .foldMap(M, map) - } + /** + * [Traversal] to focus into the first, second and third value of a [Triple] + */ + @JvmStatic + public fun triple(): Traversal, A> = + object : Traversal, A> { + override fun modify(source: Triple, map: (focus: A) -> A): Triple = + Triple(map(source.first), map(source.second), map(source.third)) + + override fun foldMap(initial: R, combine: (R, R) -> R, source: Triple, map: (focus: A) -> R): R = + combine(combine(map(source.first), map(source.second)), map(source.third)) + } - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh and eight value of a [arrow.core.Tuple8] - */ - @JvmStatic - public fun tuple8(): Every, A> = - object : Every, A> { - override fun modify( - source: Tuple8, - map: (focus: A) -> A - ): Tuple8 = - Tuple8( - map(source.first), - map(source.second), - map(source.third), - map(source.fourth), - map(source.fifth), - map(source.sixth), - map(source.seventh), - map(source.eighth) - ) + /** + * [Traversal] to focus into the first, second, third and fourth value of a [arrow.core.Tuple4] + */ + @JvmStatic + public fun tuple4(): Traversal, A> = + object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Tuple4, map: (focus: A) -> R): R = + combine(combine(combine(map(source.first), map(source.second)), map(source.third)), map(source.fourth)) + + override fun modify(source: Tuple4, map: (focus: A) -> A): Tuple4 = + Tuple4(map(source.first), map(source.second), map(source.third), map(source.fourth)) + } - override fun foldMap(M: Monoid, source: Tuple8, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth, source.sixth, source.seventh, source.eighth) - .foldMap(M, map) - } + /** + * [PTraversal] to focus into the first, second, third, fourth and fifth value of a [arrow.core.Tuple5] + */ + @JvmStatic + public fun tuple5(): Traversal, A> = + object : Traversal, A> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Tuple5, + map: (focus: A) -> R + ): R = + combine( + combine(combine(combine(map(source.first), map(source.second)), map(source.third)), map(source.fourth)), + map(source.fifth) + ) + + override fun modify(source: Tuple5, map: (focus: A) -> A): Tuple5 = + Tuple5(map(source.first), map(source.second), map(source.third), map(source.fourth), map(source.fifth)) + } - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight and ninth value of a [arrow.core.Tuple9] - */ - @JvmStatic - public fun tuple9(): Every, A> = - object : Every, A> { - override fun modify( - source: Tuple9, - map: (focus: A) -> A - ): Tuple9 = - Tuple9( - map(source.first), - map(source.second), - map(source.third), - map(source.fourth), - map(source.fifth), - map(source.sixth), - map(source.seventh), - map(source.eighth), - map(source.ninth) - ) + /** + * [Traversal] to focus into the first, second, third, fourth, fifth and sixth value of a [arrow.core.Tuple6] + */ + @JvmStatic + public fun tuple6(): Traversal, A> = + object : Traversal, A> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Tuple6, + map: (focus: A) -> R + ): R = + combine( + combine( + combine( + combine(combine(map(source.first), map(source.second)), map(source.third)), + map(source.fourth) + ), map(source.fifth) + ), map(source.sixth) + ) + + override fun modify(source: Tuple6, map: (focus: A) -> A): Tuple6 = + Tuple6( + map(source.first), + map(source.second), + map(source.third), + map(source.fourth), + map(source.fifth), + map(source.sixth) + ) + } - override fun foldMap(M: Monoid, source: Tuple9, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth, source.sixth, source.seventh, source.eighth, source.ninth) - .foldMap(M, map) - } + /** + * [Traversal] to focus into the first, second, third, fourth, fifth, sixth and seventh value of a [arrow.core.Tuple7] + */ + @JvmStatic + public fun tuple7(): Traversal, A> = + object : Traversal, A> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Tuple7, + map: (focus: A) -> R + ): R = + combine( + combine( + combine( + combine( + combine(combine(map(source.first), map(source.second)), map(source.third)), + map(source.fourth) + ), map(source.fifth) + ), map(source.sixth) + ), map(source.seventh) + ) + + override fun modify(source: Tuple7, map: (focus: A) -> A): Tuple7 = + Tuple7( + map(source.first), + map(source.second), + map(source.third), + map(source.fourth), + map(source.fifth), + map(source.sixth), + map(source.seventh) + ) + } - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10] - */ - @JvmStatic - public fun tuple10(): Every, A> = - object : Every, A> { - override fun modify( - source: Tuple10, - map: (focus: A) -> A - ): Tuple10 = - Tuple10( - map(source.first), - map(source.second), - map(source.third), - map(source.fourth), - map(source.fifth), - map(source.sixth), - map(source.seventh), - map(source.eighth), - map(source.ninth), - map(source.tenth) - ) + /** + * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh and eight value of a [arrow.core.Tuple8] + */ + @JvmStatic + public fun tuple8(): Traversal, A> = + object : Traversal, A> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Tuple8, + map: (focus: A) -> R + ): R = + combine( + combine( + combine( + combine( + combine( + combine(combine(map(source.first), map(source.second)), map(source.third)), + map(source.fourth) + ), map(source.fifth) + ), map(source.sixth) + ), map(source.seventh) + ), map(source.eighth) + ) + + override fun modify( + source: Tuple8, + map: (focus: A) -> A + ): Tuple8 = + Tuple8( + map(source.first), + map(source.second), + map(source.third), + map(source.fourth), + map(source.fifth), + map(source.sixth), + map(source.seventh), + map(source.eighth) + ) + } - override fun foldMap(M: Monoid, source: Tuple10, map: (focus: A) -> R): R = - listOf(source.first, source.second, source.third, source.fourth, source.fifth, source.sixth, source.seventh, source.eighth, source.ninth, source.tenth) - .foldMap(M, map) - } - } + /** + * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight and ninth value of a [arrow.core.Tuple9] + */ + @JvmStatic + public fun tuple9(): Traversal, A> = + object : Traversal, A> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Tuple9, + map: (focus: A) -> R + ): R = + combine( + combine( + combine( + combine( + combine( + combine( + combine(combine(map(source.first), map(source.second)), map(source.third)), + map(source.fourth) + ), map(source.fifth) + ), map(source.sixth) + ), map(source.seventh) + ), map(source.eighth) + ), map(source.ninth) + ) + + override fun modify( + source: Tuple9, + map: (focus: A) -> A + ): Tuple9 = + Tuple9( + map(source.first), + map(source.second), + map(source.third), + map(source.fourth), + map(source.fifth), + map(source.sixth), + map(source.seventh), + map(source.eighth), + map(source.ninth) + ) + } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Fold.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Fold.kt deleted file mode 100644 index 879be12d950..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Fold.kt +++ /dev/null @@ -1,322 +0,0 @@ -package arrow.optics - -import arrow.core.Either -import arrow.core.NonEmptyList -import arrow.core.Option -import arrow.core.Tuple10 -import arrow.core.Tuple4 -import arrow.core.Tuple5 -import arrow.core.Tuple6 -import arrow.core.Tuple7 -import arrow.core.Tuple8 -import arrow.core.Tuple9 -import arrow.core.foldMap -import arrow.core.identity -import arrow.typeclasses.Monoid -import arrow.typeclasses.MonoidDeprecation -import kotlin.jvm.JvmStatic - -/** - * A [Fold] is an optic that allows to focus into structure and get multiple results. - * - * [Fold] is a generalisation of an instance of [Foldable] and is implemented in terms of foldMap. - * - * @param S the source of a [Fold] - * @param A the target of a [Fold] - */ -public interface Fold { - - /** - * Map each target to a type [R] and combine the results as a fold. - */ - public fun foldMap(empty: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = - foldMap(object : Monoid { - override fun empty(): R = empty - override fun R.combine(b: R): R = combine(this, b) - }, source, map) - - /** - * Map each target to a type R and use a Monoid to fold the results - */ - @Deprecated(MonoidDeprecation, ReplaceWith("foldMap(M.empty(), M::combine, source, map)", "arrow.optics.foldMap", "arrow.typeclasses.combine")) - public fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R - - /** - * Calculate the number of targets - */ - public fun size(source: S): Int = - foldMap(0, { x, y -> x + y }, source) { 1 } - - /** - * Check if all targets satisfy the predicate - */ - public fun all(source: S, predicate: (focus: A) -> Boolean): Boolean = - foldMap(true, { x, y -> x && y }, source, predicate) - - /** - * Returns `true` if at least one focus matches the given [predicate]. - */ - public fun any(source: S, predicate: (focus: A) -> Boolean): Boolean = - foldMap(false, { x, y -> x || y }, source, predicate) - - /** - * Check if there is no target - */ - public fun isEmpty(source: S): Boolean = - foldMap(true, { _, _ -> false }, source) { false } - - /** - * Check if there is at least one target - */ - public fun isNotEmpty(source: S): Boolean = - !isEmpty(source) - - /** - * Get the first target or null - */ - public fun firstOrNull(source: S): A? = - EMPTY_VALUE.unbox(foldMap(EMPTY_VALUE, { x, y -> if (x === EMPTY_VALUE) y else x }, source, ::identity)) - - /** - * Get the last target or null - */ - public fun lastOrNull(source: S): A? = - EMPTY_VALUE.unbox(foldMap(EMPTY_VALUE, { x, y -> if (y != EMPTY_VALUE) y else x }, source, ::identity)) - - /** - * Fold using the given [empty] element and [combine]. - */ - public fun fold(empty: A, combine: (A, A) -> A, source: S): A = - foldMap(empty, combine, source, ::identity) - - /** - * Fold using the given [Monoid] instance. - */ - @Deprecated(MonoidDeprecation, ReplaceWith("fold(M.empty(), M::combine, source)", "arrow.optics.fold", "arrow.typeclasses.combine")) - public fun fold(M: Monoid, source: S): A = - foldMap(M, source, ::identity) - - /** - * Alias for fold. - */ - @Deprecated("use fold instead", ReplaceWith("fold(M, source)")) - public fun combineAll(M: Monoid, source: S): A = - fold(M, source) - - /** - * Get all targets of the [Fold] - */ - public fun getAll(source: S): List = - foldMap(emptyList(), { x, y -> x + y }, source) { listOf(it) } - - /** - * Find the first element matching the predicate, if one exists. - */ - public fun findOrNull(source: S, predicate: (focus: A) -> Boolean): A? = - EMPTY_VALUE.unbox( - foldMap(EMPTY_VALUE, { x, y -> if (x == EMPTY_VALUE) y else x }, source) { focus -> - if (predicate(focus)) focus else EMPTY_VALUE - } - ) - - /** - * Check whether at least one element satisfies the predicate. - * - * If there are no elements, the result is false. - */ - public fun exists(source: S, predicate: (focus: A) -> Boolean): Boolean = - any(source, predicate) - - /** - * Join two [Fold] with the same target - */ - public infix fun choice(other: Fold): Fold, A> = - object : Fold, A> { - override fun foldMap(M: Monoid, source: Either, map: (focus: A) -> R): R = - source.fold({ ac -> this@Fold.foldMap(M, ac, map) }, { c -> other.foldMap(M, c, map) }) - } - - /** - * Create a sum of the [Fold] and a type [C] - */ - public fun left(): Fold, Either> = - object : Fold, Either> { - override fun foldMap(M: Monoid, source: Either, map: (Either) -> R): R = - source.fold( - { a1: S -> this@Fold.foldMap(M, a1) { b -> map(Either.Left(b)) } }, - { c -> map(Either.Right(c)) }) - } - - /** - * Create a sum of a type [C] and the [Fold] - */ - public fun right(): Fold, Either> = - object : Fold, Either> { - override fun foldMap(M: Monoid, source: Either, map: (Either) -> R): R = - source.fold({ c -> map(Either.Left(c)) }, { a1 -> this@Fold.foldMap(M, a1) { b -> map(Either.Right(b)) } }) - } - - /** - * Compose a [Fold] with a [Fold] - */ - public infix fun compose(other: Fold): Fold = - object : Fold { - override fun foldMap(M: Monoid, source: S, map: (focus: C) -> R): R = - this@Fold.foldMap(M, source) { c -> other.foldMap(M, c, map) } - } - - public operator fun plus(other: Fold): Fold = - this compose other - - public companion object { - - public fun id(): Fold = - PIso.id() - - /** - * [Fold] that takes either [S] or [S] and strips the choice of [S]. - */ - public fun codiagonal(): Fold, S> = object : Fold, S> { - override fun foldMap(M: Monoid, source: Either, map: (S) -> R): R = - source.fold(map, map) - } - - /** - * Creates a [Fold] based on a predicate of the source [S] - */ - public fun select(p: (S) -> Boolean): Fold = object : Fold { - override fun foldMap(M: Monoid, source: S, map: (S) -> R): R = - if (p(source)) map(source) else M.empty() - } - - /** - * [Fold] that points to nothing - */ - public fun void(): Fold = - POptional.void() - - @JvmStatic - public fun iterable(): Fold, A> = - object : Fold, A> { - override fun foldMap(M: Monoid, source: Iterable, map: (focus: A) -> R): R = - source.foldMap(M, map) - } - - /** - * [Traversal] for [List] that focuses in each [A] of the source [List]. - */ - @JvmStatic - public fun list(): Fold, A> = - Every.list() - - /** - * [Traversal] for [Either] that has focus in each [Either.Right]. - * - * @return [Traversal] with source [Either] and focus every [Either.Right] of the source. - */ - @JvmStatic - public fun either(): Fold, R> = - Every.either() - - @JvmStatic - public fun map(): Fold, V> = - Every.map() - - /** - * [Traversal] for [NonEmptyList] that has focus in each [A]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [NonEmptyList] and focus every [A] of the source. - */ - @JvmStatic - public fun nonEmptyList(): Fold, A> = - Every.nonEmptyList() - - /** - * [Traversal] for [Option] that has focus in each [arrow.core.Some]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [Option] and focus in every [arrow.core.Some] of the source. - */ - @JvmStatic - public fun option(): Fold, A> = - Every.option() - - @JvmStatic - public fun sequence(): Fold, A> = - Every.sequence() - - /** - * [Traversal] for [String] that focuses in each [Char] of the source [String]. - * - * @receiver [PTraversal.Companion] to make it statically available. - * @return [Traversal] with source [String] and foci every [Char] in the source. - */ - @JvmStatic - public fun string(): Fold = - Every.string() - - /** - * [Traversal] to focus into the first and second value of a [Pair] - */ - @JvmStatic - public fun pair(): Fold, A> = - Every.pair() - - /** - * [Traversal] to focus into the first, second and third value of a [Triple] - */ - @JvmStatic - public fun triple(): Fold, A> = - Every.triple() - - /** - * [Traversal] to focus into the first, second, third and fourth value of a [arrow.core.Tuple4] - */ - @JvmStatic - public fun tuple4(): Fold, A> = - Every.tuple4() - - /** - * [PTraversal] to focus into the first, second, third, fourth and fifth value of a [arrow.core.Tuple5] - */ - @JvmStatic - public fun tuple5(): Fold, A> = - Every.tuple5() - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth and sixth value of a [arrow.core.Tuple6] - */ - @JvmStatic - public fun tuple6(): Fold, A> = - Every.tuple6() - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth and seventh value of a [arrow.core.Tuple7] - */ - @JvmStatic - public fun tuple7(): Fold, A> = - Every.tuple7() - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh and eight value of a [arrow.core.Tuple8] - */ - @JvmStatic - public fun tuple8(): Fold, A> = - Every.tuple8() - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight and ninth value of a [arrow.core.Tuple9] - */ - @JvmStatic - public fun tuple9(): Fold, A> = - Every.tuple9() - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10] - */ - @JvmStatic - public fun tuple10(): Fold, A> = - Every.tuple10() - } -} diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Getter.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Getter.kt deleted file mode 100644 index 7fa4469e60d..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Getter.kt +++ /dev/null @@ -1,89 +0,0 @@ -package arrow.optics - -import arrow.core.Either -import arrow.core.compose -import arrow.core.identity -import arrow.typeclasses.Monoid - -/** - * A [Getter] is an optic that allows to see into a structure and getting a focus. - * - * A [Getter] can be seen as a get function: - * - `get: (S) -> A` meaning we can look into an `S` and get an `A` - * - * @param S the source of a [Getter] - * @param A the focus of a [Getter] - */ -public fun interface Getter : Fold { - - /** - * Get the focus of a [Getter] - */ - public fun get(source: S): A - - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = - map(get(source)) - - /** - * Create a product of the [Getter] and a type [C] - */ - public fun first(): Getter, Pair> = - Getter { (s, c) -> get(s) to c } - - /** - * Create a product of type [C] and the [Getter] - */ - public fun second(): Getter, Pair> = - Getter { (c, s) -> c to get(s) } - - /** - * Create a sum of the [Getter] and type [C] - */ - override fun left(): Getter, Either> = - Getter { sc -> sc.mapLeft(this::get) } - - /** - * Create a sum of type [C] and the [Getter] - */ - override fun right(): Getter, Either> = - Getter { cs -> cs.map(this::get) } - - /** - * Join two [Getter] with the same focus - */ - public infix fun choice(other: Getter): Getter, A> = - Getter { s -> s.fold(this::get, other::get) } - - /** - * Pair two disjoint [Getter] - */ - public infix fun split(other: Getter): Getter, Pair> = - Getter { (s, c) -> get(s) to other.get(c) } - - /** - * Zip two [Getter] optics with the same source [S] - */ - public infix fun zip(other: Getter): Getter> = - Getter { s -> get(s) to other.get(s) } - - /** - * Compose a [Getter] with a [Getter] - */ - public infix fun compose(other: Getter): Getter = - Getter(other::get compose this::get) - - public operator fun plus(other: Getter): Getter = - this compose other - - public companion object { - - public fun id(): Getter = - PIso.id() - - /** - * [Getter] that takes either [S] or [S] and strips the choice of [S]. - */ - public fun codiagonal(): Getter, S> = - Getter { aa -> aa.fold(::identity, ::identity) } - } -} diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Iso.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Iso.kt index f7423abb52d..21f2f678eab 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Iso.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Iso.kt @@ -6,12 +6,7 @@ import arrow.core.None import arrow.core.Option import arrow.core.Either.Right import arrow.core.Some -import arrow.core.Validated -import arrow.core.Validated.Invalid -import arrow.core.Validated.Valid -import arrow.core.compose import arrow.core.identity -import arrow.typeclasses.Monoid import kotlin.jvm.JvmStatic /** @@ -40,8 +35,7 @@ private val stringToList: Iso> = * @param A the focus of a [PIso] * @param B the modified target of a [PIso] */ -public interface PIso : PPrism, PLens, Getter, POptional, - PSetter, Fold, PTraversal, PEvery { +public interface PIso : PPrism, PLens { /** * Get the focus of a [PIso] @@ -65,7 +59,7 @@ public interface PIso : PPrism, PLens, Gette override fun modify(source: S, map: (focus: A) -> B): T = reverseGet(map(get(source))) - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = map(get(source)) /** @@ -125,9 +119,8 @@ public interface PIso : PPrism, PLens, Gette * Compose a [PIso] with a [PIso] */ public infix fun compose(other: PIso): PIso = PIso( - other::get compose this::get, - this::reverseGet compose other::reverseGet - ) + { s -> other.get(get(s)) } + ) { d -> reverseGet(other.reverseGet(d)) } public operator fun plus(other: PIso): PIso = this compose other @@ -168,25 +161,6 @@ public interface PIso : PPrism, PLens, Gette public fun listToOptionNel(): Iso, Option>> = listToPOptionNel() - /** - * [PIso] that defines the equality between [Either] and [Validated] - */ - @JvmStatic - @Deprecated("Validated functionality is being merged into Either.\n Consider using `id` after migration.") - public fun eitherToPValidated(): PIso, Either, Validated, Validated> = - PIso( - get = { it.fold(::Invalid, ::Valid) }, - reverseGet = Validated::toEither - ) - - /** - * [Iso] that defines the equality between [Either] and [Validated] - */ - @JvmStatic - @Deprecated("Validated functionality is being merged into Either.\n Consider using `id` after migration.") - public fun eitherToValidated(): Iso, Validated> = - eitherToPValidated() - /** * [Iso] that defines the equality between a Unit value [Map] and a [Set] with its keys */ @@ -250,22 +224,5 @@ public interface PIso : PPrism, PLens, Gette @JvmStatic public fun stringToList(): Iso> = stringToList - - /** - * [PIso] that defines equality between [Validated] and [Either] - */ - @JvmStatic - public fun validatedToPEither(): PIso, Validated, Either, Either> = - PIso( - get = Validated::toEither, - reverseGet = Validated.Companion::fromEither - ) - - /** - * [Iso] that defines equality between [Validated] and [Either] - */ - @JvmStatic - public fun validatedToEither(): Iso, Either> = - validatedToPEither() } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Lens.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Lens.kt index 6912a35d6bd..aa054a7bf8e 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Lens.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Lens.kt @@ -3,7 +3,6 @@ package arrow.optics import arrow.core.Either import arrow.core.NonEmptyList import arrow.core.identity -import arrow.typeclasses.Monoid import kotlin.jvm.JvmStatic /** @@ -28,17 +27,16 @@ public typealias Lens = PLens * @param A the focus of a [PLens] * @param B the modified focus of a [PLens] */ -public interface PLens : Getter, POptional, PSetter, - PTraversal, PEvery { +public interface PLens : POptional { - override fun get(source: S): A + public fun get(source: S): A override fun set(source: S, focus: B): T override fun getOrModify(source: S): Either = Either.Right(get(source)) - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = map(get(source)) /** @@ -87,7 +85,7 @@ public interface PLens : Getter, POptional, PSette public companion object { - public fun id(): PIso = PIso.id() + public fun id(): Iso = PIso.id() /** * [PLens] that takes either [S] or [S] and strips the choice of [S]. @@ -211,5 +209,14 @@ public interface PLens : Getter, POptional, PSette @JvmStatic public fun tripleThird(): Lens, C> = triplePThird() + + /** + * Defines equality between String and [List] of [Char] + */ + @JvmStatic + public fun stringToList(): Lens> = PLens( + get = CharSequence::toList, + set = { _, ss -> ss.joinToString(separator = "") } + ) } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Optional.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Optional.kt index 5ccbb8d4b54..068f82cd1e2 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Optional.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Optional.kt @@ -9,7 +9,6 @@ import arrow.core.getOrElse import arrow.core.identity import arrow.core.prependTo import arrow.core.toOption -import arrow.typeclasses.Monoid import kotlin.jvm.JvmStatic /** @@ -39,10 +38,10 @@ public fun Optional(getOption: (source: S) -> Option, set: (source: S, * } * } * - * fun main(args: Array) { + * fun main() { * val original = User("arrow-user", None) * val set = User.email.set(original, "arRoW-UsEr@arrow-Kt.IO") - * val modified = User.email.modify(set, String::toLowerCase) + * val modified = User.email.modify(set, String::lowercase) * println("original: $original, set: $set, modified: $modified") * } * ``` @@ -60,7 +59,7 @@ public fun Optional(getOption: (source: S) -> Option, set: (source: S, * @param A the focus of a [POptional] * @param B the modified focus of a [POptional] */ -public interface POptional : PSetter, POptionalGetter, PTraversal, PEvery { +public interface POptional : PTraversal { /** * Get the modified source of a [POptional] @@ -70,10 +69,16 @@ public interface POptional : PSetter, POptionalGetter + public fun getOrModify(source: S): Either - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = - getOrModify(source).map(map).getOrElse { M.empty() } + /** + * Get the focus of an [Optional] or `null` if the is not there + */ + public fun getOrNull(source: S): A? = + getOrModify(source).getOrNull() + + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + getOrModify(source).map(map).getOrElse { initial } /** * Modify the focus of a [POptional] with a function [map] @@ -118,7 +123,7 @@ public interface POptional : PSetter, POptionalGetter first(): POptional, Pair, Pair, Pair> = + public fun first(): POptional, Pair, Pair, Pair> = POptional( { (source, c) -> getOrModify(source).mapLeft { Pair(it, c) }.map { Pair(it, c) } }, { (source, c2), (update, c) -> setNullable(source, update)?.let { Pair(it, c) } ?: Pair(set(source, update), c2) } @@ -127,7 +132,7 @@ public interface POptional : PSetter, POptionalGetter second(): POptional, Pair, Pair, Pair> = + public fun second(): POptional, Pair, Pair, Pair> = POptional( { (c, s) -> getOrModify(s).mapLeft { c to it }.map { c to it } }, { (c2, s), (c, b) -> setNullable(s, b)?.let { c to it } ?: (c2 to set(s, b)) } @@ -151,7 +156,7 @@ public interface POptional : PSetter, POptionalGetter id(): PIso = PIso.id() + public fun id(): Iso = PIso.id() /** * [POptional] that takes either [S] or [S] and strips the choice of [S]. @@ -200,10 +205,19 @@ public interface POptional : PSetter, POptionalGetter if (list.isNotEmpty()) list[0] prependTo newTail else emptyList() } ) + /** + * [Optional] to safely operate in a nullable value. + */ @JvmStatic public fun nullable(): Optional = Optional( getOption = { it.toOption() }, set = { source, new -> source?.let { new } } ) + + /** + * [Optional] to safely operate in a nullable value. + */ + @JvmStatic + public fun notNull(): Optional = nullable() } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/OptionalGetter.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/OptionalGetter.kt deleted file mode 100644 index efa0b790678..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/OptionalGetter.kt +++ /dev/null @@ -1,116 +0,0 @@ -package arrow.optics - -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import arrow.core.flatMap -import arrow.core.getOrElse -import arrow.typeclasses.Monoid -import kotlin.jvm.JvmStatic - -/** - * [OptionalGetter] is a type alias for [POptionalGetter] which fixes the type arguments - * and restricts the [POptionalGetter] to monomorphic updates. - */ -public typealias OptionalGetter = POptionalGetter - -public fun OptionalGetter(getOption: (source: S) -> Option): OptionalGetter = - POptionalGetter { s -> getOption(s).toEither { s } } - -/** - * An [OptionalGetter] is an optic that allows into a structure and querying an optional focus. - * - * @param S the source of a [POptional] - * @param T the modified source of a [POptional] - * @param A the focus of a [POptional] - */ -public interface POptionalGetter: Fold { - /** - * Get the focus of an [OptionalGetter] or return the original value while allowing the type to change if it does not match - */ - public fun getOrModify(source: S): Either - - /** - * Get the focus of an [OptionalGetter] or `null` if the is not there - */ - public fun getOrNull(source: S): A? = - getOrModify(source).getOrNull() - - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = - getOrModify(source).map(map).getOrElse { M.empty() } - - /** - * Join two [POptionalGetter] with the same focus - */ - public infix fun choice(other: POptionalGetter): POptionalGetter, Either, A> = - POptionalGetter { sources -> - sources.fold( - { leftSource -> - getOrModify(leftSource).mapLeft { Either.Left(it) } - }, - { rightSource -> - other.getOrModify(rightSource).mapLeft { Either.Right(it) } - } - ) - } - - /** - * Create a product of the [POptionalGetter] and a type [C] - */ - public fun first(): POptionalGetter, Pair, Pair> = - POptionalGetter { (source, c) -> getOrModify(source).mapLeft { Pair(it, c) }.map { Pair(it, c) } } - - /** - * Create a product of a type [C] and the [POptionalGetter] - */ - public fun second(): POptionalGetter, Pair, Pair> = - POptionalGetter { (c, s) -> getOrModify(s).mapLeft { c to it }.map { c to it } } - - /** - * Compose a [POptionalGetter] with a [POptionalGetter] - */ - public infix fun compose(other: POptionalGetter): POptionalGetter = - POptionalGetter { source -> - getOrModify(source).flatMap { a -> - other.getOrModify(a) - } - } - - public operator fun plus(other: POptionalGetter): POptionalGetter = - this compose other - - public companion object { - /** - * Invoke operator overload to create an [OptionalGetter] of type `S` with focus `A`. - */ - public operator fun invoke( - getOrModify: (source: S) -> Either - ): POptionalGetter = object : POptionalGetter { - override fun getOrModify(source: S): Either = getOrModify(source) - } - - public fun id(): PIso = PIso.id() - - /** - * [OptionalGetter] to itself if it satisfies the predicate. - * - * Select all the elements which satisfy the predicate. - * - * ```kotlin - * import arrow.optics.Traversal - * import arrow.optics.Optional - * - * val positiveNumbers = Traversal.list() compose OptionalGetter.filter { it >= 0 } - * - * positiveNumbers.getAll(listOf(1, 2, -3, 4, -5)) == listOf(1, 2, 4) - * ``` - */ - @JvmStatic - public fun filter(predicate: (A) -> Boolean): OptionalGetter = - OptionalGetter( - getOption = { if (predicate(it)) Some(it) else None } - ) - } -} - diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Prism.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Prism.kt index 96e420e9415..1807b1ed6a6 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Prism.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Prism.kt @@ -1,15 +1,15 @@ package arrow.optics import arrow.core.Either +import arrow.core.Either.Left +import arrow.core.Either.Right import arrow.core.None import arrow.core.Option import arrow.core.Some -import arrow.core.compose import arrow.core.flatMap import arrow.core.identity import arrow.core.left import arrow.core.right -import arrow.typeclasses.Monoid import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic @@ -35,14 +35,14 @@ public typealias Prism = PPrism * @param A the focus of a [PPrism] * @param B the modified focus of a [PPrism] */ -public interface PPrism : POptional, PSetter, POptionalGetter, PTraversal, PEvery { +public interface PPrism : POptional { override fun getOrModify(source: S): Either public fun reverseGet(focus: B): T - override fun foldMap(M: Monoid, source: S, map: (focus: A) -> R): R = - getOrNull(source)?.let(map) ?: M.empty() + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + getOrNull(source)?.let(map) ?: initial /** * Modify the focus of a [PPrism] with a function @@ -83,7 +83,7 @@ public interface PPrism : POptional, PSetter /** * Create a sum of the [PPrism] and a type [C] */ - override fun left(): PPrism, Either, Either, Either> = + public fun left(): PPrism, Either, Either, Either> = PPrism( { it.fold( @@ -92,8 +92,8 @@ public interface PPrism : POptional, PSetter }, { when (it) { - is Either.Left -> Either.Left(reverseGet(it.value)) - is Either.Right -> Either.Right(it.value) + is Left -> Left(reverseGet(it.value)) + is Right -> Right(it.value) } } ) @@ -101,7 +101,7 @@ public interface PPrism : POptional, PSetter /** * Create a sum of a type [C] and the [PPrism] */ - override fun right(): PPrism, Either, Either, Either> = + public fun right(): PPrism, Either, Either, Either> = PPrism( { it.fold( @@ -117,7 +117,7 @@ public interface PPrism : POptional, PSetter public infix fun compose(other: PPrism): PPrism = PPrism( getOrModify = { s -> getOrModify(s).flatMap { a -> other.getOrModify(a).mapLeft{ set(s, it) } } }, - reverseGet = this::reverseGet compose other::reverseGet + reverseGet = { reverseGet(other.reverseGet(it)) } ) public operator fun plus(other: PPrism): PPrism = @@ -125,7 +125,7 @@ public interface PPrism : POptional, PSetter public companion object { - public fun id(): PIso = PIso.id() + public fun id(): Iso = PIso.id() /** * Invoke operator overload to create a [PPrism] of type `S` with focus `A`. @@ -145,7 +145,7 @@ public interface PPrism : POptional, PSetter * A [PPrism] that checks for equality with a given value [a] */ public fun only(a: A, eq: (constant: A, other: A) -> Boolean = { aa, b -> aa == b }): Prism = Prism( - getOrModify = { a2 -> (if (eq(a, a2)) Either.Left(a) else Either.Right(Unit)) }, + getOrModify = { a2 -> (if (eq(a, a2)) Left(a) else Right(Unit)) }, reverseGet = { a } ) @@ -155,7 +155,7 @@ public interface PPrism : POptional, PSetter @JvmStatic public fun pSome(): PPrism, Option, A, B> = PPrism( - getOrModify = { option -> option.fold({ Either.Left(None) }, { Either.Right(it) }) }, + getOrModify = { option -> option.fold({ Left(None) }, ::Right) }, reverseGet = ::Some ) @@ -172,7 +172,7 @@ public interface PPrism : POptional, PSetter @JvmStatic public fun none(): Prism, Unit> = Prism( - getOrModify = { option -> option.fold({ Either.Right(Unit) }, { Either.Left(option) }) }, + getOrModify = { option -> option.fold({ Right(Unit) }, { Left(option) }) }, reverseGet = { _ -> None } ) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Setter.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Setter.kt deleted file mode 100644 index f6b607a4b90..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Setter.kt +++ /dev/null @@ -1,73 +0,0 @@ -package arrow.optics - -import arrow.core.Either - -/** - * [Setter] is a type alias for [PSetter] which fixes the type arguments - * and restricts the [PSetter] to monomorphic updates. - */ -public typealias Setter = PSetter - -/** - * A [Setter] is an optic that allows to see into a structure and set or modify its focus. - * - * A (polymorphic) [PSetter] is useful when setting or modifying a value for a constructed type - * i.e. PSetter, List, Int, String> - * - * A [PSetter] is a generalisation of a functor. - * Functor::map (fa: Kind, f: (A) -> B): Kind - * PSetter::modify(s: S, f: (A) -> B): T - * - * @param S the source of a [PSetter] - * @param T the modified source of a [PSetter] - * @param A the focus of a [PSetter] - * @param B the modified focus of a [PSetter] - */ -public fun interface PSetter { - - /** - * Modify polymorphically the focus of a [PSetter] with a function [map]. - */ - public fun modify(source: S, map: (focus: A) -> B): T - - /** - * Set polymorphically the focus of a [PSetter] with a value [focus]. - */ - public fun set(source: S, focus: B): T = - modify(source) { focus } - - /** - * Lift a function [map]: `(A) -> B to the context of `S`: `(S) -> T` - */ - public fun lift(map: (focus: A) -> B): (source: S) -> T = - { s -> modify(s) { map(it) } } - - /** - * Join two [PSetter] with the same target - */ - public infix fun choice(other: PSetter): PSetter, Either, A, B> = - PSetter { su, f -> - su.mapLeft { s -> modify(s, f) }.map { u -> other.modify(u, f) } - } - - /** - * Compose a [PSetter] with a [PSetter] - */ - public infix fun compose(other: PSetter): PSetter = - PSetter { s, fb -> modify(s) { a -> other.modify(a, fb) } } - - public operator fun plus(other: PSetter): PSetter = - this compose other - - public companion object { - - public fun id(): PSetter = - PIso.id() - - /** - * [PSetter] that takes either S or S and strips the choice of S. - */ - public fun codiagonal(): Setter, S> = - Setter { aa, f -> aa.mapLeft(f).map(f) } - } -} diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Traversal.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Traversal.kt index e58035b2b0a..dd37b22dd59 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Traversal.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/Traversal.kt @@ -3,13 +3,13 @@ package arrow.optics import arrow.core.Either import arrow.core.NonEmptyList import arrow.core.Option -import arrow.core.Tuple10 import arrow.core.Tuple4 import arrow.core.Tuple5 import arrow.core.Tuple6 import arrow.core.Tuple7 import arrow.core.Tuple8 import arrow.core.Tuple9 +import arrow.core.identity import kotlin.jvm.JvmStatic /** @@ -29,33 +29,156 @@ public typealias Traversal = PTraversal * @param A the target of a [PTraversal] * @param B the modified target of a [PTraversal] */ -public fun interface PTraversal : PSetter { +public interface PTraversal { - override fun modify(source: S, map: (focus: A) -> B): T + /** + * Map each target to a type R and use a Monoid to fold the results + */ + public fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R + + + /** + * Modify polymorphically the focus of a [PTraversal] with a function [map]. + */ + public fun modify(source: S, map: (focus: A) -> B): T + + /** + * Set polymorphically the focus of a [PTraversal] with a value [focus]. + */ + public fun set(source: S, focus: B): T = + modify(source) { focus } + + /** + * Lift a function [map]: `(A) -> B to the context of `S`: `(S) -> T` + */ + public fun lift(map: (focus: A) -> B): (source: S) -> T = + { s -> modify(s) { map(it) } } + /** + * Join two [PTraversal] with the same target + */ public fun choice(other: PTraversal): PTraversal, Either, A, B> = - PTraversal { s, f -> - s.fold( - { a -> Either.Left(this.modify(a, f)) }, - { u -> Either.Right(other.modify(u, f)) } + object : PTraversal, Either, A, B> { + override fun foldMap( + initial: R, + combine: (R, R) -> R, + source: Either, + map: (focus: A) -> R + ): R = source.fold( + { a -> this@PTraversal.foldMap(initial, combine, a, map) }, + { u -> other.foldMap(initial, combine, u, map) } ) + + override fun modify(source: Either, map: (focus: A) -> B): Either = + source.fold( + { a -> Either.Left(this@PTraversal.modify(a, map)) }, + { u -> Either.Right(other.modify(u, map)) } + ) } /** * Compose a [PTraversal] with a [PTraversal] */ public infix fun compose(other: PTraversal): PTraversal = - PTraversal { s, f -> this.modify(s) { b -> other.modify(b, f) } } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: C) -> R): R = + this@PTraversal.foldMap(initial, combine, source) { c -> other.foldMap(initial, combine, c, map) } + + override fun modify(source: S, map: (focus: C) -> D): T = + this@PTraversal.modify(source) { b -> other.modify(b, map) } + } public operator fun plus(other: PTraversal): PTraversal = this compose other + /** + * Calculate the number of targets + */ + public fun size(source: S): Int = + foldMap(0, Int::plus, source) { 1 } + + /** + * Check if all targets satisfy the predicate + */ + public fun all(source: S, predicate: (focus: A) -> Boolean): Boolean = + foldMap(true, Boolean::and, source, predicate) + + /** + * Returns `true` if at least one focus matches the given [predicate]. + */ + public fun any(source: S, predicate: (focus: A) -> Boolean): Boolean = + foldMap(false, Boolean::or, source, predicate) + + /** + * Check if there is no target + */ + public fun isEmpty(source: S): Boolean = + foldMap(true, { _, _ -> false }, source) { false } + + /** + * Check if there is at least one target + */ + public fun isNotEmpty(source: S): Boolean = + !isEmpty(source) + + /** + * Get the first target or null + */ + public fun firstOrNull(source: S): A? = + EMPTY_VALUE.unbox(foldMap(EMPTY_VALUE, { x, y -> if (x === EMPTY_VALUE) y else x }, source, ::identity)) + + /** + * Get the last target or null + */ + public fun lastOrNull(source: S): A? = + EMPTY_VALUE.unbox(foldMap(EMPTY_VALUE, { x, y -> if (y != EMPTY_VALUE) y else x }, source, ::identity)) + + /** + * Fold using the given [initial] value and [combine] function. + */ + public fun fold(initial: A, combine: (A, A) -> A, source: S): A = + foldMap(initial, combine, source, ::identity) + + /** + * Get all targets of the [Traversal] + */ + public fun getAll(source: S): List = + foldMap(emptyList(), { x, y -> x + y }, source) { listOf(it) } + + /** + * Find the first element matching the predicate, if one exists. + */ + public fun findOrNull(source: S, predicate: (focus: A) -> Boolean): A? = + EMPTY_VALUE.unbox( + foldMap(EMPTY_VALUE, { x, y -> if (x == EMPTY_VALUE) y else x }, source) { focus -> + if (predicate(focus)) focus else EMPTY_VALUE + } + ) + + /** + * Check whether at least one element satisfies the predicate. + * + * If there are no elements, the result is false. + */ + public fun exists(source: S, predicate: (focus: A) -> Boolean): Boolean = + any(source, predicate) + public companion object { - public fun id(): PTraversal = - PIso.id() + + public fun id(): Iso = PIso.id() public fun codiagonal(): Traversal, S> = - Traversal { s, f -> s.mapLeft(f).map(f) } + object : Traversal, S> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Either, map: (focus: S) -> R): R = + source.fold( + { a -> map(a) }, + { u -> map(u) } + ) + + override fun modify(source: Either, map: (focus: S) -> S): Either = + source.map(map).mapLeft(map) + } + // Traversal { s, f -> s.mapLeft(f).map(f) } /** * [PTraversal] that points to nothing @@ -66,8 +189,18 @@ public fun interface PTraversal : PSetter { /** * [PTraversal] constructor from multiple getters of the same source. */ - public operator fun invoke(get1: (S) -> A, get2: (S) -> A, set: (B, B, S) -> T): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), s) } + public operator fun invoke( + get1: (S) -> A, + get2: (S) -> A, + set: (B, B, S) -> T + ): PTraversal = + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine(map(get1(source)), map(get2(source))) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -75,7 +208,13 @@ public fun interface PTraversal : PSetter { get3: (S) -> A, set: (B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), s) } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine(combine(map(get1(source)), map(get2(source))), map(get3(source))) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -84,7 +223,13 @@ public fun interface PTraversal : PSetter { get4: (S) -> A, set: (B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), s) } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get4(source))) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), map(get4(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -94,7 +239,13 @@ public fun interface PTraversal : PSetter { get5: (S) -> A, set: (B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), s) } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get5(source))) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), map(get4(source)), map(get5(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -105,7 +256,13 @@ public fun interface PTraversal : PSetter { get6: (S) -> A, set: (B, B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), f(get6(s)), s) } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine(combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get5(source))), map(get6(source))) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), map(get4(source)), map(get5(source)), map(get6(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -117,7 +274,16 @@ public fun interface PTraversal : PSetter { get7: (S) -> A, set: (B, B, B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> set(f(get1(s)), f(get2(s)), f(get3(s)), f(get4(s)), f(get5(s)), f(get6(s)), f(get7(s)), s) } + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine( + combine(combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get5(source))), map(get6(source))), + map(get7(source)) + ) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), map(get4(source)), map(get5(source)), map(get6(source)), map(get7(source)), source) + } public operator fun invoke( get1: (S) -> A, @@ -130,18 +296,19 @@ public fun interface PTraversal : PSetter { get8: (S) -> A, set: (B, B, B, B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> - set( - f(get1(s)), - f(get2(s)), - f(get3(s)), - f(get4(s)), - f(get5(s)), - f(get6(s)), - f(get7(s)), - f(get8(s)), - s - ) + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine( + combine( + combine( + combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get5(source))), + map(get6(source)) + ), map(get7(source)) + ), map(get8(source)) + ) + + override fun modify(source: S, map: (focus: A) -> B): T = + set(map(get1(source)), map(get2(source)), map(get3(source)), map(get4(source)), map(get5(source)), map(get6(source)), map(get7(source)), map(get8(source)), source) } public operator fun invoke( @@ -156,19 +323,32 @@ public fun interface PTraversal : PSetter { get9: (S) -> A, set: (B, B, B, B, B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> - set( - f(get1(s)), - f(get2(s)), - f(get3(s)), - f(get4(s)), - f(get5(s)), - f(get6(s)), - f(get7(s)), - f(get8(s)), - f(get9(s)), - s - ) + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine( + combine( + combine( + combine( + combine(combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), map(get5(source))), + map(get6(source)) + ), map(get7(source)) + ), map(get8(source)) + ), map(get9(source)) + ) + + override fun modify(source: S, map: (focus: A) -> B): T = + set( + map(get1(source)), + map(get2(source)), + map(get3(source)), + map(get4(source)), + map(get5(source)), + map(get6(source)), + map(get7(source)), + map(get8(source)), + map(get9(source)), + source + ) } public operator fun invoke( @@ -184,20 +364,37 @@ public fun interface PTraversal : PSetter { get10: (S) -> A, set: (B, B, B, B, B, B, B, B, B, B, S) -> T ): PTraversal = - PTraversal { s, f -> - set( - f(get1(s)), - f(get2(s)), - f(get3(s)), - f(get4(s)), - f(get5(s)), - f(get6(s)), - f(get7(s)), - f(get8(s)), - f(get9(s)), - f(get10(s)), - s - ) + object : PTraversal { + override fun foldMap(initial: R, combine: (R, R) -> R, source: S, map: (focus: A) -> R): R = + combine( + combine( + combine( + combine( + combine( + combine( + combine(combine(map(get1(source)), map(get2(source))), map(get3(source))), + map(get5(source)) + ), map(get6(source)) + ), map(get7(source)) + ), map(get8(source)) + ), map(get9(source)) + ), map(get10(source)) + ) + + override fun modify(source: S, map: (focus: A) -> B): T = + set( + map(get1(source)), + map(get2(source)), + map(get3(source)), + map(get4(source)), + map(get5(source)), + map(get6(source)), + map(get7(source)), + map(get8(source)), + map(get9(source)), + map(get10(source)), + source + ) } /** @@ -210,6 +407,7 @@ public fun interface PTraversal : PSetter { /** * [Traversal] for [Either] that has focus in each [Either.Right]. * + * @receiver [PTraversal.Companion] to make it statically available. * @return [Traversal] with source [Either] and focus every [Either.Right] of the source. */ @JvmStatic @@ -426,30 +624,5 @@ public fun interface PTraversal : PSetter { public fun tuple9(): Traversal, A> = pTuple9() - /** - * [PTraversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10] - */ - @JvmStatic - public fun pTuple10(): PTraversal, Tuple10, A, B> = - PTraversal( - get1 = { it.first }, - get2 = { it.second }, - get3 = { it.third }, - get4 = { it.fourth }, - get5 = { it.fifth }, - get6 = { it.sixth }, - get7 = { it.seventh }, - get8 = { it.eighth }, - get9 = { it.ninth }, - get10 = { it.tenth }, - set = { a, b, c, d, e, f, g, h, i, j, _ -> Tuple10(a, b, c, d, e, f, g, h, i, j) } - ) - - /** - * [Traversal] to focus into the first, second, third, fourth, fifth, sixth, seventh, eight, ninth and tenth value of a [arrow.core.Tuple10] - */ - @JvmStatic - public fun tuple10(): Traversal, A> = - pTuple10() } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/at.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/at.kt index 5b8f6e8f7a3..4ea746447b1 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/at.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/at.kt @@ -1,12 +1,8 @@ package arrow.optics.dsl -import arrow.optics.Fold -import arrow.optics.Getter -import arrow.optics.Iso import arrow.optics.Lens import arrow.optics.Optional import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal import arrow.optics.typeclasses.At @@ -14,78 +10,28 @@ import arrow.optics.typeclasses.At * DSL to compose [At] with a [Lens] for a structure [S] to focus in on [A] at given index [I]. * * @receiver [Lens] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] + * @param at [At] instance to provide a [Lens] to zoom into [S] at [I] * @param i index [I] to zoom into [S] and find focus [A] * @return [Lens] with a focus in [A] at given index [I]. */ -public fun Lens.at(AT: At, i: I): Lens = this.compose(AT.at(i)) - -/** - * DSL to compose [At] with an [Iso] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Iso] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Lens] with a focus in [A] at given index [I]. - */ -public fun Iso.at(AT: At, i: I): Lens = this.compose(AT.at(i)) - -/** - * DSL to compose [At] with a [Prism] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Prism] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ -public fun Prism.at(AT: At, i: I): Optional = this.compose(AT.at(i)) +public fun Lens.at(at: At, i: I): Lens = this.compose(at.at(i)) /** * DSL to compose [At] with an [Optional] for a structure [S] to focus in on [A] at given index [I]. * - * @receiver [Optional] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] + * @receiver [Optional] or [Prism] with a focus in [S] + * @param at [At] instance to provide a [Lens] to zoom into [S] at [I] * @param i index [I] to zoom into [S] and find focus [A] * @return [Optional] with a focus in [A] at given index [I]. */ -public fun Optional.at(AT: At, i: I): Optional = this.compose(AT.at(i)) - -/** - * DSL to compose [At] with a [Getter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Getter] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Getter] with a focus in [A] at given index [I]. - */ -public fun Getter.at(AT: At, i: I): Getter = this.compose(AT.at(i)) - -/** - * DSL to compose [At] with a [Setter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Setter] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Setter] with a focus in [A] at given index [I]. - */ -public fun Setter.at(AT: At, i: I): Setter = this.compose(AT.at(i)) +public fun Optional.at(at: At, i: I): Optional = this.compose(at.at(i)) /** * DSL to compose [At] with a [Traversal] for a structure [S] to focus in on [A] at given index [I]. * * @receiver [Traversal] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] + * @param at [At] instance to provide a [Lens] to zoom into [S] at [I] * @param i index [I] to zoom into [S] and find focus [A] * @return [Traversal] with a focus in [A] at given index [I]. */ -public fun Traversal.at(AT: At, i: I): Traversal = this.compose(AT.at(i)) - -/** - * DSL to compose [At] with a [Fold] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Fold] with a focus in [S] - * @param AT [At] instance to provide a [Lens] to zoom into [S] at [I] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Fold] with a focus in [A] at given index [I]. - */ -public fun Fold.at(AT: At, i: I): Fold = this.compose(AT.at(i)) +public fun Traversal.at(at: At, i: I): Traversal = this.compose(at.at(i)) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/every.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/every.kt index 3816731e952..4cb645f8ed3 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/every.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/every.kt @@ -1,73 +1,12 @@ package arrow.optics.dsl -import arrow.optics.Every -import arrow.optics.Fold -import arrow.optics.Iso -import arrow.optics.Lens -import arrow.optics.Optional -import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal -/** - * DSL to compose [Traversal] with a [Lens] for a structure [S] to see all its foci [A] - * - * @receiver [Lens] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Traversal] with a focus in [A] - */ -public fun Lens.every(TR: Every): Every = this.compose(TR) - -/** - * DSL to compose [Traversal] with an [Iso] for a structure [S] to see all its foci [A] - * - * @receiver [Iso] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Traversal] with a focus in [A] - */ -public fun Iso.every(TR: Every): Every = this.compose(TR) - -/** - * DSL to compose [Traversal] with a [Prism] for a structure [S] to see all its foci [A] - * - * @receiver [Prism] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Traversal] with a focus in [A] - */ -public fun Prism.every(TR: Every): Every = this.compose(TR) - -/** - * DSL to compose [Traversal] with an [Optional] for a structure [S] to see all its foci [A] - * - * @receiver [Optional] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Traversal] with a focus in [A] - */ -public fun Optional.every(TR: Every): Every = this.compose(TR) - -/** - * DSL to compose [Traversal] with a [Setter] for a structure [S] to see all its foci [A] - * - * @receiver [Setter] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Setter] with a focus in [A] - */ -public fun Setter.every(TR: Every): Setter = this.compose(TR) - /** * DSL to compose [Traversal] with a [Traversal] for a structure [S] to see all its foci [A] * * @receiver [Traversal] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] + * @param tr [Traversal] that can focus into a structure [S] to see all its foci [A] * @return [Traversal] with a focus in [A] */ -public fun Traversal.every(TR: Every): Traversal = this.compose(TR) - -/** - * DSL to compose [Traversal] with a [Fold] for a structure [S] to see all its foci [A] - * - * @receiver [Fold] with a focus in [S] - * @param TR [Traversal] that can focus into a structure [S] to see all its foci [A] - * @return [Fold] with a focus in [A] - */ -public fun Fold.every(TR: Every): Fold = this.compose(TR) +public fun Traversal.every(tr: Traversal): Traversal = this.compose(tr) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/index.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/index.kt index c9682f8066c..ca7ff58db85 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/index.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/index.kt @@ -1,80 +1,27 @@ package arrow.optics.dsl -import arrow.optics.Fold -import arrow.optics.Iso import arrow.optics.Lens import arrow.optics.Optional import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal import arrow.optics.typeclasses.Index -/** - * DSL to compose [Index] with a [Lens] for a structure [S] to focus in on [A] at given index [I] - * - * @receiver [Lens] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I] - */ -public fun Lens.index(ID: Index, i: I): Optional = this.compose(ID.index(i)) - -/** - * DSL to compose [Index] with an [Iso] for a structure [S] to focus in on [A] at given index [I] - * - * @receiver [Iso] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I] - */ -public fun Iso.index(ID: Index, i: I): Optional = this.compose(ID.index(i)) - -/** - * DSL to compose [Index] with a [Prism] for a structure [S] to focus in on [A] at given index [I] - * - * @receiver [Prism] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I] - */ -public fun Prism.index(ID: Index, i: I): Optional = this.compose(ID.index(i)) - /** * DSL to compose [Index] with an [Optional] for a structure [S] to focus in on [A] at given index [I] * - * @receiver [Optional] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] + * @receiver [Optional], [Lens], or [Prism] with a focus in [S] + * @param idx [Index] instance to provide a [Optional] to focus into [S] at [I] * @param i index [I] to focus into [S] and find focus [A] * @return [Optional] with a focus in [A] at given index [I] */ -public fun Optional.index(ID: Index, i: I): Optional = this.compose(ID.index(i)) - -/** - * DSL to compose [Index] with a [Setter] for a structure [S] to focus in on [A] at given index [I] - * - * @receiver [Setter] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Setter] with a focus in [A] at given index [I]. - */ -public fun Setter.index(ID: Index, i: I): Setter = this.compose(ID.index(i)) +public fun Optional.index(idx: Index, i: I): Optional = this.compose(idx.index(i)) /** * DSL to compose [Index] with a [Traversal] for a structure [S] to focus in on [A] at given index [I] * * @receiver [Traversal] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] + * @param idx [Index] instance to provide a [Optional] to focus into [S] at [I] * @param i index [I] to focus into [S] and find focus [A] * @return [Traversal] with a focus in [A] at given index [I]. */ -public fun Traversal.index(ID: Index, i: I): Traversal = this.compose(ID.index(i)) - -/** - * DSL to compose [Index] with a [Fold] for a structure [S] to focus in on [A] at given index [I] - * - * @receiver [Fold] with a focus in [S] - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Fold] with a focus in [A] at given index [I]. - */ -public fun Fold.index(ID: Index, i: I): Fold = this.compose(ID.index(i)) +public fun Traversal.index(idx: Index, i: I): Traversal = this.compose(idx.index(i)) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/nullable.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/nullable.kt new file mode 100644 index 00000000000..af5d3c1df6b --- /dev/null +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/nullable.kt @@ -0,0 +1,23 @@ +package arrow.optics.dsl + +import arrow.optics.Lens +import arrow.optics.Optional +import arrow.optics.POptional +import arrow.optics.Prism +import arrow.optics.Traversal + +/** + * DSL to compose an [Optional] with focus on a nullable type with [notNull]. + * + * @receiver [Optional], [Lens], or [Prism] with a focus in <[S]?> + * @return [Optional] with a focus in [S] + */ +public inline val Optional.notNull: Optional inline get() = this.compose(POptional.notNull()) + +/** + * DSL to compose a [Traversal] with focus on a nullable type with [notNull]. + * + * @receiver [Traversal] with a focus in <[S]?> + * @return [Traversal] with a focus in [S] + */ +public inline val Traversal.notNull: Traversal inline get() = this.compose(POptional.notNull()) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/option.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/option.kt index 64a45d2e3be..18239669eae 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/option.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/dsl/option.kt @@ -1,54 +1,19 @@ package arrow.optics.dsl import arrow.core.Option -import arrow.optics.Fold -import arrow.optics.Iso import arrow.optics.Lens import arrow.optics.Optional import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal -/** - * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Lens] with a focus of [Option]<[S]> - * - * @receiver [Lens] with a focus in [Option]<[S]> - * @return [Optional] with a focus in [S] - */ -public inline val Lens>.some: Optional inline get() = this.compose(Prism.some()) - -/** - * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Iso] with a focus of [Option]<[S]> - * - * @receiver [Iso] with a focus in [Option]<[S]> - * @return [Prism] with a focus in [S] - */ -public inline val Iso>.some: Prism inline get() = this.compose(Prism.some()) - -/** - * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Prism] with a focus of [Option]<[S]> - * - * @receiver [Prism] with a focus in [Option]<[S]> - * @return [Prism] with a focus in [S] - */ -public inline val Prism>.some: Prism inline get() = this.compose(Prism.some()) - /** * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Optional] with a focus of [Option]<[S]> * - * @receiver [Optional] with a focus in [Option]<[S]> + * @receiver [Optional], [Lens], or [Prism] with a focus in [Option]<[S]> * @return [Optional] with a focus in [S] */ public inline val Optional>.some: Optional inline get() = this.compose(Prism.some()) -/** - * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Setter] with a focus of [Option]<[S]> - * - * @receiver [Setter] with a focus in [Option]<[S]> - * @return [Setter] with a focus in [S] - */ -public inline val Setter>.some: Setter inline get() = this.compose(Prism.some()) - /** * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Traversal] with a focus of [Option]<[S]> * @@ -56,11 +21,3 @@ public inline val Setter>.some: Setter inline get() = * @return [Traversal] with a focus in [S] */ public inline val Traversal>.some: Traversal inline get() = this.compose(Prism.some()) - -/** - * DSL to compose a [Prism] with focus [arrow.core.Some] with a [Fold] with a focus of [Option]<[S]> - * - * @receiver [Fold] with a focus in [Option]<[S]> - * @return [Fold] with a focus in [S] - */ -public inline val Fold>.some: Fold inline get() = this.compose(Prism.some()) diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/At.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/At.kt index 4f3dee12bd5..9f96d1648b7 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/At.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/At.kt @@ -2,14 +2,9 @@ package arrow.optics.typeclasses import arrow.core.None import arrow.core.Option -import arrow.optics.Fold -import arrow.optics.Getter -import arrow.optics.Iso import arrow.optics.Lens import arrow.optics.Optional import arrow.optics.PLens -import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal import kotlin.jvm.JvmStatic @@ -37,27 +32,7 @@ public fun interface At { * @param i index [I] to zoom into [S] and find focus [A] * @return [Lens] with a focus in [A] at given index [I]. */ - public fun Lens.at(i: I): Lens = - this@at.compose(this@At.at(i)) - - /** - * DSL to compose [At] with an [Iso] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Iso] with a focus in [S] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Lens] with a focus in [A] at given index [I]. - */ - public fun Iso.at(i: I): Lens = - this.compose(this@At.at(i)) - - /** - * DSL to compose [At] with a [Prism] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Prism] with a focus in [S] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public fun Prism.at(i: I): Optional = this.compose(this@At.at(i)) + public fun Lens.at(i: I): Lens = this@at.compose(this@At.at(i)) /** * DSL to compose [At] with an [Optional] for a structure [S] to focus in on [A] at given index [I]. @@ -68,24 +43,6 @@ public fun interface At { */ public fun Optional.at(i: I): Optional = this.compose(this@At.at(i)) - /** - * DSL to compose [At] with a [Getter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Getter] with a focus in [S] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Getter] with a focus in [A] at given index [I]. - */ - public fun Getter.at(i: I): Getter = this.compose(this@At.at(i)) - - /** - * DSL to compose [At] with a [Setter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Setter] with a focus in [S] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Setter] with a focus in [A] at given index [I]. - */ - public fun Setter.at(i: I): Setter = this.compose(this@At.at(i)) - /** * DSL to compose [At] with a [Traversal] for a structure [S] to focus in on [A] at given index [I]. * @@ -95,27 +52,8 @@ public fun interface At { */ public fun Traversal.at(i: I): Traversal = this.compose(this@At.at(i)) - /** - * DSL to compose [At] with a [Fold] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Fold] with a focus in [S] - * @param i index [I] to zoom into [S] and find focus [A] - * @return [Fold] with a focus in [A] at given index [I]. - */ - public fun Fold.at(i: I): Fold = this.compose(this@At.at(i)) - public companion object { - /** - * Lift an instance of [At] using an [Iso]. - * - * @param AT [At] that can provide [Lens] for a structure [U] with a focus in [A] with given index [I]. - * @param iso [Iso] that defines an isomorphism between [S] and [U] - * @return [At] to provide [Lens] for structure [S] with focus in [A] at given index [I] - */ - public fun fromIso(AT: At, iso: Iso): At = - At { i -> iso compose AT.at(i) } - @JvmStatic public fun map(): At, K, Option> = At { i -> diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Cons.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Cons.kt index 47883f600cc..7d14d5d36dc 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Cons.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Cons.kt @@ -2,7 +2,6 @@ package arrow.optics.typeclasses import arrow.core.left import arrow.core.right -import arrow.optics.Iso import arrow.optics.Optional import arrow.optics.PLens import arrow.optics.PPrism @@ -53,12 +52,6 @@ public fun interface Cons { public companion object { - /** - * Lift an instance of [Cons] using an [Iso]. - */ - public fun fromIso(C: Cons, iso: Iso): Cons = - Cons { iso compose C.cons() compose iso.reverse().second() } - public operator fun invoke(prism: Prism>): Cons = Cons { prism } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/FilterIndex.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/FilterIndex.kt index 16c0d920bc6..90fb95731ab 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/FilterIndex.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/FilterIndex.kt @@ -4,8 +4,8 @@ import arrow.core.NonEmptyList import arrow.core.Predicate import arrow.core.toNonEmptyListOrNull import arrow.optics.Every -import arrow.optics.Iso -import arrow.typeclasses.Monoid +import arrow.optics.PLens +import arrow.optics.Traversal import kotlin.jvm.JvmStatic /** @@ -20,26 +20,19 @@ public fun interface FilterIndex { /** * Filter the foci [A] of a [Every] with the predicate [p]. */ - public fun filter(p: Predicate): Every + public fun filter(p: Predicate): Traversal public companion object { - /** - * Lift an instance of [FilterIndex] using an [Iso] - */ - public fun fromIso(FI: FilterIndex, iso: Iso): FilterIndex = - FilterIndex { p -> iso compose FI.filter(p) } - /** * [FilterIndex] instance definition for [List]. */ @JvmStatic public fun list(): FilterIndex, Int, A> = FilterIndex { p -> - object : Every, A> { - override fun foldMap(M: Monoid, source: List, map: (A) -> R): R = M.run { - source.foldIndexed(empty()) { index, acc, a -> if (p(index)) acc.combine(map(a)) else acc } - } + object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: List, map: (A) -> R): R = + source.foldIndexed(initial) { index, acc, a -> if (p(index)) combine(acc, map(a)) else acc } override fun modify(source: List, map: (focus: A) -> A): List = source.mapIndexed { index, a -> if (p(index)) map(a) else a } @@ -49,12 +42,11 @@ public fun interface FilterIndex { @JvmStatic public fun map(): FilterIndex, K, V> = FilterIndex { p -> - object : Every, V> { - override fun foldMap(M: Monoid, source: Map, map: (V) -> R): R = M.run { - source.entries.fold(empty()) { acc, (k, v) -> - if (p(k)) acc.combine(map(v)) else acc + object : Traversal, V> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Map, map: (V) -> R): R = + source.entries.fold(initial) { acc, (k, v) -> + if (p(k)) combine(acc, map(v)) else acc } - } override fun modify(source: Map, map: (focus: V) -> V): Map = source.mapValues { (k, v) -> if (p(k)) map(v) else v } @@ -67,12 +59,11 @@ public fun interface FilterIndex { @JvmStatic public fun nonEmptyList(): FilterIndex, Int, A> = FilterIndex { p -> - object : Every, A> { - override fun foldMap(M: Monoid, source: NonEmptyList, map: (A) -> R): R = M.run { - source.foldIndexed(empty()) { index, acc, r -> - if (p(index)) acc.combine(map(r)) else acc + object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: NonEmptyList, map: (A) -> R): R = + source.foldIndexed(initial) { index, acc, r -> + if (p(index)) combine(acc, map(r)) else acc } - } override fun modify(source: NonEmptyList, map: (focus: A) -> A): NonEmptyList = source.mapIndexed { index, a -> if (p(index)) map(a) else a }.toNonEmptyListOrNull() @@ -83,12 +74,11 @@ public fun interface FilterIndex { @JvmStatic public fun sequence(): FilterIndex, Int, A> = FilterIndex { p -> - object : Every, A> { - override fun foldMap(M: Monoid, source: Sequence, map: (A) -> R): R = M.run { - source.foldIndexed(empty()) { index, acc, a -> - if (p(index)) acc.combine(map(a)) else acc + object : Traversal, A> { + override fun foldMap(initial: R, combine: (R, R) -> R, source: Sequence, map: (A) -> R): R = + source.foldIndexed(initial) { index, acc, a -> + if (p(index)) combine(acc, map(a)) else acc } - } override fun modify(source: Sequence, map: (focus: A) -> A): Sequence = source.mapIndexed { index, a -> if (p(index)) map(a) else a } @@ -105,7 +95,7 @@ public fun interface FilterIndex { @JvmStatic public fun string(): FilterIndex = FilterIndex { p -> - Iso.stringToList() compose list().filter(p) + PLens.stringToList() compose list().filter(p) } } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Index.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Index.kt index 3b03e8dbd31..a8c4a2bb22f 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Index.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Index.kt @@ -4,13 +4,9 @@ import arrow.core.NonEmptyList import arrow.core.left import arrow.core.right import arrow.core.toNonEmptyListOrNull -import arrow.optics.Fold -import arrow.optics.Iso -import arrow.optics.Lens import arrow.optics.Optional +import arrow.optics.PLens import arrow.optics.POptional -import arrow.optics.Prism -import arrow.optics.Setter import arrow.optics.Traversal import kotlin.jvm.JvmStatic @@ -31,33 +27,6 @@ public fun interface Index { */ public fun index(i: I): Optional - /** - * DSL to compose [Index] with a [Lens] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Lens] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public fun Lens.index(i: I): Optional = this.compose(this@Index.index(i)) - - /** - * DSL to compose [Index] with an [Iso] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Iso] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public fun Iso.index(i: I): Optional = this.compose(this@Index.index(i)) - - /** - * DSL to compose [Index] with a [Prism] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Prism] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public fun Prism.index(i: I): Optional = this.compose(this@Index.index(i)) - /** * DSL to compose [Index] with an [Optional] for a structure [S] to focus in on [A] at given index [I]. * @@ -67,15 +36,6 @@ public fun interface Index { */ public fun Optional.index(i: I): Optional = this.compose(this@Index.index(i)) - /** - * DSL to compose [Index] with a [Setter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Setter] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Setter] with a focus in [A] at given index [I]. - */ - public fun Setter.index(i: I): Setter = this.compose(this@Index.index(i)) - /** * DSL to compose [Index] with a [Traversal] for a structure [S] to focus in on [A] at given index [I]. * @@ -85,42 +45,6 @@ public fun interface Index { */ public fun Traversal.index(i: I): Traversal = this.compose(this@Index.index(i)) - /** - * DSL to compose [Index] with a [Fold] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Fold] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Fold] with a focus in [A] at given index [I]. - */ - public fun Fold.index(i: I): Fold = this.compose(this@Index.index(i)) - - /** - * DSL to compose [Index] with a [Lens] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Lens] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public operator fun Lens.get(i: I): Optional = this.compose(this@Index.index(i)) - - /** - * DSL to compose [Index] with an [Iso] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Iso] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public operator fun Iso.get(i: I): Optional = this.compose(this@Index.index(i)) - - /** - * DSL to compose [Index] with a [Prism] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Prism] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Optional] with a focus in [A] at given index [I]. - */ - public operator fun Prism.get(i: I): Optional = this.compose(this@Index.index(i)) - /** * DSL to compose [Index] with an [Optional] for a structure [S] to focus in on [A] at given index [I]. * @@ -130,15 +54,6 @@ public fun interface Index { */ public operator fun Optional.get(i: I): Optional = this.compose(this@Index.index(i)) - /** - * DSL to compose [Index] with a [Setter] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Setter] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Setter] with a focus in [A] at given index [I]. - */ - public operator fun Setter.get(i: I): Setter = this.compose(this@Index.index(i)) - /** * DSL to compose [Index] with a [Traversal] for a structure [S] to focus in on [A] at given index [I]. * @@ -148,25 +63,7 @@ public fun interface Index { */ public operator fun Traversal.get(i: I): Traversal = this.compose(this@Index.index(i)) - /** - * DSL to compose [Index] with a [Fold] for a structure [S] to focus in on [A] at given index [I]. - * - * @receiver [Fold] with a focus in [S] - * @param i index [I] to focus into [S] and find focus [A] - * @return [Fold] with a focus in [A] at given index [I]. - */ - public operator fun Fold.get(i: I): Fold = this.compose(this@Index.index(i)) - public companion object { - /** - * Lift an instance of [Index] using an [Iso]. - * - * @param ID [Index] instance to provide a [Optional] to focus into [S] at [I] - * @param iso [Iso] that defines an isomorphism between a type [S] and [A] - * @return [Index] for a structure [S] to focus in an optional [A] at a given index [I] - */ - public fun fromIso(ID: Index, iso: Iso): Index = - Index { i -> iso compose ID.index(i) } /** * [Index] instance definition for [List]. @@ -224,7 +121,7 @@ public fun interface Index { @JvmStatic public fun string(): Index = Index { i -> - Iso.stringToList() compose list().index(i) + PLens.stringToList() compose list().index(i) } } } diff --git a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Snoc.kt b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Snoc.kt index 92bedbd7bce..8d6ab4356e0 100644 --- a/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Snoc.kt +++ b/arrow-libs/optics/arrow-optics/src/commonMain/kotlin/arrow/optics/typeclasses/Snoc.kt @@ -1,10 +1,8 @@ package arrow.optics.typeclasses import arrow.core.Either -import arrow.core.Nullable import arrow.core.left import arrow.core.right -import arrow.optics.Iso import arrow.optics.Optional import arrow.optics.PLens import arrow.optics.Prism @@ -56,12 +54,6 @@ public fun interface Snoc { public companion object { - /** - * Lift an instance of [Snoc] using an [Iso]. - */ - public fun fromIso(SS: Snoc, iso: Iso): Snoc = - Snoc { iso compose SS.snoc() compose iso.reverse().first() } - /** * Construct a [Snoc] instance from a [Prism]. */ @@ -76,7 +68,9 @@ public fun interface Snoc { Snoc { object : Prism, Pair, A>> { override fun getOrModify(source: List): Either, Pair, A>> = - Nullable.zip(source.dropLast(1), source.lastOrNull(), ::Pair)?.right() ?: source.left() + source.lastOrNull()?.let { last -> + Pair(source.dropLast(1), last) + }?.right() ?: source.left() override fun reverseGet(focus: Pair, A>): List = focus.first + focus.second diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/CopyTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/CopyTest.kt index 2426b4730ac..6a406d861b5 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/CopyTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/CopyTest.kt @@ -1,7 +1,8 @@ package arrow.optics -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe +import kotlinx.coroutines.test.runTest +import kotlin.test.Test // from https://kotlinlang.slack.com/archives/C5UPMM0A0/p1688822411819599 // and https://github.com/overfullstack/my-lab/blob/master/arrow/src/test/kotlin/ga/overfullstack/optics/OpticsLab.kt @@ -61,8 +62,8 @@ fun Person.moveToAmsterdamInside(): Person = copy { } } -class CopyTest : StringSpec({ - "optics" { +class CopyTest { + @Test fun copyOptics() = runTest { val me = Person( "Gopal", @@ -81,7 +82,7 @@ class CopyTest : StringSpec({ Person.address.get(meAfterMoving) shouldBe newAddress } - "optics composition" { + @Test fun copyOpticsComposition() = runTest { val personCity: Lens = Person.address compose Address.city compose City.name val me = @@ -96,7 +97,7 @@ class CopyTest : StringSpec({ meAtTheCapital.address.city.name shouldBe "Amsterdam" } - "optics copy to modify multiple fields" { + @Test fun copyMultiple() = runTest { val me = Person( "Alejandro", @@ -108,4 +109,4 @@ class CopyTest : StringSpec({ meAfterMoving1 shouldBe meAfterMoving2 meAfterMoving1.address.city.name shouldBe "Amsterdam" } -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/EveryTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/EveryTest.kt index b9919f09a24..650705a7b3a 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/EveryTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/EveryTest.kt @@ -1,92 +1,71 @@ package arrow.optics -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.orNull import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class EveryTest : StringSpec({ +class EveryTest { - with(Every.list()) { - - "asFold should behave as valid Fold: size" { - checkAll(Arb.list(Arb.int())) { ints -> - size(ints) shouldBe ints.size - } - } - - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.list(Arb.int())) { ints -> - isNotEmpty(ints) shouldBe ints.isNotEmpty() - } - } - - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.list(Arb.int())) { ints -> - isEmpty(ints) shouldBe ints.isEmpty() - } - } - - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.list(Arb.int())) { ints -> - getAll(ints) shouldBe ints - } - } - - "asFold should behave as valid Fold: fold" { - checkAll(Arb.list(Arb.int())) { ints -> - fold(0, { x, y -> x + y }, ints) shouldBe ints.sum() - } - } - - "asFold should behave as valid Fold: headOption" { - checkAll(Arb.list(Arb.int().orNull())) { ints -> - Every.list().firstOrNull(ints) shouldBe ints.firstOrNull() - } - } + @Test + fun sizeOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints -> + Every.list().size(ints) shouldBe ints.size + } + } - "asFold should behave as valid Fold: lastOption" { - checkAll(Arb.list(Arb.int().orNull())) { ints -> - Every.list().lastOrNull(ints) shouldBe ints.lastOrNull() - } - } + @Test + fun nonEmptyOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints -> + Every.list().isNotEmpty(ints) shouldBe ints.isNotEmpty() } + } - with(Every.list()) { + @Test + fun isEmptyOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints -> + Every.list().isEmpty(ints) shouldBe ints.isEmpty() + } + } - "Getting all targets of a traversal" { - checkAll(Arb.list(Arb.int())) { ints -> - getAll(ints) shouldBe ints - } - } + @Test + fun getAllOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints -> + Every.list().getAll(ints) shouldBe ints + } + } - "Folding all the values of a traversal" { - checkAll(Arb.list(Arb.int())) { ints -> - fold(0, { x, y -> x + y }, ints) shouldBe ints.sum() - } - } + @Test + fun foldOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints -> + Every.list().fold(0, { x, y -> x + y }, ints) shouldBe ints.sum() + } + } - "Combining all the values of a traversal" { - checkAll(Arb.list(Arb.int())) { ints -> - fold(0, { x, y -> x + y }, ints) shouldBe ints.sum() - } - } + @Test + fun firstOrNullOk() = runTest { + checkAll(Arb.list(Arb.int().orNull())) { ints -> + Every.list().firstOrNull(ints) shouldBe ints.firstOrNull() + } + } - "Finding an number larger than 10" { - checkAll(Arb.list(Arb.int(-100..100).orNull())) { ints -> - val predicate = { i: Int? -> i?.let { it > 10 } ?: false } - Every.list().findOrNull(ints, predicate) shouldBe ints.firstOrNull(predicate) - } - } + @Test + fun lastOrNullOk() = runTest { + checkAll(Arb.list(Arb.int().orNull())) { ints -> + Every.list().lastOrNull(ints) shouldBe ints.lastOrNull() + } + } - "Get the length from a traversal" { - checkAll(Arb.list(Arb.int())) { ints -> - size(ints) shouldBe ints.size - } - } + @Test + fun firstOrNullPredicateOk() = runTest { + checkAll(Arb.list(Arb.int(-100..100).orNull())) { ints -> + val predicate = { i: Int? -> i?.let { it > 10 } ?: false } + Every.list().findOrNull(ints, predicate) shouldBe ints.firstOrNull(predicate) } + } -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/FoldTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/FoldTest.kt deleted file mode 100644 index 0ce444814d8..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/FoldTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -package arrow.optics - -import io.kotest.core.spec.style.StringSpec -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.list -import io.kotest.property.arbitrary.orNull -import io.kotest.property.checkAll - -class FoldTest : StringSpec({ - - "Fold select a list that contains one" { - val select = Fold.select> { it.contains(1) } - - checkAll(Arb.list(Arb.int())) { ints -> - select.run { getAll(ints) }.firstOrNull() shouldBe - ints.let { if (it.contains(1)) it else null } - } - } - - with(Fold.list()) { - - "Folding a list of ints" { - checkAll(Arb.list(Arb.int())) { ints -> - fold(0, { x, y -> x + y }, ints) shouldBe ints.sum() - } - } - - "Folding and mapping a list of strings" { - checkAll(Arb.list(Arb.int())) { ints -> - Fold.list() - .foldMap(0, { x, y -> x + y }, ints.map(Int::toString), String::toInt) shouldBe ints.sum() - } - } - - "Get all targets" { - checkAll(Arb.list(Arb.int())) { ints -> - getAll(ints) shouldBe ints - } - } - - "Get the size of the fold" { - checkAll(Arb.list(Arb.int())) { ints -> - size(ints) shouldBe ints.size - } - } - - "Find the first element matching the predicate" { - checkAll(Arb.list(Arb.int(-100..100).orNull())) { ints -> - val predicate = { i: Int? -> i?.let { it > 10 } ?: false } - Fold.list().findOrNull(ints, predicate) shouldBe ints.firstOrNull(predicate) - } - } - - "Checking existence of a target" { - checkAll(Arb.list(Arb.int().orNull()), Arb.boolean()) { ints, predicate -> - Fold.list().exists(ints) { predicate } shouldBe (predicate && ints.isNotEmpty()) - } - } - - "Check if all targets match the predicate" { - checkAll(Arb.list(Arb.int())) { ints -> - all(ints) { it % 2 == 0 } shouldBe ints.all { it % 2 == 0 } - } - } - - "Check if there is no target" { - checkAll(Arb.list(Arb.int())) { ints -> - isEmpty(ints) shouldBe ints.isEmpty() - } - } - - "Check if there is a target" { - checkAll(Arb.list(Arb.int())) { ints -> - isNotEmpty(ints) shouldBe ints.isNotEmpty() - } - } - } - -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/GetterTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/GetterTest.kt deleted file mode 100644 index 0c6c95309c9..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/GetterTest.kt +++ /dev/null @@ -1,113 +0,0 @@ -package arrow.optics - -import arrow.core.Either.Left -import arrow.core.Either.Right -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.string -import io.kotest.property.arbitrary.boolean -import io.kotest.property.checkAll - -class GetterTest : StringSpec({ - - "asFold should behave as valid Fold: size" { - checkAll(Arb.token()) { token -> - Getter.token().size(token) shouldBe 1 - } - } - - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.token()) { token -> - Getter.token().isNotEmpty(token) shouldBe true - } - } - - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.token()) { token -> - !Getter.token().isEmpty(token) shouldBe true - } - } - - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.token()) { token -> - Getter.token().getAll(token) shouldBe listOf(token.value) - } - } - - "asFold should behave as valid Fold: fold" { - checkAll(Arb.token()) { token -> - Getter.token().fold("", { x, y -> x + y }, token) shouldBe token.value - } - } - - "asFold should behave as valid Fold: headOption" { - checkAll(Arb.token()) { token -> - Getter.token().firstOrNull(token) shouldBe token.value - } - } - - "asFold should behave as valid Fold: lastOption" { - checkAll(Arb.token()) { token -> - Getter.token().lastOrNull(token) shouldBe token.value - } - } - - "Getting the target should always yield the exact result" { - checkAll(Arb.string()) { value: String -> - Getter.token().get(Token(value)) shouldBe value - } - } - - "Finding a target using a predicate within a Getter should be wrapped in the correct option result" { - checkAll(Arb.string(), Arb.boolean()) { value: String, predicate: Boolean -> - (Getter.token().findOrNull(Token(value)) { predicate }?.let { true } ?: false) shouldBe predicate - } - } - - "Checking existence of a target should always result in the same result as predicate" { - checkAll(Arb.string(), Arb.boolean()) { value: String, predicate: Boolean -> - Getter.token().any(Token(value)) { predicate } shouldBe predicate - } - } - - "Zipping two lenses should yield a tuple of the targets" { - checkAll(Arb.string()) { value: String -> - Getter { it.length }.zip { it.uppercase() } - .get(value) shouldBe (value.length to value.uppercase()) - } - } - - "Joining two getters together with same target should yield same result" { - checkAll(Arb.string()) { tokenValue: String -> - val userTokenStringGetter = Iso.user() compose Getter.token() - val joinedGetter = Getter.token().choice(userTokenStringGetter) - val token = Token(tokenValue) - val user = User(token) - joinedGetter.get(Left(token)) shouldBe joinedGetter.get(Right(user)) - } - } - - "Pairing two disjoint getters should yield a pair of their results" { - val splitGetter: Getter, Pair> = Getter.token().split(Iso.user()) - checkAll(Arb.token(), Arb.user()) { token: Token, user: User -> - splitGetter.get(token to user) shouldBe (token.value to user.token) - } - } - - "Creating a first pair with a type should result in the target to value" { - val first = Getter.token().first() - checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> - first.get(token to int) shouldBe (token.value to int) - } - } - - "Creating a second pair with a type should result in the value target" { - checkAll(Arb.int(), Arb.token()) { int: Int, token: Token -> - val first = Getter.token().second() - first.get(int to token) shouldBe (int to token.value) - } - } - -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/IsoTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/IsoTest.kt index b8f0608807b..3d7cd9f6e7f 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/IsoTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/IsoTest.kt @@ -6,26 +6,27 @@ import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.OptionalLaws import arrow.optics.test.laws.PrismLaws -import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec 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.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class IsoTest : StringSpec({ +class IsoTest { - val aIso: Iso = Iso( - get = { a: SumType.A -> a.string }, - reverseGet = SumType::A - ) + private val aIso: Iso = Iso( + get = { a: SumType.A -> a.string }, + reverseGet = SumType::A + ) + @Test + fun isoTokenLaws() = testLaws( - "Iso token - ", LensLaws( lens = Iso.token(), aGen = Arb.token(), @@ -54,13 +55,6 @@ class IsoTest : StringSpec({ funcGen = Arb.functionAToB(Arb.string()) ), - SetterLaws( - setter = Iso.token(), - aGen = Arb.token(), - bGen = Arb.string(), - funcGen = Arb.functionAToB(Arb.string()) - ), - IsoLaws( iso = Iso.token(), aGen = Arb.token(), @@ -69,138 +63,131 @@ class IsoTest : StringSpec({ ) ) - with(Iso.token()) { - - "asFold should behave as valid Fold: size" { - checkAll(Arb.token()) { token -> - size(token) shouldBe 1 - } - } - - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.token()) { token -> - isNotEmpty(token) shouldBe true - } - } - - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.token()) { token -> - !isEmpty(token) shouldBe true - } - } - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.token()) { token -> - getAll(token) shouldBe listOf(token.value) - } - } - - "asFold should behave as valid Fold: fold" { - checkAll(Arb.token()) { token -> - fold("", { x, y -> x + y }, token) shouldBe token.value - } - } - - "asFold should behave as valid Fold: headOption" { - checkAll(Arb.token()) { token -> - firstOrNull(token) shouldBe token.value - } - } - - "asFold should behave as valid Fold: lastOption" { - checkAll(Arb.token()) { token -> - lastOrNull(token) shouldBe token.value - } - } + @Test + fun sizeOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().size(token) shouldBe 1 } + } - with(Iso.token()) { + @Test + fun isNotEmptyOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().isNotEmpty(token) shouldBe true + } + } - "asGetter should behave as valid Getter: get" { - checkAll(Arb.token()) { token -> - get(token) shouldBe Getter.token().get(token) - } - } + @Test + fun isEmptyOk() = runTest { + checkAll(Arb.token()) { token -> + !Iso.token().isEmpty(token) shouldBe true + } + } - "asGetter should behave as valid Getter: find" { - checkAll(Arb.token(), Arb.functionAToB(Arb.boolean())) { token, p -> - findOrNull(token, p) shouldBe Getter.token().findOrNull(token, p) - } - } + @Test + fun getAllOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().getAll(token) shouldBe listOf(token.value) + } + } - "asGetter should behave as valid Getter: exist" { - checkAll(Arb.token(), Arb.functionAToB(Arb.boolean())) { token, p -> - any(token, p) shouldBe Getter.token().any(token, p) - } - } + @Test + fun foldOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().fold("", { x, y -> x + y }, token) shouldBe token.value } + } - "Lifting a function should yield the same result as not yielding" { - checkAll(Arb.token(), Arb.string()) { token, value -> - Iso.token().modify(token) { value } shouldBe Iso.token().lift { value }(token) - } + @Test + fun firstOrNullOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().firstOrNull(token) shouldBe token.value } + } - "Creating a first pair with a type should result in the target to value" { - val first = Iso.token().first() - checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> - first.get(token to int) shouldBe (token.value to int) - } + @Test + fun lastOrNullOk() = runTest { + checkAll(Arb.token()) { token -> + Iso.token().lastOrNull(token) shouldBe token.value } + } - "Creating a second pair with a type should result in the value to target" { - val second = Iso.token().second() - checkAll(Arb.int(), Arb.token()) { int: Int, token: Token -> - second.get(int to token) shouldBe (int to token.value) - } + @Test + fun modifyOk() = runTest { + checkAll(Arb.token(), Arb.string()) { token, value -> + Iso.token().modify(token) { value } shouldBe Iso.token().lift { value }(token) } + } - "Creating a left with a type should result in a sum target to value" { - val left = Iso.token().left() - checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> - left.get(Either.Left(token)) shouldBe Either.Left(token.value) - left.get(Either.Right(int)) shouldBe Either.Right(int) - } + @Test + fun firstOk() = runTest { + val first = Iso.token().first() + checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> + first.get(token to int) shouldBe (token.value to int) } + } - "Creating a right with a type should result in a sum value to target" { - val left = Iso.token().right() - checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> - left.get(Either.Left(int)) shouldBe Either.Left(int) - left.get(Either.Right(token)) shouldBe Either.Right(token.value) - } + @Test + fun secondOk() = runTest { + val second = Iso.token().second() + checkAll(Arb.int(), Arb.token()) { int: Int, token: Token -> + second.get(int to token) shouldBe (int to token.value) + } + } + + @Test + fun leftOk() = runTest { + val left = Iso.token().left() + checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> + left.get(Either.Left(token)) shouldBe Either.Left(token.value) + left.get(Either.Right(int)) shouldBe Either.Right(int) + } + } + + @Test + fun rightOk() = runTest { + val left = Iso.token().right() + checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> + left.get(Either.Left(int)) shouldBe Either.Left(int) + left.get(Either.Right(token)) shouldBe Either.Right(token.value) } + } - "Finding a target using a predicate within a Iso should be wrapped in the correct option result" { - checkAll(Arb.boolean()) { predicate: Boolean -> - (Iso.token().findOrNull(Token("any value")) { predicate }?.let { true } ?: false) shouldBe predicate - } + @Test + fun firstOrNullPredicateOk() = runTest { + checkAll(Arb.boolean()) { predicate: Boolean -> + (Iso.token().findOrNull(Token("any value")) { predicate }?.let { true } ?: false) shouldBe predicate } + } - "Checking existence predicate over the target should result in same result as predicate" { - checkAll(Arb.boolean()) { predicate: Boolean -> - Iso.token().any(Token("any value")) { predicate } shouldBe predicate - } + @Test + fun anyOk() = runTest { + checkAll(Arb.boolean()) { predicate: Boolean -> + Iso.token().any(Token("any value")) { predicate } shouldBe predicate } + } - "Pairing two disjoint isos together" { - val joinedIso = Iso.token() split Iso.user() + @Test + fun splitOk() = runTest { + val joinedIso = Iso.token() split Iso.user() - checkAll(Arb.string()) { tokenValue: String -> - val token = Token(tokenValue) - val user = User(token) - joinedIso.get(token to user) shouldBe (tokenValue to token) - } + checkAll(Arb.string()) { tokenValue: String -> + val token = Token(tokenValue) + val user = User(token) + joinedIso.get(token to user) shouldBe (tokenValue to token) } + } - "Composing isos should result in an iso of the first iso's value with the second iso's target" { - val composedIso = Iso.user() compose Iso.token() + @Test + fun composeOk() = runTest { + val composedIso = Iso.user() compose Iso.token() - checkAll(Arb.string()) { tokenValue: String -> - val token = Token(tokenValue) - val user = User(token) - composedIso.get(user) shouldBe tokenValue - } + checkAll(Arb.string()) { tokenValue: String -> + val token = Token(tokenValue) + val user = User(token) + composedIso.get(user) shouldBe tokenValue } + } -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/LensTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/LensTest.kt index caac6159204..a30cdb46d16 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/LensTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/LensTest.kt @@ -5,21 +5,22 @@ import arrow.core.Either.Right import arrow.optics.test.functionAToB import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec 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.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class LensTest : StringSpec({ +class LensTest { + @Test + fun lensTokenLaws() = testLaws( - "TokenLens - ", LensLaws( lens = Lens.token(), aGen = Arb.token(), @@ -39,18 +40,12 @@ class LensTest : StringSpec({ aGen = Arb.token(), bGen = Arb.string(), funcGen = Arb.functionAToB(Arb.string()), - ), - - SetterLaws( - setter = Lens.token(), - aGen = Arb.token(), - bGen = Arb.string(), - funcGen = Arb.functionAToB(Arb.string()), ) ) + @Test + fun identityLens() = testLaws( - "Identity Lens - ", LensLaws( lens = Lens.id(), aGen = Arb.int(), @@ -59,114 +54,110 @@ class LensTest : StringSpec({ ) ) - "asFold should behave as valid Fold: size" { - checkAll(Arb.token()) { token -> - Lens.token().size(token) shouldBe 1 - } - } - - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.token()) { token -> - Lens.token().isNotEmpty(token) shouldBe true - } - } - - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.token()) { token -> - !Lens.token().isEmpty(token) shouldBe true - } - } - - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.token()) { token -> - Lens.token().getAll(token) shouldBe listOf(token.value) - } + @Test + fun sizeOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().size(token) shouldBe 1 } + } - "asFold should behave as valid Fold: fold" { - checkAll(Arb.token()) { token -> - Lens.token().fold("", { x, y -> x + y }, token) shouldBe token.value - } + @Test + fun isNonEmptyOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().isNotEmpty(token) shouldBe true } + } - "asFold should behave as valid Fold: headOption" { - checkAll(Arb.token()) { token -> - Lens.token().firstOrNull(token) shouldBe token.value - } + @Test + fun isEmptyOk() = runTest { + checkAll(Arb.token()) { token -> + !Lens.token().isEmpty(token) shouldBe true } + } - "asFold should behave as valid Fold: lastOption" { - checkAll(Arb.token()) { token -> - Lens.token().lastOrNull(token) shouldBe token.value - } + @Test + fun getAllOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().getAll(token) shouldBe listOf(token.value) } + } - "asGetter should behave as valid Getter: get" { - checkAll(Arb.token()) { token -> - Lens.token().get(token) shouldBe Getter.token().get(token) - } + @Test + fun foldOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().fold("", { x, y -> x + y }, token) shouldBe token.value } + } - "asGetter should behave as valid Getter: find" { - checkAll(Arb.token(), Arb.functionAToB(Arb.boolean())) { token, p -> - Lens.token().findOrNull(token, p) shouldBe Getter.token().findOrNull(token, p) - } + @Test + fun firstOrNullOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().firstOrNull(token) shouldBe token.value } + } - "asGetter should behave as valid Getter: exist" { - checkAll(Arb.token(), Arb.functionAToB(Arb.boolean())) { token, p -> - Lens.token().any(token, p) shouldBe Getter.token().any(token, p) - } + @Test + fun lastOrNullOk() = runTest { + checkAll(Arb.token()) { token -> + Lens.token().lastOrNull(token) shouldBe token.value } + } - "Lifting a function should yield the same result as not yielding" { - checkAll(Arb.token(), Arb.string()) { token, value -> - Lens.token().set(token, value) shouldBe Lens.token().lift { value }(token) - } + @Test + fun setOrLift() = runTest { + checkAll(Arb.token(), Arb.string()) { token, value -> + Lens.token().set(token, value) shouldBe Lens.token().lift { value }(token) } + } - "Finding a target using a predicate within a Lens should be wrapped in the correct option result" { - checkAll(Arb.boolean()) { predicate: Boolean -> - (Lens.token().findOrNull(Token("any value")) { predicate }?.let { true } ?: false) shouldBe predicate - } + @Test + fun findOrNullPredicate() = runTest { + checkAll(Arb.boolean()) { predicate: Boolean -> + (Lens.token().findOrNull(Token("any value")) { predicate }?.let { true } ?: false) shouldBe predicate } + } - "Checking existence predicate over the target should result in same result as predicate" { - checkAll(Arb.boolean()) { predicate: Boolean -> - Lens.token().any(Token("any value")) { predicate } shouldBe predicate - } + @Test + fun anyOk() = runTest { + checkAll(Arb.boolean()) { predicate: Boolean -> + Lens.token().any(Token("any value")) { predicate } shouldBe predicate } + } - "Joining two lenses together with same target should yield same result" { - val userTokenStringLens = Lens.user() compose Lens.token() - val joinedLens = Lens.token() choice userTokenStringLens + @Test + fun joinOk() = runTest { + val userTokenStringLens = Lens.user() compose Lens.token() + val joinedLens = Lens.token() choice userTokenStringLens - checkAll(Arb.string()) { tokenValue: String -> - val token = Token(tokenValue) - val user = User(token) - joinedLens.get(Left(token)) shouldBe joinedLens.get(Right(user)) - } + checkAll(Arb.string()) { tokenValue: String -> + val token = Token(tokenValue) + val user = User(token) + joinedLens.get(Left(token)) shouldBe joinedLens.get(Right(user)) } + } - "Pairing two disjoint lenses should yield a pair of their results" { - val spiltLens: Lens, Pair> = Lens.token() split Lens.user() - checkAll(Arb.token(), Arb.user()) { token: Token, user: User -> - spiltLens.get(token to user) shouldBe (token.value to user.token) - } + @Test + fun splitOk() = runTest { + val spiltLens: Lens, Pair> = Lens.token() split Lens.user() + checkAll(Arb.token(), Arb.user()) { token: Token, user: User -> + spiltLens.get(token to user) shouldBe (token.value to user.token) } + } - "Creating a first pair with a type should result in the target to value" { - val first = Lens.token().first() - checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> - first.get(token to int) shouldBe (token.value to int) - } + @Test + fun firstOk() = runTest { + val first = Lens.token().first() + checkAll(Arb.token(), Arb.int()) { token: Token, int: Int -> + first.get(token to int) shouldBe (token.value to int) } + } - "Creating a second pair with a type should result in the value target" { - val second = Lens.token().second() - checkAll(Arb.int(), Arb.token()) { int: Int, token: Token -> - second.get(int to token) shouldBe (int to token.value) - } + @Test + fun secondOk() = runTest { + val second = Lens.token().second() + checkAll(Arb.int(), Arb.token()) { int: Int, token: Token -> + second.get(int to token) shouldBe (int to token.value) } + } -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalGetterTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalGetterTest.kt deleted file mode 100644 index 3f81049e0d2..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalGetterTest.kt +++ /dev/null @@ -1,25 +0,0 @@ -package arrow.optics - -import io.kotest.core.spec.style.StringSpec -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.list -import io.kotest.property.checkAll - -class OptionalGetterTest : StringSpec({ - - "get should return value if predicate is true and null if otherwise" { - checkAll(Arb.int(), Arb.boolean()) { int, predicate -> - OptionalGetter.filter { predicate }.getOrNull(int) shouldBe (if (predicate) int else null) - } - } - - "getAll should return the old list if predicate is true" { - checkAll(Arb.list(Arb.int()), Arb.boolean()) { list, predicate -> - (Fold.list() compose OptionalGetter.filter { predicate }).getAll(list) shouldBe (if (predicate) list else emptyList()) - } - } - -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalTest.kt index 00fb2d5e344..f8977ee7943 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/OptionalTest.kt @@ -8,7 +8,6 @@ import arrow.core.toOption import arrow.optics.test.functionAToB import arrow.optics.test.laws.OptionalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.nulls.shouldNotBeNull import io.kotest.matchers.shouldBe import io.kotest.property.Arb @@ -19,11 +18,14 @@ import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class OptionalTest : StringSpec({ +class OptionalTest { + @Test + fun identityLaws() = testLaws( - "Optional identity - ", OptionalLaws( optional = Optional.id(), aGen = Arb.int(), @@ -32,8 +34,9 @@ class OptionalTest : StringSpec({ ) ) + @Test + fun optionalFirstHeadLaws() = testLaws( - "Optional first head - ", OptionalLaws( optional = Optional.listHead().first(), aGen = Arb.pair(Arb.list(Arb.int()), Arb.boolean()), @@ -42,8 +45,9 @@ class OptionalTest : StringSpec({ ) ) + @Test + fun optionalSecondHeadLaws() = testLaws( - "Optional second head - ", OptionalLaws( optional = Optional.listHead().second(), aGen = Arb.pair(Arb.boolean(), Arb.list(Arb.int())), @@ -52,121 +56,135 @@ class OptionalTest : StringSpec({ ) ) - "asSetter should set absent optional" { - checkAll(Arb.incompleteUser(), Arb.token()) { user, token -> - val updatedUser = Optional.incompleteUserToken().set(user, token) - Optional.incompleteUserToken().getOrNull(updatedUser).shouldNotBeNull() - } + @Test + fun setAbsentOptional() = runTest { + checkAll(Arb.incompleteUser(), Arb.token()) { user, token -> + val updatedUser = Optional.incompleteUserToken().set(user, token) + Optional.incompleteUserToken().getOrNull(updatedUser).shouldNotBeNull() } + } - with(Optional.listHead()) { - - "asFold should behave as valid Fold: size" { - checkAll(Arb.list(Arb.int())) { ints: List -> - size(ints) shouldBe ints.firstOrNull().toOption().map { 1 }.getOrElse { 0 } - } - } + @Test + fun sizeOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints: List -> + Optional.listHead().size(ints) shouldBe ints.firstOrNull().toOption().map { 1 }.getOrElse { 0 } + } + } - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.list(Arb.int())) { ints: List -> - isNotEmpty(ints) shouldBe ints.firstOrNull().toOption().isSome() - } - } + @Test + fun nonEmptyOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints: List -> + Optional.listHead().isNotEmpty(ints) shouldBe ints.firstOrNull().toOption().isSome() + } + } - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.list(Arb.int())) { ints: List -> - isEmpty(ints) shouldBe ints.firstOrNull().toOption().isNone() - } - } + @Test + fun isEmptyOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints: List -> + Optional.listHead().isEmpty(ints) shouldBe ints.firstOrNull().toOption().isNone() + } + } - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.list(Arb.int())) { ints: List -> - getAll(ints) shouldBe ints.firstOrNull().toOption().toList() - } - } + @Test + fun getAllOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints: List -> + Optional.listHead().getAll(ints) shouldBe ints.firstOrNull().toOption().toList() + } + } - "asFold should behave as valid Fold: fold" { - checkAll(Arb.list(Arb.int())) { ints: List -> - fold(0, { x, y -> x + y }, ints) shouldBe - ints.firstOrNull().toOption().fold({ 0 }, ::identity) - } - } + @Test + fun foldOk() = runTest { + checkAll(Arb.list(Arb.int())) { ints: List -> + Optional.listHead().fold(0, { x, y -> x + y }, ints) shouldBe + ints.firstOrNull().toOption().fold({ 0 }, ::identity) } + } - "listHead.firstOrNull == firstOrNull" { - checkAll(Arb.list(Arb.int().orNull())) { ints -> - Optional.listHead().firstOrNull(ints) shouldBe ints.firstOrNull() - } + @Test + fun firstOrNullOk() = runTest { + checkAll(Arb.list(Arb.int().orNull())) { ints -> + Optional.listHead().firstOrNull(ints) shouldBe ints.firstOrNull() } + } - "listHead.lastOrNull == firstOrNull" { - checkAll(Arb.list(Arb.int().orNull())) { ints -> - Optional.listHead().lastOrNull(ints) shouldBe ints.firstOrNull() - } + @Test + fun lastOrNullOk() = runTest { + checkAll(Arb.list(Arb.int().orNull())) { ints -> + Optional.listHead().lastOrNull(ints) shouldBe ints.firstOrNull() } + } - "unit should always " { - checkAll(Arb.string()) { string: String -> - Optional.void().getOrNull(string) shouldBe null - } + @Test + fun unitAlwaysNull() = runTest { + checkAll(Arb.string()) { string: String -> + Optional.void().getOrNull(string) shouldBe null } + } - "unit should always return source when setting target" { - checkAll(Arb.int(), Arb.string()) { int: Int, string: String -> - Optional.void().set(string, int) shouldBe string - } + @Test + fun unitDoesNothing() = runTest { + checkAll(Arb.int(), Arb.string()) { int: Int, string: String -> + Optional.void().set(string, int) shouldBe string } + } - "Checking if there is no target" { - checkAll(Arb.list(Arb.int())) { list -> - Optional.listHead().isNotEmpty(list) shouldBe list.isNotEmpty() - } + @Test + fun noTarget() = runTest { + checkAll(Arb.list(Arb.int())) { list -> + Optional.listHead().isNotEmpty(list) shouldBe list.isNotEmpty() } + } - "Lift should be consistent with modify" { - checkAll(Arb.list(Arb.int())) { list -> - val f = { i: Int -> i + 5 } - Optional.listHead().lift(f)(list) shouldBe Optional.listHead().modify(list, f) - } + @Test + fun liftConsistentWithModify() = runTest { + checkAll(Arb.list(Arb.int())) { list -> + val f = { i: Int -> i + 5 } + Optional.listHead().lift(f)(list) shouldBe Optional.listHead().modify(list, f) } + } - "Checking if a target exists" { - checkAll(Arb.list(Arb.int())) { list -> - Optional.listHead().isEmpty(list) shouldBe list.isEmpty() - } + @Test + fun checkTargetExists() = runTest { + checkAll(Arb.list(Arb.int())) { list -> + Optional.listHead().isEmpty(list) shouldBe list.isEmpty() } + } - "Finding a target using a predicate should be wrapped in the correct option result" { - checkAll(Arb.list(Arb.int()), Arb.boolean()) { list, predicate -> - (Optional.listHead().findOrNull(list) { predicate }?.let { true } - ?: false) shouldBe (predicate && list.isNotEmpty()) - } + @Test + fun findOrNullOk() = runTest { + checkAll(Arb.list(Arb.int()), Arb.boolean()) { list, predicate -> + (Optional.listHead().findOrNull(list) { predicate }?.let { true } + ?: false) shouldBe (predicate && list.isNotEmpty()) } + } - "Checking existence predicate over the target should result in same result as predicate" { - checkAll(Arb.list(Arb.int().orNull()), Arb.boolean()) { list, predicate -> - Optional.listHead().exists(list) { predicate } shouldBe (predicate && list.isNotEmpty()) - } + @Test + fun existsOk() = runTest { + checkAll(Arb.list(Arb.int().orNull()), Arb.boolean()) { list, predicate -> + Optional.listHead().exists(list) { predicate } shouldBe (predicate && list.isNotEmpty()) } + } - "Checking satisfaction of predicate over the target should result in opposite result as predicate" { - checkAll(Arb.list(Arb.int()), Arb.boolean()) { list, predicate -> - Optional.listHead().all(list) { predicate } shouldBe if (list.isEmpty()) true else predicate - } + @Test + fun allOk() = runTest { + checkAll(Arb.list(Arb.int()), Arb.boolean()) { list, predicate -> + Optional.listHead().all(list) { predicate } shouldBe if (list.isEmpty()) true else predicate } + } - "Set a value over a non empty list target then the first item of the result should be the value" { - checkAll(Arb.list(Arb.int(), 1..200), Arb.int()) { list, value -> - Optional.listHead().set(list, value)[0] shouldBe value - } + @Test + fun setNonEmptyList() = runTest { + checkAll(Arb.list(Arb.int(), 1..200), Arb.int()) { list, value -> + Optional.listHead().set(list, value)[0] shouldBe value } + } - "Joining two optionals together with same target should yield same result" { - val joinedOptional = Optional.listHead().choice(Optional.defaultHead()) + @Test + fun joinOk() = runTest { + val joinedOptional = Optional.listHead().choice(Optional.defaultHead()) - checkAll(Arb.int()) { int -> - joinedOptional.getOrNull(Left(listOf(int))) shouldBe joinedOptional.getOrNull(Right(int)) - } + checkAll(Arb.int()) { int -> + joinedOptional.getOrNull(Left(listOf(int))) shouldBe joinedOptional.getOrNull(Right(int)) } - -}) + } +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/PrismTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/PrismTest.kt index 6536d391964..e0a2b7dabca 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/PrismTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/PrismTest.kt @@ -4,10 +4,8 @@ import arrow.optics.test.either import arrow.optics.test.functionAToB import arrow.optics.test.laws.OptionalLaws import arrow.optics.test.laws.PrismLaws -import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean @@ -15,11 +13,14 @@ import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string import io.kotest.property.checkAll +import kotlinx.coroutines.test.runTest +import kotlin.test.Test -class PrismTest : StringSpec({ +class PrismTest { + @Test + fun prismSumLaws() = testLaws( - "Prism sum - ", PrismLaws( prism = Prism.sumType(), aGen = Arb.sumType(), @@ -27,13 +28,6 @@ class PrismTest : StringSpec({ funcGen = Arb.functionAToB(Arb.string()), ), - SetterLaws( - setter = Prism.sumType(), - aGen = Arb.sumType(), - bGen = Arb.string(), - funcGen = Arb.functionAToB(Arb.string()), - ), - TraversalLaws( traversal = Prism.sumType(), aGen = Arb.sumType(), @@ -49,8 +43,9 @@ class PrismTest : StringSpec({ ) ) + @Test + fun prismSumFirstLaws() = testLaws( - "Prism sum first - ", PrismLaws( prism = Prism.sumType().first(), aGen = Arb.pair(Arb.sumType(), Arb.int()), @@ -59,8 +54,9 @@ class PrismTest : StringSpec({ ) ) + @Test + fun prismSumSecondLaws() = testLaws( - "Prism sum second - ", PrismLaws( prism = Prism.sumType().second(), aGen = Arb.pair(Arb.int(), Arb.sumType()), @@ -69,8 +65,9 @@ class PrismTest : StringSpec({ ) ) + @Test + fun prismSumRightLaws() = testLaws( - "Prism sum right - ", PrismLaws( prism = Prism.sumType().right(), aGen = Arb.either(Arb.int(), Arb.sumType()), @@ -79,8 +76,9 @@ class PrismTest : StringSpec({ ) ) + @Test + fun prismSumLeftLaws() = testLaws( - "Prism sum left - ", PrismLaws( prism = Prism.sumType().left(), aGen = Arb.either(Arb.sumType(), Arb.int()), @@ -89,8 +87,9 @@ class PrismTest : StringSpec({ ) ) + @Test + fun prismIdentityLaws() = testLaws( - "Prism identity - ", PrismLaws( prism = Prism.id(), aGen = Arb.either(Arb.int(), Arb.int()), @@ -99,99 +98,112 @@ class PrismTest : StringSpec({ ) ) - with(Prism.sumType()) { - "asFold should behave as valid Fold: size" { - checkAll(Arb.sumType()) { sum: SumType -> - size(sum) shouldBe (Prism.sumType().getOrNull(sum)?.let { 1 } ?: 0) - } - } - - "asFold should behave as valid Fold: nonEmpty" { - checkAll(Arb.sumType()) { sum: SumType -> - isNotEmpty(sum) shouldBe (Prism.sumType().getOrNull(sum) != null) - } - } - - "asFold should behave as valid Fold: isEmpty" { - checkAll(Arb.sumType()) { sum: SumType -> - isEmpty(sum) shouldBe (Prism.sumType().getOrNull(sum) == null) - } - } - - "asFold should behave as valid Fold: getAll" { - checkAll(Arb.sumType()) { sum: SumType -> - getAll(sum) shouldBe listOfNotNull(Prism.sumType().getOrNull(sum)) - } - } - - "asFold should behave as valid Fold: fold" { - checkAll(Arb.sumType()) { sum: SumType -> - fold("", { x, y -> x + y }, sum) shouldBe - (Prism.sumType().getOrNull(sum) ?: "") - } - } - - "asFold should behave as valid Fold: headOption" { - checkAll(Arb.sumType()) { sum: SumType -> - firstOrNull(sum) shouldBe Prism.sumType().getOrNull(sum) - } - } - - "asFold should behave as valid Fold: lastOption" { - checkAll(Arb.sumType()) { sum: SumType -> - lastOrNull(sum) shouldBe Prism.sumType().getOrNull(sum) - } - } + @Test + fun sizeOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().size(sum) shouldBe (Prism.sumType().getOrNull(sum)?.let { 1 } ?: 0) + } + } + + @Test + fun nonEmptyOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().isNotEmpty(sum) shouldBe (Prism.sumType().getOrNull(sum) != null) + } + } + + @Test + fun isEmptyOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().isEmpty(sum) shouldBe (Prism.sumType().getOrNull(sum) == null) + } + } + + @Test + fun getAllOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().getAll(sum) shouldBe listOfNotNull(Prism.sumType().getOrNull(sum)) + } + } + + @Test + fun foldOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().fold("", { x, y -> x + y }, sum) shouldBe + (Prism.sumType().getOrNull(sum) ?: "") + } + } + + @Test + fun firstOrNullOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().firstOrNull(sum) shouldBe Prism.sumType().getOrNull(sum) } + } - "Joining two prisms together with same target should yield same result" { - checkAll(Arb.sumType()) { a -> - (Prism.sumType() compose Prism.string()).getOrNull(a) shouldBe Prism.sumType().getOrNull(a) - ?.let(Prism.string()::getOrNull) - (Prism.sumType() + Prism.string()).getOrNull(a) shouldBe (Prism.sumType() compose Prism.string()).getOrNull(a) - } + @Test + fun lastOrNullOk() = runTest { + checkAll(Arb.sumType()) { sum: SumType -> + Prism.sumType().lastOrNull(sum) shouldBe Prism.sumType().getOrNull(sum) + } + } + + @Test + fun joinOk() = runTest { + checkAll(Arb.sumType()) { a -> + (Prism.sumType() compose Prism.string()).getOrNull(a) shouldBe Prism.sumType().getOrNull(a) + ?.let(Prism.string()::getOrNull) + (Prism.sumType() + Prism.string()).getOrNull(a) shouldBe (Prism.sumType() compose Prism.string()).getOrNull(a) } + } - "Checking if a prism exists with a target" { - checkAll(Arb.sumType(), Arb.sumType(), Arb.boolean()) { a, other, bool -> - Prism.only(a) { _, _ -> bool }.isEmpty(other) shouldBe bool - } + @Test + fun checkExists() = runTest { + checkAll(Arb.sumType(), Arb.sumType(), Arb.boolean()) { a, other, bool -> + Prism.only(a) { _, _ -> bool }.isEmpty(other) shouldBe bool } + } - "Checking if there is no target" { - checkAll(Arb.sumType()) { sum -> - Prism.sumType().isEmpty(sum) shouldBe (sum !is SumType.A) - } + @Test + fun checkNoTarget() = runTest { + checkAll(Arb.sumType()) { sum -> + Prism.sumType().isEmpty(sum) shouldBe (sum !is SumType.A) } + } - "Checking if a target exists" { - checkAll(Arb.sumType()) { sum -> - Prism.sumType().isNotEmpty(sum) shouldBe (sum is SumType.A) - } + @Test + fun checkTargetExists() = runTest { + checkAll(Arb.sumType()) { sum -> + Prism.sumType().isNotEmpty(sum) shouldBe (sum is SumType.A) } + } - "Setting a target on a prism should set the correct target" { - checkAll(Arb.sumTypeA(), Arb.string()) { a, string -> - (Prism.sumType().setNullable(a, string)!!) shouldBe a.copy(string = string) - } + @Test + fun setOk() = runTest { + checkAll(Arb.sumTypeA(), Arb.string()) { a, string -> + (Prism.sumType().setNullable(a, string)!!) shouldBe a.copy(string = string) } + } - "Finding a target using a predicate within a Lens should be wrapped in the correct option result" { - checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> - (Prism.sumType().findOrNull(sum) { predicate }?.let { true } ?: false) shouldBe (predicate && sum is SumType.A) - } + @Test + fun findOrNullOk() = runTest { + checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> + (Prism.sumType().findOrNull(sum) { predicate }?.let { true } ?: false) shouldBe (predicate && sum is SumType.A) } + } - "Checking existence predicate over the target should result in same result as predicate" { - checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> - Prism.sumType().any(sum) { predicate } shouldBe (predicate && sum is SumType.A) - } + @Test + fun anyOk() = runTest { + checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> + Prism.sumType().any(sum) { predicate } shouldBe (predicate && sum is SumType.A) } + } - "Checking satisfaction of predicate over the target should result in opposite result as predicate" { - checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> - Prism.sumType().all(sum) { predicate } shouldBe (predicate || sum is SumType.B) - } + @Test + fun allOk() = runTest { + checkAll(Arb.sumType(), Arb.boolean()) { sum, predicate -> + Prism.sumType().all(sum) { predicate } shouldBe (predicate || sum is SumType.B) } + } -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/SetterTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/SetterTest.kt deleted file mode 100644 index 61cbf338804..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/SetterTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -package arrow.optics - -import arrow.core.getOrElse -import arrow.core.left -import arrow.core.right -import arrow.optics.test.functionAToB -import arrow.optics.test.laws.SetterLaws -import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec -import io.kotest.matchers.shouldBe -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.string -import io.kotest.property.checkAll - -class SetterTest : StringSpec({ - - testLaws( - "Setter identity - ", - SetterLaws( - setter = Setter.id(), - aGen = Arb.int(), - bGen = Arb.int(), - funcGen = Arb.functionAToB(Arb.int()), - ) - ) - - testLaws( - "Setter token - ", - SetterLaws( - setter = Setter.token(), - aGen = Arb.token(), - bGen = Arb.string(), - funcGen = Arb.functionAToB(Arb.string()), - ) - ) - - "Joining two lenses together with same target should yield same result" { - val userTokenStringSetter = Setter.user() compose Setter.token() - val joinedSetter = Setter.token().choice(userTokenStringSetter) - val oldValue = "oldValue" - val token = Token(oldValue) - val user = User(token) - - checkAll(Arb.string()) { value: String -> - joinedSetter.set(token.left(), value).swap().getOrElse { Token("Wrong value") }.value shouldBe - joinedSetter.set(user.right(), value).getOrElse { User(Token("Wrong value")) }.token.value - } - } - - "Lifting a function should yield the same result as direct modify" { - checkAll(Arb.token(), Arb.string()) { token, value -> - Setter.token().modify(token) { value } shouldBe Setter.token().lift { value }(token) - } - } - -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TestDomain.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TestDomain.kt index 1068b9624c4..a6d7f7d9abf 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TestDomain.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TestDomain.kt @@ -42,19 +42,11 @@ internal fun PIso.Companion.token(): Iso = Iso( ::Token ) -internal fun PSetter.Companion.token(): Setter = Setter { token, s -> - token.copy(value = s(token.value)) -} - internal fun PIso.Companion.user(): Iso = Iso( { user: User -> user.token }, ::User ) -internal fun PSetter.Companion.user(): Setter = Setter { user, s -> - user.copy(token = s(user.token)) -} - internal data class Token(val value: String) { companion object } @@ -71,10 +63,7 @@ internal data class IncompleteUser(val token: Token?) internal fun Arb.Companion.incompleteUser(): Arb = Arb.constant(IncompleteUser(null)) -internal fun Getter.Companion.token(): Getter = - Getter { it.value } - -internal fun PLens.Companion.user(): Lens = Lens( +internal fun PLens.Companion.user(): Lens = PLens( { user: User -> user.token }, { user: User, token: Token -> user.copy(token = token) } ) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TraversalTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TraversalTest.kt index 06b7d9c0076..f83db44314f 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TraversalTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/TraversalTest.kt @@ -2,12 +2,9 @@ package arrow.optics import arrow.optics.test.functionAToB import arrow.optics.test.option -import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.nonEmptyList -import arrow.optics.test.sequence -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.int @@ -15,28 +12,22 @@ import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.string +import kotlin.test.Test -class TraversalTest : StringSpec({ +class TraversalTest { + @Test fun traversalListLaws() = testLaws( - "Traversal list - ", TraversalLaws( traversal = Traversal.list(), aGen = Arb.list(Arb.int()), bGen = Arb.int(), funcGen = Arb.functionAToB(Arb.int()), - ), - - SetterLaws( - setter = Traversal.list(), - aGen = Arb.list(Arb.int()), - bGen = Arb.int(), - funcGen = Arb.functionAToB(Arb.int()), ) ) + @Test fun traversalNonEmptyListLaws() = testLaws( - "Traversal Nel - ", TraversalLaws( traversal = Traversal.nonEmptyList(), aGen = Arb.nonEmptyList(Arb.int()), @@ -45,19 +36,19 @@ class TraversalTest : StringSpec({ ) ) + @Test fun traversalSequenceLaws() = testLaws( - "Traversal sequence - ", TraversalLaws( traversal = Traversal.sequence(), - aGen = Arb.sequence(Arb.int()), + aGen = Arb.list(Arb.int()).map { it.asSequence() }, bGen = Arb.int(), funcGen = Arb.functionAToB(Arb.int()), eq = { a, b -> a.toList() == b.toList() } ) ) + @Test fun traversalMapLaws() = testLaws( - "Traversal map - ", TraversalLaws( traversal = Traversal.map(), aGen = Arb.map(Arb.int(), Arb.long()), @@ -66,8 +57,8 @@ class TraversalTest : StringSpec({ ) ) + @Test fun traversalOptionLaws() = testLaws( - "Traversal option - ", TraversalLaws( traversal = Traversal.option(), aGen = Arb.option(Arb.string()), @@ -76,8 +67,8 @@ class TraversalTest : StringSpec({ ) ) + @Test fun traversalStringLaws() = testLaws( - "Traversal string - ", TraversalLaws( traversal = Traversal.string(), aGen = Arb.string(), @@ -86,4 +77,4 @@ class TraversalTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/AtInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/AtInstanceTest.kt index ef5138dfdf7..d83a564d084 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/AtInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/AtInstanceTest.kt @@ -5,17 +5,18 @@ import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.option import arrow.optics.typeclasses.At -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.set +import kotlin.test.Test -class AtInstanceTest : StringSpec({ +class AtInstanceTest { + @Test + fun atMapLaws() = testLaws( - "At map - ", LensLaws( lensGen = Arb.long().map { At.map().at(it) }, aGen = Arb.map(Arb.long(), Arb.int()), @@ -24,8 +25,9 @@ class AtInstanceTest : StringSpec({ ) ) + @Test + fun atSetLaws() = testLaws( - "At set - ", LensLaws( lensGen = Arb.long().map { At.set().at(it) }, aGen = Arb.set(Arb.long()), @@ -33,4 +35,4 @@ class AtInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.boolean()), ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt index 4b07238130e..2b3cf3bb9d3 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/ConsInstanceTest.kt @@ -4,17 +4,18 @@ import arrow.optics.test.functionAToB import arrow.optics.test.laws.PrismLaws import arrow.optics.test.laws.testLaws import arrow.optics.typeclasses.Cons -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string +import kotlin.test.Test -class ConsInstanceTest : StringSpec({ +class ConsInstanceTest { + @Test + fun consListLaws() = testLaws( - "Const list - ", PrismLaws( prism = Cons.list().cons(), aGen = Arb.list(Arb.int()), @@ -23,8 +24,9 @@ class ConsInstanceTest : StringSpec({ ) ) + @Test + fun consStringLaws() = testLaws( - "Cons string - ", PrismLaws( prism = Cons.string().cons(), aGen = Arb.string(), @@ -32,4 +34,4 @@ class ConsInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.pair(Arb.char(), Arb.string())), ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt index 8a6d2c33eb7..da75829afb0 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/EitherInstanceTest.kt @@ -5,12 +5,14 @@ import arrow.optics.test.either import arrow.optics.test.functionAToB import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.string +import kotlin.test.Test -class EitherInstanceTest : StringSpec({ +class EitherInstanceTest { + @Test + fun eitherLaws() = testLaws( TraversalLaws( traversal = Traversal.either(), @@ -19,4 +21,4 @@ class EitherInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.int()), ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt index 97d492c464a..e8765846ec1 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/FilterIndexInstanceTest.kt @@ -4,20 +4,20 @@ import arrow.optics.test.functionAToB import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.nonEmptyList -import arrow.optics.test.sequence import arrow.optics.typeclasses.FilterIndex -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.string +import kotlin.test.Test -class FilterIndexInstanceTest : StringSpec({ +class FilterIndexInstanceTest { + @Test + fun filterIndexListLaws() = testLaws( - "FilterIndex list - ", TraversalLaws( traversal = FilterIndex.list().filter { true }, aGen = Arb.list(Arb.int()), @@ -26,18 +26,20 @@ class FilterIndexInstanceTest : StringSpec({ ) ) + @Test + fun filterIndexSequenceLaws() = testLaws( - "FilterIndex sequence - ", TraversalLaws( traversal = FilterIndex.sequence().filter { true }, - aGen = Arb.sequence(Arb.int()), + aGen = Arb.list(Arb.int()).map { it.asSequence() }, bGen = Arb.int(), funcGen = Arb.functionAToB(Arb.int()), ) { a, b -> a.toList() == b.toList() } ) + @Test + fun filterIndexNonEmptyListLaws() = testLaws( - "FilterIndex Nel - ", TraversalLaws( traversal = FilterIndex.nonEmptyList().filter { true }, aGen = Arb.nonEmptyList(Arb.int()), @@ -46,8 +48,9 @@ class FilterIndexInstanceTest : StringSpec({ ) ) + @Test + fun filterIndexMapLaws() = testLaws( - "FilterIndex map - ", TraversalLaws( traversal = FilterIndex.map().filter { true }, aGen = Arb.map(Arb.char(), Arb.int()), @@ -56,8 +59,9 @@ class FilterIndexInstanceTest : StringSpec({ ) ) + @Test + fun filterIndexStringLaws() = testLaws( - "FilterIndex string - ", TraversalLaws( traversal = FilterIndex.string().filter { true }, aGen = Arb.string(), @@ -65,4 +69,4 @@ class FilterIndexInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.char()), ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt index 733c1d36e9d..e0e1e4efde1 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/IndexInstanceTest.kt @@ -4,10 +4,7 @@ import arrow.optics.test.functionAToB import arrow.optics.test.nonEmptyList import arrow.optics.test.laws.OptionalLaws import arrow.optics.test.laws.testLaws -import arrow.optics.test.sequence import arrow.optics.typeclasses.Index -import io.kotest.assertions.fail -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.int @@ -15,11 +12,13 @@ import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.string +import kotlin.test.Test -class IndexInstanceTest : StringSpec({ +class IndexInstanceTest { + @Test + fun indexListLaws() = testLaws( - "Index list - ", OptionalLaws( optionalGen = Arb.int().map { Index.list().index(it) }, aGen = Arb.list(Arb.long()), @@ -28,19 +27,21 @@ class IndexInstanceTest : StringSpec({ ) ) + @Test + fun indexSequenceLaws() = testLaws( - "Index sequence - ", OptionalLaws( optionalGen = Arb.int().map { Index.sequence().index(it) }, - aGen = Arb.sequence(Arb.long()), + aGen = Arb.list(Arb.long()).map { it.asSequence() }, bGen = Arb.long(), funcGen = Arb.functionAToB(Arb.long()), eqa = { a, b -> a.toList() == b.toList() } ) ) + @Test + fun indexMapLaws() = testLaws( - "Index map - ", OptionalLaws( optionalGen = Arb.int().map { Index.list().index(it) }, aGen = Arb.list(Arb.long()), @@ -49,8 +50,9 @@ class IndexInstanceTest : StringSpec({ ) ) + @Test + fun indexNonEmptyListLaws() = testLaws( - "Index Nel - ", OptionalLaws( optionalGen = Arb.int().map { Index.nonEmptyList().index(it) }, aGen = Arb.nonEmptyList(Arb.long()), @@ -59,8 +61,9 @@ class IndexInstanceTest : StringSpec({ ) ) + @Test + fun indexStringLaws() = testLaws( - "Index string - ", OptionalLaws( optionalGen = Arb.int().map { Index.string().index(it) }, aGen = Arb.string(), @@ -69,4 +72,4 @@ class IndexInstanceTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt index 7eb5059a95e..403b38c17b5 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/instances/SnocInstanceTest.kt @@ -4,17 +4,18 @@ import arrow.optics.test.functionAToB import arrow.optics.test.laws.PrismLaws import arrow.optics.test.laws.testLaws import arrow.optics.typeclasses.Snoc -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string +import kotlin.test.Test -class SnocInstanceTest : StringSpec({ +class SnocInstanceTest { + @Test + fun snocListLaws() = testLaws( - "Snoc list - ", PrismLaws( prism = Snoc.list().snoc(), aGen = Arb.list(Arb.int()), @@ -22,8 +23,10 @@ class SnocInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.pair(Arb.list(Arb.int()), Arb.int())), ) ) + + @Test + fun snocStringLaws() = testLaws( - "Snoc string - ", PrismLaws( prism = Snoc.string().snoc(), aGen = Arb.string(), @@ -31,4 +34,4 @@ class SnocInstanceTest : StringSpec({ funcGen = Arb.functionAToB(Arb.pair(Arb.string(), Arb.char())), ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/EitherTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/EitherTest.kt deleted file mode 100644 index 826724f0fe1..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/EitherTest.kt +++ /dev/null @@ -1,23 +0,0 @@ -package arrow.optics.std - -import arrow.optics.Iso -import arrow.optics.test.either -import arrow.optics.test.functionAToB -import arrow.optics.test.laws.IsoLaws -import arrow.optics.test.laws.testLaws -import arrow.optics.test.validated -import io.kotest.core.spec.style.StringSpec -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.string - -class EitherTest : StringSpec({ - testLaws( - IsoLaws( - iso = Iso.eitherToValidated(), - aGen = Arb.either(Arb.string(), Arb.int()), - bGen = Arb.validated(Arb.string(), Arb.int()), - funcGen = Arb.functionAToB(Arb.validated(Arb.string(), Arb.int())), - ) - ) -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ListTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ListTest.kt index 8c33e48eee8..6af753918ff 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ListTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ListTest.kt @@ -5,20 +5,20 @@ import arrow.optics.Optional import arrow.optics.test.functionAToB import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.OptionalLaws -import arrow.optics.test.laws.SetterLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.nonEmptyList import arrow.optics.test.option -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list +import kotlin.test.Test -class ListTest : StringSpec({ +class ListTest { + @Test + fun headLaws() = testLaws( - "Optional list head - ", OptionalLaws( optional = Optional.listHead(), aGen = Arb.list(Arb.int()), @@ -30,17 +30,12 @@ class ListTest : StringSpec({ aGen = Arb.list(Arb.int()), bGen = Arb.int(), funcGen = Arb.functionAToB(Arb.int()), - ), - SetterLaws( - setter = Optional.listHead(), - aGen = Arb.list(Arb.int()), - bGen = Arb.int(), - funcGen = Arb.functionAToB(Arb.int()), ) ) + @Test + fun tailLaws() = testLaws( - "Optional list tail - ", OptionalLaws( optional = Optional.listTail(), aGen = Arb.list(Arb.int()), @@ -49,8 +44,9 @@ class ListTest : StringSpec({ ) ) + @Test + fun isoToOptionNelLaws() = testLaws( - "Iso list to Option Nel - ", IsoLaws( iso = Iso.listToOptionNel(), aGen = Arb.list(Arb.int()), @@ -59,4 +55,4 @@ class ListTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/MapTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/MapTest.kt index 1fff498bdb1..67f4eee46ac 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/MapTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/MapTest.kt @@ -4,23 +4,23 @@ import arrow.optics.Iso import arrow.optics.test.functionAToB import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.constant -import io.kotest.property.arbitrary.long import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.set import io.kotest.property.arbitrary.string +import kotlin.test.Test -class MapTest : StringSpec({ +class MapTest { - testLaws( - IsoLaws( - iso = Iso.mapToSet(), - aGen = Arb.map(Arb.long(), Arb.constant(Unit)), - bGen = Arb.set(Arb.long()), - funcGen = Arb.functionAToB(Arb.set(Arb.long())), - ) + @Test + fun mapToSetLaws() = testLaws( + IsoLaws( + iso = Iso.mapToSet(), + aGen = Arb.map(Arb.string(), Arb.constant(Unit), maxSize = 20), + bGen = Arb.set(Arb.string(), range = 0 .. 20), + funcGen = Arb.functionAToB(Arb.set(Arb.string(), range = 0 .. 20)), ) + ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/NonEmptyListTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/NonEmptyListTest.kt index c6d7f48aa02..878aee071c0 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/NonEmptyListTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/NonEmptyListTest.kt @@ -5,16 +5,16 @@ import arrow.optics.test.functionAToB import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.nonEmptyList -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list -import io.kotest.property.arbitrary.string +import kotlin.test.Test -class NonEmptyListTest : StringSpec({ +class NonEmptyListTest { + @Test + fun headLaws() = testLaws( - "Lens Nel head - ", LensLaws( lens = Lens.nonEmptyListHead(), aGen = Arb.nonEmptyList(Arb.int()), @@ -23,8 +23,8 @@ class NonEmptyListTest : StringSpec({ ) ) + @Test fun tailLaws() = testLaws( - "Lens Nel tail - ", LensLaws( lens = Lens.nonEmptyListTail(), aGen = Arb.nonEmptyList(Arb.int()), @@ -33,4 +33,4 @@ class NonEmptyListTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/OptionTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/OptionTest.kt index f00588377c4..15705124bdf 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/OptionTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/OptionTest.kt @@ -8,16 +8,17 @@ import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.PrismLaws import arrow.optics.test.laws.testLaws import arrow.optics.test.option -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.constant import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.orNull +import kotlin.test.Test -class OptionTest : StringSpec({ +class OptionTest { + @Test + fun someLaws() = testLaws( - "Prism some - ", PrismLaws( prism = Prism.some(), aGen = Arb.option(Arb.int()), @@ -26,8 +27,9 @@ class OptionTest : StringSpec({ ) ) + @Test + fun noneLaws() = testLaws( - "Prism none - ", PrismLaws( prism = Prism.none(), aGen = Arb.option(Arb.int()), @@ -36,8 +38,9 @@ class OptionTest : StringSpec({ ) ) + @Test + fun isoToNullable() = testLaws( - "Iso option to nullable - ", IsoLaws( iso = Iso.optionToNullable().reverse(), aGen = Arb.int().orNull(), @@ -46,8 +49,9 @@ class OptionTest : StringSpec({ ) ) + @Test + fun isoToEither() = testLaws( - "Iso option to either - ", IsoLaws( iso = Iso.optionToEither(), aGen = Arb.option(Arb.int()), @@ -56,4 +60,4 @@ class OptionTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/StringTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/StringTest.kt index 9703d4d3453..1d4162ba971 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/StringTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/StringTest.kt @@ -3,17 +3,18 @@ package arrow.optics.std import arrow.optics.Iso import arrow.optics.test.laws.IsoLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec import io.kotest.property.Arb import io.kotest.property.arbitrary.char import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.string +import kotlin.test.Test -class StringTest : StringSpec({ +class StringTest { + @Test + fun isoToList() = testLaws( - "Iso string to list - ", IsoLaws( iso = Iso.stringToList(), aGen = Arb.string(), @@ -22,4 +23,4 @@ class StringTest : StringSpec({ ) ) -}) +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/TupleTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/TupleTest.kt index 31710b47ebb..e250dd58b50 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/TupleTest.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/TupleTest.kt @@ -6,18 +6,25 @@ import arrow.optics.test.functionAToB import arrow.optics.test.laws.LensLaws import arrow.optics.test.laws.TraversalLaws import arrow.optics.test.laws.testLaws -import io.kotest.core.spec.style.StringSpec +import arrow.optics.test.tuple4 +import arrow.optics.test.tuple5 +import arrow.optics.test.tuple6 +import arrow.optics.test.tuple7 +import arrow.optics.test.tuple8 +import arrow.optics.test.tuple9 import io.kotest.property.Arb import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.pair import io.kotest.property.arbitrary.string import io.kotest.property.arbitrary.triple +import kotlin.test.Test -class TupleTest : StringSpec({ +class TupleTest { + @Test + fun firstLaws() = testLaws( - "Lens pair first - ", LensLaws( lens = Lens.pairFirst(), aGen = Arb.pair(Arb.int(), Arb.string()), @@ -26,8 +33,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun secondLaws() = testLaws( - "Lens pair second - ", LensLaws( lens = Lens.pairSecond(), aGen = Arb.pair(Arb.int(), Arb.string()), @@ -36,8 +44,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun tripleFirstLaws() = testLaws( - "Lens triple first - ", LensLaws( lens = Lens.tripleFirst(), aGen = Arb.triple(Arb.int(), Arb.string(), Arb.string()), @@ -46,8 +55,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun tripleSecondLaws() = testLaws( - "Lens triple second - ", LensLaws( lens = Lens.tripleSecond(), aGen = Arb.triple(Arb.int(), Arb.string(), Arb.int()), @@ -56,8 +66,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun tripleThirdLaws() = testLaws( - "Lens triple third - ", LensLaws( lens = Lens.tripleThird(), aGen = Arb.triple(Arb.int(), Arb.int(), Arb.string()), @@ -66,8 +77,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun pairLaws() = testLaws( - "Traversal pair - ", TraversalLaws( traversal = Traversal.pair(), aGen = Arb.pair(Arb.boolean(), Arb.boolean()), @@ -76,8 +88,9 @@ class TupleTest : StringSpec({ ) ) + @Test + fun tripleLaws() = testLaws( - "Traversal triple - ", TraversalLaws( traversal = Traversal.triple(), aGen = Arb.triple(Arb.boolean(), Arb.boolean(), Arb.boolean()), @@ -86,4 +99,97 @@ class TupleTest : StringSpec({ ) ) -}) + @Test + fun tuple4Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple4(), + aGen = Arb.tuple4(Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean()), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.boolean()), + ) + ) + + @Test + fun tuple5Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple5(), + aGen = Arb.tuple5(Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean()), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.boolean()), + ) + ) + + @Test + fun tuple6Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple6(), + aGen = Arb.tuple6(Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean(), Arb.boolean()), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.boolean()), + ) + ) + + @Test + fun tuple7Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple7(), + aGen = Arb.tuple7( + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean() + ), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.boolean()), + ) + ) + + @Test + fun tuple8Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple8(), + aGen = Arb.tuple8( + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean() + ), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.boolean()), + ) + ) + + @Test + fun tuple9Laws() = + testLaws( + TraversalLaws( + traversal = Traversal.tuple9(), + aGen = Arb.tuple9( + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean(), + Arb.boolean() + ), + bGen = Arb.boolean(), + funcGen = Arb.functionAToB(Arb.int()), + ) + ) + +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ValidatedTest.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ValidatedTest.kt deleted file mode 100644 index 0b58be4a2de..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/std/ValidatedTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package arrow.optics.std - -import arrow.optics.Iso -import arrow.optics.test.either -import arrow.optics.test.functionAToB -import arrow.optics.test.laws.IsoLaws -import arrow.optics.test.laws.testLaws -import arrow.optics.test.validated -import io.kotest.core.spec.style.StringSpec -import io.kotest.property.Arb -import io.kotest.property.arbitrary.int -import io.kotest.property.arbitrary.string - -class ValidatedTest : StringSpec({ - - testLaws( - "Iso validated to either - ", - IsoLaws( - iso = Iso.validatedToEither(), - aGen = Arb.validated(Arb.string(), Arb.int()), - bGen = Arb.either(Arb.string(), Arb.int()), - funcGen = Arb.functionAToB(Arb.either(Arb.string(), Arb.int())), - ) - ) - -}) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt index 827fc09bd1d..0d3ddd5ed4e 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt @@ -3,7 +3,13 @@ package arrow.optics.test import arrow.core.Either import arrow.core.NonEmptyList import arrow.core.Option -import arrow.core.Validated +import arrow.core.Tuple4 +import arrow.core.Tuple5 +import arrow.core.Tuple6 +import arrow.core.Tuple7 +import arrow.core.Tuple8 +import arrow.core.Tuple9 +import arrow.core.toNonEmptyListOrNull import arrow.core.toOption import io.kotest.property.Arb import io.kotest.property.arbitrary.bind @@ -11,9 +17,10 @@ import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.orNull +import kotlin.math.max fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.bind(arb, Arb.list(arb, range), ::NonEmptyList) + Arb.list(arb, max(range.first, 1) .. range.last).map { it.toNonEmptyListOrNull()!! } fun Arb.Companion.sequence(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, range).map { it.asSequence() } @@ -30,5 +37,65 @@ fun Arb.Companion.either(arbE: Arb, arbA: Arb): Arb> { return Arb.choice(arbLeft, arbRight) } -fun Arb.Companion.validated(arbE: Arb, arbA: Arb): Arb> = - Arb.either(arbE, arbA).map { Validated.fromEither(it) } +fun Arb.Companion.tuple4( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, ::Tuple4) + +fun Arb.Companion.tuple5( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, ::Tuple5) + +fun Arb.Companion.tuple6( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, ::Tuple6) + +fun Arb.Companion.tuple7( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, arbG, ::Tuple7) + +fun Arb.Companion.tuple8( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb, + arbH: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, arbG, arbH, ::Tuple8) + +fun Arb.Companion.tuple9( + arbA: Arb, + arbB: Arb, + arbC: Arb, + arbD: Arb, + arbE: Arb, + arbF: Arb, + arbG: Arb, + arbH: Arb, + arbI: Arb +): Arb> = + Arb.bind(arbA, arbB, arbC, arbD, arbE, arbF, arbG, arbH, arbI, ::Tuple9) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/IsoLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/IsoLaws.kt index b48664abd52..b1cac3fee70 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/IsoLaws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/IsoLaws.kt @@ -1,6 +1,5 @@ package arrow.optics.test.laws -import arrow.core.compose import arrow.core.identity import arrow.optics.Iso import io.kotest.property.Arb @@ -42,7 +41,7 @@ data class IsoLaws( private suspend fun Iso.composeModify(aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext = checkAll(100, aGen, funcGen, funcGen) { a, f, g -> - modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) + modify(modify(a, f), g).equalUnderTheLaw(modify(a) { g(f(it)) }, eq) } private suspend fun Iso.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/Laws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/Laws.kt index 4ecef3b4528..4c97cf56e6b 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/Laws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/Laws.kt @@ -1,39 +1,29 @@ package arrow.optics.test.laws import io.kotest.assertions.fail -import io.kotest.core.names.TestName -import io.kotest.core.spec.style.StringSpec -import io.kotest.core.spec.style.scopes.StringSpecScope -import io.kotest.core.spec.style.scopes.addTest -import io.kotest.core.test.TestContext +import io.kotest.assertions.withClue +import kotlinx.coroutines.test.TestResult +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runTest interface LawSet { val laws: List } -data class Law(val name: String, val test: suspend TestContext.() -> Unit) +data class Law(val name: String, val test: suspend TestScope.() -> Unit) fun A.equalUnderTheLaw(b: A, f: (A, A) -> Boolean = { x, y -> x == y }): Boolean = if (f(this, b)) true else fail("Found $this but expected: $b") -fun StringSpec.testLaws(vararg lawSets: LawSet): Unit = testLaws(lawSets.flatMap { it.laws }) +fun testLaws(vararg lawSets: LawSet): TestResult = testLaws(lawSets.flatMap { it.laws }) -fun StringSpec.testLaws(prefix: String, vararg lawSets: LawSet): Unit = testLaws(prefix, lawSets.flatMap { it.laws }) - -fun StringSpec.testLaws(vararg laws: List): Unit = laws - .flatMap { list: List -> list.asIterable() } - .distinctBy { law: Law -> law.name } - .forEach { law: Law -> - addTest(TestName(null, law.name, false), false, null) { - law.test(StringSpecScope(this.coroutineContext, testCase)) - } - } - -fun StringSpec.testLaws(prefix: String, vararg laws: List): Unit = laws - .flatMap { list: List -> list.asIterable() } - .distinctBy { law: Law -> law.name } - .forEach { law: Law -> - addTest(TestName(prefix, law.name, false), false, null) { - law.test(StringSpecScope(this.coroutineContext, testCase)) +fun testLaws(vararg laws: List): TestResult = runTest { + laws + .flatMap(List::asIterable) + .distinctBy(Law::name) + .forEach { law: Law -> + withClue("Testing ${law.name}") { + law.test(this@runTest) + } } - } +} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/LensLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/LensLaws.kt index 0b687d8db58..6d5cd7e93d7 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/LensLaws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/LensLaws.kt @@ -1,6 +1,5 @@ package arrow.optics.test.laws -import arrow.core.compose import arrow.core.identity import arrow.optics.Lens import io.kotest.property.Arb @@ -67,7 +66,7 @@ data class LensLaws( private suspend fun lensComposeModify(lensGen: Arb>, aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext = checkAll(100, lensGen, aGen, funcGen, funcGen) { lens, a, f, g -> lens.run { - modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) + modify(modify(a, f), g).equalUnderTheLaw(modify(a) { g(f(it)) }, eq) } } diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/OptionalLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/OptionalLaws.kt index 5bd11edd042..95c4e429b55 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/OptionalLaws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/OptionalLaws.kt @@ -1,6 +1,5 @@ package arrow.optics.test.laws -import arrow.core.compose import arrow.core.identity import arrow.optics.Optional import io.kotest.property.Arb @@ -94,7 +93,7 @@ data class OptionalLaws( checkAll(100, optionalGen, aGen, funcGen, funcGen) { optional, a, f, g -> optional.run { modify(modify(a, f), g) - .equalUnderTheLaw(modify(a, g compose f), eq) + .equalUnderTheLaw(modify(a) { g(f(it)) }, eq) } } diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/PrismLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/PrismLaws.kt index 64b41f5ea8d..aec60e8fa3d 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/PrismLaws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/PrismLaws.kt @@ -1,6 +1,5 @@ package arrow.optics.test.laws -import arrow.core.compose import arrow.core.identity import arrow.optics.Prism import io.kotest.property.Arb @@ -43,7 +42,7 @@ data class PrismLaws( private suspend fun Prism.composeModify(aGen: Arb, funcGen: Arb<(B) -> B>, eq: (A, A) -> Boolean): PropertyContext = checkAll(100, aGen, funcGen, funcGen) { a, f, g -> - modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) + modify(modify(a, f), g).equalUnderTheLaw(modify(a) { g(f(it)) }, eq) } private suspend fun Prism.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/SetterLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/SetterLaws.kt deleted file mode 100644 index 526e1b3c6b4..00000000000 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/SetterLaws.kt +++ /dev/null @@ -1,44 +0,0 @@ -package arrow.optics.test.laws - -import arrow.core.compose -import arrow.core.identity -import arrow.optics.Setter -import io.kotest.property.Arb -import io.kotest.property.PropertyContext -import io.kotest.property.checkAll - -data class SetterLaws( - val setter: Setter, - val aGen: Arb, - val bGen: Arb, - val funcGen: Arb<(B) -> B>, - val eq: (A, A) -> Boolean = { a, b -> a == b } -): LawSet { - - override val laws: List = listOf( - Law("Setter law: set is idempotent") { setter.setIdempotent(aGen, bGen, eq) }, - Law("Setter law: modify identity") { setter.modifyIdentity(aGen, eq) }, - Law("Setter law: compose modify") { setter.composeModify(aGen, eq, funcGen) }, - Law("Setter law: consistent set modify") { setter.consistentSetModify(aGen, bGen, eq) } - ) - - private suspend fun Setter.setIdempotent(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = - checkAll(100, aGen, bGen) { a, b -> - set(set(a, b), b).equalUnderTheLaw(set(a, b), eq) - } - - private suspend fun Setter.modifyIdentity(aGen: Arb, eq: (A, A) -> Boolean): PropertyContext = - checkAll(100, aGen) { a -> - modify(a, ::identity).equalUnderTheLaw(a, eq) - } - - private suspend fun Setter.composeModify(aGen: Arb, eq: (A, A) -> Boolean, funcGen: Arb<(B) -> B>): PropertyContext = - checkAll(100, aGen, funcGen, funcGen) { a, f, g -> - modify(modify(a, f), g).equalUnderTheLaw(modify(a, g compose f), eq) - } - - private suspend fun Setter.consistentSetModify(aGen: Arb, bGen: Arb, eq: (A, A) -> Boolean): PropertyContext = - checkAll(100, aGen, bGen) { a, b -> - modify(a) { b }.equalUnderTheLaw(set(a, b), eq) - } -} diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/TraversalLaws.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/TraversalLaws.kt index 152e7e62497..28c718856dc 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/TraversalLaws.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/laws/TraversalLaws.kt @@ -1,6 +1,5 @@ package arrow.optics.test.laws -import arrow.core.compose import arrow.core.identity import arrow.optics.Traversal import io.kotest.property.Arb @@ -45,6 +44,6 @@ data class TraversalLaws( funcGen ) { a, f, g -> modify(modify(a, f), g) - .equalUnderTheLaw(modify(a, g compose f), eq) + .equalUnderTheLaw(modify(a) { g(f(it)) }, eq) } } diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/examples/example-optional-01.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/examples/example-optional-01.kt index f9d299003a7..5cd0e6feab2 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/examples/example-optional-01.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/examples/example-optional-01.kt @@ -15,9 +15,9 @@ data class User(val username: String, val email: Option) { } } -fun main(args: Array) { +fun main() { val original = User("arrow-user", None) val set = User.email.set(original, "arRoW-UsEr@arrow-Kt.IO") - val modified = User.email.modify(set, String::toLowerCase) + val modified = User.email.modify(set, String::lowercase) println("original: $original, set: $set, modified: $modified") } diff --git a/arrow-libs/resilience/arrow-resilience/build.gradle.kts b/arrow-libs/resilience/arrow-resilience/build.gradle.kts index 0faa5d92e24..678b74b3a37 100644 --- a/arrow-libs/resilience/arrow-resilience/build.gradle.kts +++ b/arrow-libs/resilience/arrow-resilience/build.gradle.kts @@ -21,14 +21,13 @@ kotlin { api(projects.arrowCore) compileOnly(libs.kotlin.stdlib) implementation(libs.coroutines.core) - implementation("org.jetbrains.kotlin:kotlin-stdlib") } } commonTest { dependencies { implementation(projects.arrowFxCoroutines) + implementation(libs.kotlin.test) implementation(libs.coroutines.test) - implementation(kotlin("test")) } } } @@ -41,3 +40,7 @@ kotlin { } } } + +tasks.withType().configureEach { + useJUnitPlatform() +} diff --git a/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/CircuitBreaker.kt b/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/CircuitBreaker.kt index e348f127c4c..51a89feac7e 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/CircuitBreaker.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/CircuitBreaker.kt @@ -1,9 +1,7 @@ -@file:OptIn(ExperimentalTime::class) - package arrow.resilience +import arrow.atomic.Atomic import arrow.core.Either -import arrow.core.continuations.AtomicRef import arrow.core.identity import arrow.resilience.CircuitBreaker.State.Closed import arrow.resilience.CircuitBreaker.State.HalfOpen @@ -14,7 +12,6 @@ import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.withContext import kotlin.time.Duration import kotlin.time.Duration.Companion.nanoseconds -import kotlin.time.ExperimentalTime import kotlin.time.TimeMark import kotlin.time.TimeSource @@ -50,9 +47,7 @@ import kotlin.time.TimeSource * import arrow.resilience.CircuitBreaker * import kotlinx.coroutines.delay * import kotlin.time.Duration.Companion.seconds - * import kotlin.time.ExperimentalTime * - * @ExperimentalTime * suspend fun main(): Unit { * //sampleStart * val circuitBreaker = CircuitBreaker( @@ -92,9 +87,7 @@ import kotlin.time.TimeSource * import arrow.resilience.retry * import kotlinx.coroutines.delay * import kotlin.time.Duration.Companion.seconds - * import kotlin.time.ExperimentalTime * - * @ExperimentalTime * suspend fun main(): Unit { * suspend fun apiCall(): Unit { * println("apiCall . . .") @@ -134,7 +127,7 @@ import kotlin.time.TimeSource public class CircuitBreaker private constructor( - private val state: AtomicRef, + private val state: Atomic, private val resetTimeout: Duration, private val exponentialBackoffFactor: Double, private val maxResetTimeout: Duration, @@ -531,7 +524,7 @@ private constructor( "maxResetTimeout expected to be greater than ${Duration.ZERO}, but was $maxResetTimeout" } return CircuitBreaker( - state = AtomicRef(Closed(openingStrategy)), + state = Atomic(Closed(openingStrategy)), resetTimeout = resetTimeout, exponentialBackoffFactor = exponentialBackoffFactor, maxResetTimeout = maxResetTimeout, diff --git a/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/Saga.kt b/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/Saga.kt index 9ebda60fe2a..c38831bdd0a 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/Saga.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonMain/kotlin/arrow/resilience/Saga.kt @@ -1,7 +1,7 @@ package arrow.resilience -import arrow.core.continuations.AtomicRef -import arrow.core.continuations.updateAndGet +import arrow.atomic.Atomic +import arrow.atomic.updateAndGet import arrow.core.nonFatalOrThrow import kotlinx.coroutines.NonCancellable import kotlinx.coroutines.withContext @@ -84,6 +84,7 @@ public interface SagaScope { * By doing so we can guarantee that any transactional like operations made by the [Saga] will * guarantee that it results in the correct state. */ +@Suppress("NOTHING_TO_INLINE") public inline fun saga(noinline block: suspend SagaScope.() -> A): Saga = block /** Create a lazy [Saga] that will only run when the [Saga] is invoked. */ @@ -119,7 +120,7 @@ public object SagaActionStep // Internal implementation of the `saga { }` builder. @PublishedApi internal class SagaBuilder( - private val stack: AtomicRef Unit>> = AtomicRef(emptyList()) + private val stack: Atomic Unit>> = Atomic(emptyList()) ) : SagaScope { @SagaDSLMarker diff --git a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/CircuitBreakerTest.kt b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/CircuitBreakerTest.kt index 4a2125b058a..bebebdd2ddd 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/CircuitBreakerTest.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/CircuitBreakerTest.kt @@ -5,7 +5,6 @@ import arrow.resilience.CircuitBreaker.OpeningStrategy import arrow.resilience.CircuitBreaker.OpeningStrategy.SlidingWindow import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.test.runTest @@ -20,20 +19,18 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime import kotlin.time.TestTimeSource -@OptIn(ExperimentalTime::class, ExperimentalCoroutinesApi::class) class CircuitBreakerTest { - val dummy = RuntimeException("dummy") - val maxFailures = 5 - val exponentialBackoffFactor = 2.0 - val resetTimeout = 500.milliseconds - val maxTimeout = 1000.milliseconds + private val dummy = RuntimeException("dummy") + private val maxFailures = 5 + private val exponentialBackoffFactor = 2.0 + private val resetTimeout = 500.milliseconds + private val maxTimeout = 1000.milliseconds @Test fun shouldWorkForSuccessfulAsyncTasks(): TestResult = runTest { - val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures),) + val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures)) var effect = 0 val iterations = stackSafeIteration() Schedule.recurs(iterations.toLong()).repeat { @@ -44,7 +41,7 @@ class CircuitBreakerTest { @Test fun shouldWorkForSuccessfulImmediateTasks(): TestResult = runTest { - val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures),) + val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures)) var effect = 0 val iterations = stackSafeIteration() Schedule.recurs(iterations.toLong()).repeat { @@ -55,7 +52,7 @@ class CircuitBreakerTest { @Test fun staysClosedAfterLessThanMaxFailures(): TestResult = runTest { - val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures),) + val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures)) val result = recurAndCollect>(4).repeat { Either.catch { cb.protectOrThrow { throw dummy } } @@ -67,7 +64,7 @@ class CircuitBreakerTest { @Test fun closedCircuitBreakerResetsFailureCountAfterSuccess(): TestResult = runTest { - val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures),) + val cb = CircuitBreaker(resetTimeout = resetTimeout, openingStrategy = OpeningStrategy.Count(maxFailures)) val result = recurAndCollect>(4).repeat { Either.catch { cb.protectOrThrow { throw dummy } } diff --git a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/FlowTest.kt b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/FlowTest.kt index 17882ad0825..86e8d99ba7a 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/FlowTest.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/FlowTest.kt @@ -15,10 +15,8 @@ import kotlin.test.assertFailsWith import kotlin.test.assertTrue import kotlin.test.fail import kotlin.time.Duration.Companion.milliseconds -import kotlin.time.ExperimentalTime @OptIn(ExperimentalCoroutinesApi::class) -@ExperimentalTime class FlowTest { @Test diff --git a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/SagaSpec.kt b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/SagaSpec.kt index 63b25e7c307..b6ae2ae121d 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/SagaSpec.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/SagaSpec.kt @@ -14,7 +14,6 @@ import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.fail -@OptIn(ExperimentalCoroutinesApi::class) @Suppress("unused") class SagaSpec { diff --git a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/ScheduleTest.kt b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/ScheduleTest.kt index b6a1574478a..db290885e27 100644 --- a/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/ScheduleTest.kt +++ b/arrow-libs/resilience/arrow-resilience/src/commonTest/kotlin/arrow/resilience/ScheduleTest.kt @@ -20,7 +20,6 @@ import kotlin.time.Duration import kotlin.time.Duration.Companion.ZERO import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime internal data class SideEffect(var counter: Int = 0) { fun increment() { @@ -28,8 +27,6 @@ internal data class SideEffect(var counter: Int = 0) { } } -@ExperimentalTime -@Suppress("UNREACHABLE_CODE", "UNUSED_VARIABLE") class ScheduleTest { class MyException : Exception() @@ -337,19 +334,16 @@ fun Schedule.Decision.delay(): Duration? = when (this) { is Done -> null } -@ExperimentalTime private fun fibs(one: Duration): Sequence = generateSequence(Pair(one, one)) { (a, b) -> Pair(b, (a + b)) }.map { it.first } -@ExperimentalTime private fun exp(base: Duration): Sequence = generateSequence(Pair(base, 1.0)) { (_, n) -> Pair(base * 2.0.pow(n), n + 1) }.map { it.first } -@ExperimentalTime private fun linear(base: Duration): Sequence = generateSequence(Pair(base, 1.0)) { (_, n) -> Pair((base * n), (n + 1)) diff --git a/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt b/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt index 0f646f65684..68469f2fdfe 100644 --- a/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt +++ b/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-01.kt @@ -5,9 +5,7 @@ import arrow.core.Either import arrow.resilience.CircuitBreaker import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -@ExperimentalTime suspend fun main(): Unit { val circuitBreaker = CircuitBreaker( resetTimeout = 2.seconds, diff --git a/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt b/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt index 9aaace53da3..5611e480b01 100644 --- a/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt +++ b/arrow-libs/resilience/arrow-resilience/src/jvmTest/kotlin/examples/example-circuitbreaker-02.kt @@ -7,9 +7,7 @@ import arrow.resilience.Schedule import arrow.resilience.retry import kotlinx.coroutines.delay import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -@ExperimentalTime suspend fun main(): Unit { suspend fun apiCall(): Unit { println("apiCall . . .") diff --git a/arrow-libs/stack/build.gradle.kts b/arrow-libs/stack/build.gradle.kts index d8c336f8172..59d50419fec 100644 --- a/arrow-libs/stack/build.gradle.kts +++ b/arrow-libs/stack/build.gradle.kts @@ -14,12 +14,12 @@ dependencies { api("io.arrow-kt:arrow-atomic:$version") api("io.arrow-kt:arrow-autoclose:$version") api("io.arrow-kt:arrow-cache4k:$version") - api("io.arrow-kt:arrow-continuations:$version") api("io.arrow-kt:arrow-core:$version") api("io.arrow-kt:arrow-core-high-arity:$version") api("io.arrow-kt:arrow-core-retrofit:$version") api("io.arrow-kt:arrow-core-serialization:$version") api("io.arrow-kt:arrow-eval:$version") + api("io.arrow-kt:arrow-functions:$version") api("io.arrow-kt:arrow-collectors:$version") api("io.arrow-kt:arrow-fx-coroutines:$version") api("io.arrow-kt:arrow-fx-stm:$version") diff --git a/build.gradle.kts b/build.gradle.kts index 033f799272c..f45928a16f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,7 +40,6 @@ plugins { alias(libs.plugins.android.library) apply false alias(libs.plugins.dokka) alias(libs.plugins.animalSniffer) apply false - alias(libs.plugins.kotest.multiplatform) apply false alias(libs.plugins.kotlinx.kover) alias(libs.plugins.kotlin.multiplatform) apply false alias(libs.plugins.kotlinx.serialization) apply false @@ -67,11 +66,11 @@ configure { dependencies { kover(projects.arrowAtomic) - kover(projects.arrowContinuations) kover(projects.arrowCore) kover(projects.arrowCoreHighArity) kover(projects.arrowCoreRetrofit) kover(projects.arrowCoreSerialization) + kover(projects.arrowFunctions) kover(projects.arrowFxCoroutines) kover(projects.arrowFxStm) kover(projects.arrowOptics) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8a6bbd01e9d..3b54dbfeb00 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,10 @@ [versions] animalSniffer = "1.7.1" arrowGradleConfig = "0.12.0-rc.24" -assertj = "3.25.3" coroutines = "1.8.0" classgraph = "4.8.172" dokka = "1.9.20" -jUnit = "4.13.2" -jUnitJupiter = "5.10.2" -jUnitVintage = "5.10.2" kotest = "5.8.1" -kotestGradle = "5.8.1" kover = "0.7.6" kotlin = "1.9.23" kotlinxSerializationPlugin = "1.9.23" @@ -31,14 +26,8 @@ cache4k = "0.13.0" [libraries] coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "coroutines" } -jUnitJUnit = { module = "junit:junit", version.ref = "jUnit" } -jUnitVintageEngine = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "jUnitVintage" } -junitJupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "jUnitJupiter" } -junitJupiterEngine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "jUnitJupiter" } 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-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect" } kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test" } @@ -53,7 +42,6 @@ squareup-retrofit-converter-kotlinxSerialization = { module = "com.squareup.retr squareup-moshi-kotlin = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" } ksp = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "kspVersion" } kspGradlePlugin = { module = "com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin", version.ref = "kspVersion" } -assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } classgraph = { module = "io.github.classgraph:classgraph", version.ref = "classgraph" } compose-runtime = { module = "androidx.compose.runtime:runtime", version.ref = "compose" } kotlinCompileTesting = { module = "dev.zacsweers.kctfork:core", version.ref = "kotlinCompileTesting" } @@ -68,7 +56,6 @@ arrowGradleConfig-nexus = { id = "io.arrow-kt.arrow-gradle-config-nexus", versio arrowGradleConfig-publish = { id = "io.arrow-kt.arrow-gradle-config-publish", version.ref = "arrowGradleConfig" } arrowGradleConfig-versioning = { id = "io.arrow-kt.arrow-gradle-config-versioning", version.ref = "arrowGradleConfig" } dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } -kotest-multiplatform = { id = "io.kotest.multiplatform", version.ref = "kotestGradle" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlin-binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "kotlinBinaryCompatibilityValidator" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 8ca60b32cb5..3fcebadcb2c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,7 +17,7 @@ pluginManagement { } plugins { - id("com.gradle.enterprise") version "3.17.2" + id("com.gradle.develocity") version "3.17.2" id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0") } @@ -58,15 +58,15 @@ project(":arrow-annotations").projectDir = file("arrow-libs/core/arrow-annotatio include("arrow-core") project(":arrow-core").projectDir = file("arrow-libs/core/arrow-core") +include("arrow-functions") +project(":arrow-functions").projectDir = file("arrow-libs/core/arrow-functions") + include("arrow-core-high-arity") project(":arrow-core-high-arity").projectDir = file("arrow-libs/core/arrow-core-high-arity") include("arrow-atomic") project(":arrow-atomic").projectDir = file("arrow-libs/core/arrow-atomic") -include("arrow-continuations") -project(":arrow-continuations").projectDir = file("arrow-libs/core/arrow-continuations") - include("arrow-eval") project(":arrow-eval").projectDir = file("arrow-libs/core/arrow-eval") @@ -114,9 +114,9 @@ project(":arrow-optics-ksp-plugin").projectDir = file("arrow-libs/optics/arrow-o include("arrow-stack") project(":arrow-stack").projectDir = file("arrow-libs/stack") -gradleEnterprise { +develocity { buildScan { - termsOfServiceUrl = "https://gradle.com/terms-of-service" - termsOfServiceAgree = "yes" + termsOfUseUrl = "https://gradle.com/terms-of-service" + termsOfUseAgree = "yes" } }