diff --git a/.github/workflows/generate-alpha-tag.yaml b/.github/workflows/generate-alpha-tag.yaml index e9d693b807d..6315f758a8a 100644 --- a/.github/workflows/generate-alpha-tag.yaml +++ b/.github/workflows/generate-alpha-tag.yaml @@ -6,7 +6,7 @@ on: - main env: - GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" jobs: check: diff --git a/.github/workflows/generate-tag.yaml b/.github/workflows/generate-tag.yaml index 8d9138c84d5..0eabd7ef031 100644 --- a/.github/workflows/generate-tag.yaml +++ b/.github/workflows/generate-tag.yaml @@ -26,7 +26,7 @@ on: - 'auto' env: - GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" jobs: check: diff --git a/.github/workflows/githubpages.yaml b/.github/workflows/githubpages.yaml new file mode 100644 index 00000000000..1ca498df61e --- /dev/null +++ b/.github/workflows/githubpages.yaml @@ -0,0 +1,29 @@ +name: githubpages + +on: + push: + branches: + - main + +env: + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + +jobs: + githubpages: + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Dokka + id: Dokka + run: ./gradlew cleanDocs dokkaHtmlMultiModule -Pgithubpages=true + + - name: Deploy to gh-pages + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./docs diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 5c7aa999eb9..43b28036704 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -7,7 +7,7 @@ on: 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" + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -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 }} @@ -88,7 +88,7 @@ jobs: - name: Create API doc uses: gradle/gradle-build-action@v2 with: - arguments: -Pkotlin.mpp.enableCompatibilityMetadataVariant=true dokkaGfm + arguments: -Pkotlin.mpp.enableCompatibilityMetadataVariant=true cleanDocs dokkaHtmlMultiModule - name: Build release directory (/docs) working-directory: arrow-site diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index e0ebc4e9e4b..6293d4fa2ae 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -3,7 +3,8 @@ name: "pull_request" on: pull_request env: - GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + GRADLE_OPTS: -Dorg.gradle.daemon=false -Dorg.gradle.kotlin.dsl.internal.io.timeout=120000 -Dorg.gradle.jvmargs="-Xmx5g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError -XX:+UseParallelGC -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" + jobs: ios_watchos: diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index ce23b2fd33c..f89abf6a019 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -161,6 +161,7 @@ public abstract class arrow/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 final fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; @@ -188,6 +189,8 @@ public abstract class arrow/core/Either { 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; @@ -298,6 +301,7 @@ public final class arrow/core/EitherKt { 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; @@ -316,7 +320,6 @@ public final class arrow/core/EitherKt { 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 toEitherNel (Ljava/lang/Object;)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; @@ -621,6 +624,8 @@ public final class arrow/core/IterableKt { public static final fun firstOrNone (Ljava/lang/Iterable;)Larrow/core/Option; public static final fun firstOrNone (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun flatten (Ljava/lang/Iterable;)Ljava/util/List; + public static final fun flattenNelOrAccumulate (Ljava/lang/Iterable;)Larrow/core/Either; + public static final fun flattenNelOrAccumulate (Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; 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; @@ -703,8 +708,11 @@ public final class arrow/core/MapKt { 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 mapOrAccumulate (Ljava/util/Map;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; + public static final fun mapOrAccumulate (Ljava/util/Map;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; 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/Function3;)Ljava/util/Map; public static final fun salign (Ljava/util/Map;Larrow/typeclasses/Semigroup;Ljava/util/Map;)Ljava/util/Map; @@ -795,6 +803,8 @@ public final class arrow/core/NonEmptyList$Companion { 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; @@ -991,6 +1001,8 @@ public final class arrow/core/OptionKt { 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; @@ -1548,6 +1560,8 @@ public final class arrow/core/SequenceKt { 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; public static final fun many (Lkotlin/sequences/Sequence;)Lkotlin/sequences/Sequence; + public static final fun mapOrAccumulate (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; + public static final fun mapOrAccumulate (Lkotlin/sequences/Sequence;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; 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; @@ -3205,11 +3219,9 @@ public final class arrow/core/raise/DefaultRaise : arrow/core/raise/Raise { public fun ()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/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -3230,11 +3242,9 @@ public final class arrow/core/raise/IorRaise : arrow/core/raise/Raise, arrow/typ 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/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -3256,21 +3266,17 @@ public final class arrow/core/raise/NullableRaise : arrow/core/raise/Raise { public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun attempt-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Either;)Ljava/lang/Object; public static final fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Option;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Validated;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun bind-impl (Larrow/core/raise/Raise;Ljava/lang/Object;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final synthetic fun box-impl (Larrow/core/raise/Raise;)Larrow/core/raise/NullableRaise; @@ -3313,20 +3319,16 @@ public final class arrow/core/raise/OptionRaise : arrow/core/raise/Raise { public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun attempt-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Either;)Ljava/lang/Object; public static final fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Option;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Validated;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final synthetic fun box-impl (Larrow/core/raise/Raise;)Larrow/core/raise/OptionRaise; @@ -3368,11 +3370,9 @@ public final class arrow/core/raise/OptionRaise : arrow/core/raise/Raise { 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/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 catch (Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -3390,11 +3390,9 @@ public abstract interface class arrow/core/raise/Raise { 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/Option;Lkotlin/jvm/functions/Function2;)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;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 catch (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; @@ -3408,13 +3406,38 @@ public final class arrow/core/raise/Raise$DefaultImpls { 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 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 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 fun catch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public fun catch (Lkotlin/jvm/functions/Function2;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 fun raise (Ljava/lang/Object;)Ljava/lang/Void; + public fun recover (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun shift (Ljava/lang/Object;)Ljava/lang/Object; + public final fun withNel (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; +} + public abstract interface annotation class arrow/core/raise/RaiseDSL : java/lang/annotation/Annotation { } public final class arrow/core/raise/RaiseKt { public static final fun _fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun _foldOrThrow (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun catch (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun catch (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun catch (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function1; public static final fun catch (Lkotlin/jvm/functions/Function2;)Lkotlin/jvm/functions/Function2; public static final fun catch (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;)Lkotlin/jvm/functions/Function2; @@ -3427,10 +3450,15 @@ public final class arrow/core/raise/RaiseKt { public static final fun fold (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun fold (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun fold (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + 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/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 ior (Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;)Larrow/core/Ior; - public static final fun mapErrorNel (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun mapOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;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;)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 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; @@ -3438,8 +3466,8 @@ public final class arrow/core/raise/RaiseKt { 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 (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun recover (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)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; @@ -3447,9 +3475,7 @@ public final class arrow/core/raise/RaiseKt { 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; public static final fun toIor (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public static final fun toOption (Lkotlin/jvm/functions/Function1;)Larrow/core/Option; public static final fun toOption (Lkotlin/jvm/functions/Function1;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 toOption (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun toResult (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static final fun toResult (Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; @@ -3457,42 +3483,38 @@ public final class arrow/core/raise/RaiseKt { 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 zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;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;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;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;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;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/Function8;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;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/Function7;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Larrow/typeclasses/Semigroup;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function8;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function7;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function6;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; - public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function9;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function8;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function7;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;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/Function6;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;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/Function9;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;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/Function8;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;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/Function7;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;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/Function6;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function5;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;)Ljava/lang/Object; + public static final fun zipOrAccumulate (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; } public final class arrow/core/raise/ResultRaise : arrow/core/raise/Raise { public fun attempt (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun attempt-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun bind (Larrow/core/Either;)Ljava/lang/Object; - public fun bind (Larrow/core/Option;Lkotlin/jvm/functions/Function2;)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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)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 static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Either;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Option;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/Validated;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/EagerEffect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Larrow/core/continuations/Effect;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final fun bind-impl (Larrow/core/raise/Raise;Ljava/lang/Object;)Ljava/lang/Object; - public static fun bind-impl (Larrow/core/raise/Raise;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public static fun bind-impl (Larrow/core/raise/Raise;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static final synthetic fun box-impl (Larrow/core/raise/Raise;)Larrow/core/raise/ResultRaise; 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 ec972404117..198cfef509f 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 @@ -921,10 +921,10 @@ public sealed class Either { @Deprecated( NicheAPI + "Prefer when or fold instead", - ReplaceWith("MN.run { fold({ MN.empty().combine(f(it)) }, { MN.empty().combine(g(it)) }) }") + ReplaceWith("MN.run { fold({ empty().combine(f(it)) }, { empty().combine(g(it)) }) }") ) public inline fun bifoldMap(MN: Monoid, f: (A) -> C, g: (B) -> C): C = - MN.run { fold({ MN.empty().combine(f(it)) }, { MN.empty().combine(g(it)) }) } + MN.run { fold({ empty().combine(f(it)) }, { empty().combine(g(it)) }) } /** * Swap the generic parameters [A] and [B] of this [Either]. @@ -1083,6 +1083,13 @@ public sealed class Either { 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. @@ -1138,6 +1145,10 @@ public sealed class Either { return getOrElse { 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() /** @@ -1197,14 +1208,14 @@ public sealed class Either { public inline fun traverseNullable(fa: (B) -> C?): Either? = orNull()?.let(fa)?.right() - // TODO will be renamed to mapAccumulating in 2.x.x. Backport, and deprecate in 1.x.x + @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> = - when (this) { - is Right -> fa(this.value).map(::Right) - is Left -> this.valid() - } + 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> = @@ -1333,6 +1344,9 @@ public sealed class Either { public fun toValidated(): Validated = fold({ it.invalid() }, { it.valid() }) + public fun toIor(): Ior = + fold({ Ior.Left(it) }, { Ior.Right(it) }) + public companion object { @Deprecated( @@ -1944,6 +1958,13 @@ public sealed class Either { ) 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 } /** @@ -2596,7 +2617,7 @@ public const val RedundantAPI: String = public fun Either.toEitherNel(): EitherNel = mapLeft { nonEmptyListOf(it) } -public fun E.toEitherNel(): EitherNel = +public fun E.leftNel(): EitherNel = nonEmptyListOf(this).left() /** 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 89015278700..e44b03055c5 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 @@ -1,15 +1,22 @@ @file:Suppress("unused", "FunctionName") +/** + * + */ package arrow.core import arrow.core.Either.Left import arrow.core.Either.Right import arrow.core.raise.Raise +import arrow.core.raise.RaiseAccumulate import arrow.core.raise.either +import arrow.core.raise.fold +import arrow.core.raise.mapOrAccumulate import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import kotlin.Result.Companion.success import kotlin.experimental.ExperimentalTypeInference +import kotlin.jvm.JvmName public inline fun Iterable.zip( c: Iterable, @@ -339,49 +346,64 @@ public inline fun Iterable.traverseValidated( ): Validated> = traverse(semigroup, f) +@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> = - semigroup.run { - fold(Valid(ArrayList(collectionSizeOrDefault(10))) as Validated>) { acc, a -> - when (val res = f(a)) { - is Validated.Valid -> when (acc) { - is Valid -> acc.also { it.value.add(res.value) } - is Invalid -> acc - } - is Validated.Invalid -> when (acc) { - is Valid -> res - is Invalid -> Invalid(acc.value.combine(res.value)) - } - } - } - } + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() @Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(f)", "arrow.core.traverse")) public inline fun Iterable.traverseValidated(f: (A) -> ValidatedNel): ValidatedNel> = traverse(f) +@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> = - traverse(Semigroup.nonEmptyList(), f) + mapOrAccumulate { f(it).bindNel() }.toValidated() @Deprecated("sequenceValidated is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence(semigroup)", "arrow.core.sequence")) public fun Iterable>.sequenceValidated(semigroup: Semigroup): Validated> = sequence(semigroup) +@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> = - traverse(semigroup, ::identity) + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated() @Deprecated("sequenceValidated is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence()", "arrow.core.sequence")) public fun Iterable>.sequenceValidated(): ValidatedNel> = sequence() +@Deprecated( + ValidatedDeprMsg + "Use the mapOrAccumulate API instead", + ReplaceWith( + "mapOrAccumulate, A> { it.bindNel() }.toValidated()", + "arrow.core.mapOrAccumulate" + ) +) public fun Iterable>.sequence(): ValidatedNel> = - traverse(Semigroup.nonEmptyList(), ::identity) + mapOrAccumulate { it.bindNel() }.toValidated() @Deprecated("traverseOption is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(f)", "arrow.core.traverse")) public inline fun Iterable.traverseOption(f: (A) -> Option): Option> = @@ -431,94 +453,107 @@ public fun Iterable.sequenceNullable(): List? = sequence() /** - * 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. - * The [combine] function is used to accumulate all the _logical errors_. + * 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_. + * + * Within this DSL you can `bind` both [Either], and [EitherNel] values and invoke [Raise] based function of _logical error_ type [Error]. Let's see an example of all the different cases: + * + * ```kotlin + * fun test() { + * listOf(1, 2, 3, 4).mapOrAccumulate({ a, b -> "$a, $b" }) { i -> + * when(i) { + * 1 -> "Either - $i".left().bind() + * 2 -> "EitherNel - $i".leftNel().bindNel() + * 3 -> raise("Raise - $i") + * else -> withNel { raise(nonEmptyListOf("RaiseNel - $i")) } + * } + * } shouldBe "Either - 1, EitherNel - 2, Raise - 3, RaiseNel - 4".left() + * } + * ``` + * + * */ @OptIn(ExperimentalTypeInference::class) public inline fun Iterable.mapOrAccumulate( combine: (Error, Error) -> Error, - @BuilderInference transform: Raise.(A) -> B, -): Either> = - fold>>(Right(ArrayList(collectionSizeOrDefault(10)))) { acc, a -> - when (val res = either { transform(a) }) { - is Right -> when (acc) { - is Right -> acc.also { acc.value.add(res.value) } - is Left -> acc - } - - is Left -> when (acc) { - is Right -> res - is Left -> Left(combine(acc.value, res.value)) - } - } - } + @BuilderInference transform: RaiseAccumulate.(A) -> B, +): Either> = either { + mapOrAccumulate(this@mapOrAccumulate, combine, transform) +} /** - * Returns [Either] a [List] containing the results of applying the given [transform] function - * to each element in the original collection, + * 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_ into a [NonEmptyList] that were _raised_ while applying the [transform] function. + * + * Let's see an example of all the different cases: + * + * ```kotlin + * fun test() { + * listOf(1, 2, 3, 4).mapOrAccumulate { i -> + * when(i) { + * 1 -> "Either - $i".left().bind() + * 2 -> "EitherNel - $i".leftNel().bindNel() + * 3 -> raise("Raise - $i") + * else -> withNel { raise(nonEmptyListOf("RaiseNel - $i")) } + * } + * } shouldBe nonEmptyListOf("Either - 1", "EitherNel - 2", "Raise - 3", "RaiseNel - 4").left() + * } + * ``` + * + * */ @OptIn(ExperimentalTypeInference::class) public inline fun Iterable.mapOrAccumulate( - @BuilderInference transform: Raise.(A) -> B, -): Either, List> { - val buffer = mutableListOf() - val res = fold, ArrayList>>(Right(ArrayList(collectionSizeOrDefault(10)))) { acc, a -> - when (val res = either { transform(a) }) { - is Right -> when (acc) { - is Right -> acc.also { acc.value.add(res.value) } - is Left -> acc - } - - is Left -> when (acc) { - is Right -> Left(buffer.also { it.add(res.value) }) - is Left -> Left(buffer.also { it.add(res.value) }) - } - } - } - return res.mapLeft { NonEmptyList(it[0], it.drop(1)) } + @BuilderInference transform: RaiseAccumulate.(A) -> B, +): Either, List> = either { + mapOrAccumulate(this@mapOrAccumulate, transform) } /** - * Flatten a list of [Either] into a single [Either] with a list of values, or accumulates all errors using [combine]. + * Flatten an [Iterable] of [Either]. + * Alias for [mapOrAccumulate] over an [Iterable] of computed [Either]. + * Either returns a [List] containing all [Either.Right] values, or [Either.Left] values accumulated using [combine]. */ public inline fun Iterable>.flattenOrAccumulate(combine: (Error, Error) -> Error): Either> = - fold, Either>>(Right(ArrayList(collectionSizeOrDefault(10)))) { acc, res -> - when (res) { - is Right -> when (acc) { - is Right -> acc.also { acc.value.add(res.value) } - is Left -> acc - } + mapOrAccumulate(combine) { it.bind() } - is Left -> when (acc) { - is Right -> res - is Left -> Left(combine(acc.value, res.value)) - } - } - } +/** + * Flatten an [Iterable] of [Either]. + * Alias for [mapOrAccumulate] over an [Iterable] of computed [Either]. + * Either returns a [List] containing all [Either.Right] values, or [EitherNel] [Left] values accumulated using [combine]. + */ +@JvmName("flattenNelOrAccumulate") +public fun Iterable>.flattenOrAccumulate(combine: (Error, Error) -> Error): Either> = + mapOrAccumulate(combine) { it.bindNel() } /** - * Flatten a list of [Either] into a single [Either] with a list of values, or accumulates all errors with into an [NonEmptyList]. + * Flatten an [Iterable] of [Either]. + * Alias for [mapOrAccumulate] over an [Iterable] of computed [Either]. + * Either returns a [List] containing all [Either.Right] values, or a [NonEmptyList] of all [Either.Left] values. */ -public fun Iterable>.flattenOrAccumulate(): Either, List> { - val buffer = mutableListOf() - val res = fold, Either, ArrayList>>(Right(ArrayList(collectionSizeOrDefault(10)))) { acc, res -> - when (res) { - is Right -> when (acc) { - is Right -> acc.also { acc.value.add(res.value) } - is Left -> acc - } +public fun Iterable>.flattenOrAccumulate(): Either, List> = + mapOrAccumulate { it.bind() } - is Left -> when (acc) { - is Right -> Left(buffer.also { it.add(res.value) }) - is Left -> Left(buffer.also { it.add(res.value) }) - } - } - } - return res.mapLeft { NonEmptyList(it[0], it.drop(1)) } -} +/** + * Flatten an [Iterable] of [Either]. + * Alias for [mapOrAccumulate] over an [Iterable] of computed [Either]. + * Either returns a [List] containing all [Either.Right] values, or a [NonEmptyList] of all [EitherNel] [Left] values. + */ +@JvmName("flattenNelOrAccumulate") +public fun Iterable>.flattenOrAccumulate(): Either, List> = + mapOrAccumulate { it.bindNel() } public fun Iterable.sequence(): List? = traverse(::identity) @@ -568,7 +603,7 @@ public inline fun List.reduceRightNull( * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Iterable.padZip(other: Iterable): List> = align(other) { ior -> @@ -599,7 +634,7 @@ public fun Iterable.padZip(other: Iterable): List> = * println("noPadding = $noPadding") * } * ``` - * + * */ public inline fun Iterable.padZip(other: Iterable, fa: (A?, B?) -> C): List = padZip(other).map { fa(it.first, it.second) } @@ -624,7 +659,7 @@ public inline fun Iterable.padZip(other: Iterable, fa: (A?, B?) * println("both = $both") * } * ``` - * + * */ public inline fun Iterable.leftPadZip(other: Iterable, fab: (A?, B) -> C): List = padZip(other) { a: A?, b: B? -> b?.let { fab(a, it) } }.mapNotNull(::identity) @@ -650,7 +685,7 @@ public inline fun Iterable.leftPadZip(other: Iterable, fab: (A?, * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Iterable.leftPadZip(other: Iterable): List> = this.leftPadZip(other) { a, b -> a to b } @@ -675,7 +710,7 @@ public fun Iterable.leftPadZip(other: Iterable): List> * println("both = $both") * } * ``` - * + * */ public inline fun Iterable.rightPadZip(other: Iterable, fa: (A, B?) -> C): List = other.leftPadZip(this) { a, b -> fa(b, a) } @@ -700,7 +735,7 @@ public inline fun Iterable.rightPadZip(other: Iterable, fa: (A, * println("noPadding = $noPadding") * } * ``` - * + * */ public fun Iterable.rightPadZip(other: Iterable): List> = this.rightPadZip(other) { a, b -> a to b } @@ -721,7 +756,7 @@ public fun Iterable.rightPadZip(other: Iterable): List> * println(result) * } * ``` - * + * */ public inline fun Iterable.align(b: Iterable, fa: (Ior) -> C): List = buildList(maxOf(this.collectionSizeOrDefault(10), b.collectionSizeOrDefault(10))) { @@ -752,7 +787,7 @@ public inline fun Iterable.align(b: Iterable, fa: (Ior) -> * println(result) * } * ``` - * + * */ public fun Iterable.align(b: Iterable): List> = this.align(b, ::identity) @@ -785,7 +820,7 @@ public fun Iterable.salign( * println(result) * } * ``` - * + * */ public fun Iterable>.unzip(): Pair, List> = fold(emptyList() to emptyList()) { (l, r), x -> @@ -810,7 +845,7 @@ public fun Iterable>.unzip(): Pair, List> = * println(result) * } * ``` - * + * */ public inline fun Iterable.unzip(fc: (C) -> Pair): Pair, List> = map(fc).unzip() @@ -830,7 +865,7 @@ public inline fun Iterable.unzip(fc: (C) -> Pair): Pair + * */ public fun Iterable>.unalign(): Pair, List> = fold(emptyList() to emptyList()) { (l, r), x -> @@ -857,7 +892,7 @@ public fun Iterable>.unalign(): Pair, List> = * println(result) * } * ``` - * + * */ public inline fun Iterable.unalign(fa: (C) -> Ior): Pair, List> = map(fa).unalign() @@ -876,6 +911,7 @@ public fun Iterable.firstOrNone(): Option = } else { None } + else -> { iterator().nextOrNone() } @@ -909,6 +945,7 @@ public fun Iterable.singleOrNone(): Option = 1 -> firstOrNone() else -> None } + else -> { iterator().run { nextOrNone().filter { !hasNext() } } } @@ -940,6 +977,7 @@ public fun Iterable.lastOrNone(): Option = } else { None } + else -> iterator().run { if (hasNext()) { var last: T @@ -974,6 +1012,7 @@ public fun Iterable.elementAtOrNone(index: Int): Option = in indices -> Some(elementAt(index)) else -> None } + else -> iterator().skip(index).nextOrNone() } @@ -983,6 +1022,7 @@ private tailrec fun Iterator.skip(count: Int): Iterator = next() skip(count - 1) } + else -> this } @@ -1000,7 +1040,7 @@ private tailrec fun Iterator.skip(count: Int): Iterator = * println(result) * } * ``` - * + * */ public fun Iterable.split(): Pair, A>? = firstOrNull()?.let { first -> @@ -1025,7 +1065,7 @@ public fun Iterable.tail(): List = * println(result) * } * ``` - * + * */ public fun Iterable.interleave(other: Iterable): List = this.split()?.let { (fa, a) -> @@ -1046,7 +1086,7 @@ public fun Iterable.interleave(other: Iterable): List = * println(result) * } * ``` - * + * */ public fun Iterable.unweave(ffa: (A) -> Iterable): List = split()?.let { (fa, a) -> @@ -1071,7 +1111,7 @@ public fun Iterable.unweave(ffa: (A) -> Iterable): List = * println(result) * } * ``` - * + * */ public inline fun Iterable.ifThen(fb: Iterable, ffa: (A) -> Iterable): Iterable = firstOrNull()?.let { first -> ffa(first) + tail().flatMap(ffa) } ?: fb.toList() @@ -1109,6 +1149,7 @@ public fun Iterable>.separateEither(): Pair, List * @receiver Iterable of Validated * @return a tuple containing List with [Validated.Invalid] and another List with its [Validated.Valid] values. */ +@Deprecated("Use separateEither instead.", ReplaceWith("map { it.toEither() }.separateEither()")) public fun Iterable>.separateValidated(): Pair, List> { val invalids = ArrayList(collectionSizeOrDefault(10)) val valids = ArrayList(collectionSizeOrDefault(10)) 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 41ea03aced8..110d09a61cb 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 @@ -1,7 +1,10 @@ +@file:OptIn(ExperimentalTypeInference::class) + package arrow.core import arrow.core.Either.Left import arrow.core.Either.Right +import arrow.core.raise.RaiseAccumulate import arrow.typeclasses.Semigroup import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmStatic @@ -438,8 +441,11 @@ public fun NonEmptyList>.sequence(): Either semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated()", + "arrow.core.mapOrAccumulate" + ) ) public inline fun NonEmptyList.traverseValidated( semigroup: Semigroup, @@ -447,31 +453,51 @@ public inline fun NonEmptyList.traverseValidated( ): Validated> = traverse(semigroup, f) +@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 NonEmptyList.traverse( semigroup: Semigroup, f: (A) -> Validated ): Validated> = - fold>>(mutableListOf().valid()) { acc, a -> - when (val res = f(a)) { - is Valid -> when (acc) { - is Valid -> acc.also { it.value.add(res.value) } - is Invalid -> acc - } - is Invalid -> when (acc) { - is Valid -> res - is Invalid -> semigroup.run { Invalid(acc.value.combine(res.value)) } - } - } - }.map { requireNotNull(it.toNonEmptyListOrNull()) } + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() -@Deprecated("sequenceValidated is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence()", "arrow.core.sequence")) +@Deprecated( + ValidatedDeprMsg + "Use the mapOrAccumulate API instead", + ReplaceWith( + "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated()", + "arrow.core.mapOrAccumulate" + ) +) public fun NonEmptyList>.sequenceValidated(semigroup: Semigroup): Validated> = - sequence(semigroup) + 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 NonEmptyList>.sequence(semigroup: Semigroup): Validated> = - traverse(semigroup, ::identity) + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated() + +public inline fun NonEmptyList.mapOrAccumulate( + combine: (E, E) -> E, + @BuilderInference transform: RaiseAccumulate.(A) -> B +): Either> = + all.mapOrAccumulate(combine, transform).map { requireNotNull(it.toNonEmptyListOrNull()) } + +public inline fun NonEmptyList.mapOrAccumulate( + @BuilderInference transform: RaiseAccumulate.(A) -> B +): Either, NonEmptyList> = + all.mapOrAccumulate(transform).map { requireNotNull(it.toNonEmptyListOrNull()) } @Deprecated( "traverseOption is being renamed to traverse to simplify the Arrow API", 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 cab16616cf7..21a54953a8f 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 @@ -2,6 +2,8 @@ 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.option import arrow.typeclasses.Monoid @@ -390,10 +392,21 @@ public sealed class Option { } @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) @@ -1254,23 +1267,28 @@ public inline fun Option.getOrElse(default: () -> T): T { * * @param alternative the default option if this is empty. */ -public inline fun Option.orElse(alternative: () -> Option): Option { - contract { callsInPlace(alternative, InvocationKind.AT_MOST_ONCE) } - return if (isEmpty()) alternative() else this -} +@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 orElse method", - ReplaceWith("orElse(value)") + NicheAPI + "Prefer using the recover method", + ReplaceWith("recover { value.bind() }", "arrow.core.recover") ) -public infix fun Option.or(value: Option): Option = if (isEmpty()) { - value -} else { - this -} +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]. */ +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( @@ -1561,14 +1579,25 @@ public fun Option>.uniteValidated(): Option = 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> = - unzip(::identity) + fold({ None to None }, { (a, b) -> Some(a) to Some(b) }) -public inline fun Option.unzip(f: (C) -> Pair): Pair, Option> = - fold( - { None to None }, - { f(it).let { pair -> Some(pair.first) to Some(pair.second) } } +@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) } }) /** * Given [A] is a sub type of [B], re-type this value from Option to Option 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 7f67780684d..6a1127682ec 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 @@ -1,7 +1,11 @@ +@file:OptIn(ExperimentalTypeInference::class) + package arrow.core import arrow.core.Either.Left import arrow.core.Either.Right +import arrow.core.raise.RaiseAccumulate +import arrow.core.raise.fold import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import kotlin.experimental.ExperimentalTypeInference @@ -635,8 +639,15 @@ public fun Sequence>.sequence(): Option> = public fun Sequence>.sequenceOption(): Option> = sequence().map { it.asSequence() } +@Deprecated( + ValidatedDeprMsg + "Use the mapOrAccumulate API instead", + ReplaceWith( + "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated()", + "arrow.core.mapOrAccumulate" + ) +) public fun Sequence>.sequence(semigroup: Semigroup): Validated> = - traverse(semigroup, ::identity) + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { it.bind() }.toValidated() @Deprecated( "sequenceValidated is being renamed to sequence to simplify the Arrow API", @@ -719,24 +730,41 @@ public fun Sequence.traverse(f: (A) -> Option): Option> { public fun Sequence.traverseOption(f: (A) -> Option): Option> = traverse(f).map { it.asSequence() } +@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 fun Sequence.traverse( semigroup: Semigroup, f: (A) -> Validated ): Validated> = - fold(mutableListOf().valid() as Validated>) { acc, a -> - when (val res = f(a)) { - is Valid -> when (acc) { - is Valid -> acc.also { it.value.add(res.value) } - is Invalid -> acc - } - is Invalid -> when (acc) { - is Valid -> res - is Invalid -> semigroup.run { acc.value.combine(res.value).invalid() } - } - } - } + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it).bind() }.toValidated() + +public fun Sequence.mapOrAccumulate( + combine: (Error, Error) -> Error, + @BuilderInference transform: RaiseAccumulate.(A) -> B +): Either> { + var left: Any? = EmptyValue + val right = mutableListOf() + for (item in this) + fold({ transform(RaiseAccumulate(this), item) }, { errors -> left = EmptyValue.combine(left, errors.reduce(combine), combine) }, { b -> right.add(b) }) + return if (left !== EmptyValue) EmptyValue.unbox(left).left() else right.right() +} + +public fun Sequence.mapOrAccumulate( + @BuilderInference transform: RaiseAccumulate.(A) -> B +): Either, List> { + val left = mutableListOf() + val right = mutableListOf() + for (item in this) + fold({ transform(RaiseAccumulate(this), item) }, { errors -> left.addAll(errors) }, { b -> right.add(b) }) + return left.toNonEmptyListOrNull()?.left() ?: right.right() +} @Deprecated( "traverseValidated is being renamed to traverse to simplify the Arrow API", 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 index cf668335f19..dee1e08acdc 100644 --- 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 @@ -8,23 +8,47 @@ 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(value)", "arrow.core.Either") +) public typealias Valid = Validated.Valid + +@Deprecated( + ValidatedDeprMsg + "Use Left to construct Either values instead", + ReplaceWith("Either.Left(value)", "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) }) @@ -32,6 +56,10 @@ public sealed class Validated { * 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( @@ -43,10 +71,18 @@ public sealed class Validated { * 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 = @@ -56,11 +92,19 @@ public sealed class Validated { 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 { @@ -69,6 +113,10 @@ public sealed class Validated { 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) } @@ -91,6 +139,10 @@ public sealed class Validated { * ``` * */ + @Deprecated( + DeprAndNicheMsg + "Prefer creating explicit lambdas instead", + ReplaceWith("{ it.bimap(fl, fr) }") + ) @JvmStatic public inline fun lift( crossinline fl: (A) -> C, @@ -116,14 +168,32 @@ public sealed class Validated { * ``` * */ + @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> = @@ -136,6 +206,13 @@ public sealed class Validated { 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> = @@ -148,12 +225,20 @@ public sealed class Validated { 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, @@ -161,31 +246,67 @@ public sealed class Validated { ): B = fold({ fe(c, it) }, { fa(c, it) }) - public inline fun bifoldMap(MN: Monoid, g: (E) -> B, f: (A) -> B): B = MN.run { + @Deprecated( + DeprAndNicheMsg + "Prefer when or fold instead", + ReplaceWith("MN.run { fold({ empty().combine(g(it)) }, { empty().combine(f(it)) }) }") + ) + public inline fun bifoldMap(MN: Monoid, g: (E) -> B, f: (A) -> B): B = MN.run { bifoldLeft(MN.empty(), { c, b -> c.combine(g(b)) }) { c, a -> c.combine(f(a)) } } + @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({ MB.empty() }, f)") + ) public inline fun foldMap(MB: Monoid, f: (A) -> B): B = fold({ MB.empty() }, f) @@ -194,6 +315,10 @@ public sealed class Validated { { "Validated.Valid($it)" } ) + @Deprecated( + ValidatedDeprMsg + "Use Right to construct Either values instead", + ReplaceWith("Either.Right(value)", "arrow.core.Either") + ) public data class Valid(val value: A) : Validated() { override fun toString(): String = "Validated.Valid($value)" @@ -204,38 +329,75 @@ public sealed class Validated { } } + @Deprecated( + ValidatedDeprMsg + "Use Left to construct Either values instead", + ReplaceWith("Either.Left(value)", "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 /** @@ -247,6 +409,10 @@ public sealed class Validated { /** * 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) @@ -254,10 +420,18 @@ public sealed class Validated { * 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) @@ -265,6 +439,10 @@ public sealed class Validated { * 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())) @@ -279,6 +457,10 @@ public sealed class Validated { /** * 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) @@ -286,6 +468,10 @@ public sealed class Validated { * 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) @@ -306,6 +492,10 @@ public sealed class Validated { * ``` * */ + @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 -> { @@ -332,6 +522,10 @@ public sealed class Validated { * ``` * */ + @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 @@ -345,16 +539,38 @@ public sealed class Validated { * 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({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), fb.toEither(), ::Pair).toValidated()", + "arrow.core.Either" + ) +) public fun Validated.zip(SE: Semigroup, fb: Validated): Validated> = zip(SE, fb, ::Pair) +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -375,6 +591,13 @@ public inline fun Validated.zip( f(a, b) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -396,6 +619,13 @@ public inline fun Validated.zip( f(a, b, c) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -418,6 +648,13 @@ public inline fun Validated.zip( f(a, b, c, d) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -441,6 +678,13 @@ public inline fun Validated.zip( f(a, b, c, d, e) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, 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, @@ -465,6 +709,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, 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, @@ -479,6 +730,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, 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, @@ -494,6 +752,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g, h) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, 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, @@ -510,6 +775,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g, h, i) } +@Deprecated( + ValidatedDeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, 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, @@ -551,12 +823,26 @@ public inline fun Validated.zip( Validated.Invalid(accumulatedError as E) } +@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, @@ -564,6 +850,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -572,6 +865,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -581,6 +881,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -591,6 +898,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -602,6 +916,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -614,6 +935,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -627,6 +955,13 @@ public inline fun ValidatedNel.zip( ): 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, @@ -658,32 +993,77 @@ public inline fun ValidatedNel.zip( * ``` * */ +@Deprecated( + ValidatedDeprMsg + "Use widen on Either after refactoring", + ReplaceWith("toEither().widen()") +) public fun Validated.widen(): Validated = this +@Deprecated( + ValidatedDeprMsg + "Use leftWiden on Either after refactoring", + ReplaceWith("toEither().leftWiden()") +) public fun Validated.leftWiden(): Validated = this +@Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or map", + ReplaceWith("(0 until (n.coerceAtLeast(0))).mapOrAccumulate({ a, b -> SE.run { a.combine(b) } }) { 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( + DeprAndNicheMsg + "Use fold on Either after refactoring", + ReplaceWith("MA.run { fold({ empty() }) { empty().combine(it) } }") +) public fun Validated.fold(MA: Monoid): A = MA.run { foldLeft(empty()) { acc, a -> acc.combine(a) } } @@ -692,30 +1072,68 @@ public fun Validated.fold(MA: Monoid): A = MA.run { 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")) +@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")) +@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")) +@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 }) }, @@ -725,21 +1143,37 @@ public operator fun , A : Comparable> Validated.compa /** * 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) @@ -747,6 +1181,13 @@ public inline fun Validated.valueOr(f: (E) -> A): A = * 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 -> SE.run { e.combine(ee) } }.bind() }.toValidated()", + "arrow.core.recover" + ) +) public inline fun Validated.findValid(SE: Semigroup, that: () -> Validated): Validated = fold( { e -> @@ -774,6 +1215,10 @@ public inline fun Validated.findValid(SE: Semigroup, that: () -> * ``` * */ +@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) @@ -785,36 +1230,64 @@ public inline fun Validated.andThen(f: (A) -> Validated): * 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({ a, b -> SE.run { a.combine(b) } }, toEither(), y.toEither(), { a, b -> SA.run { a.combine(b) } }).toValidated()") +) public fun Validated.combine( SE: Semigroup, SA: Semigroup, @@ -827,6 +1300,13 @@ public fun Validated.combine( else -> y } +@Deprecated( + DeprAndNicheMsg, + ReplaceWith( + "toEither().recover { e -> y.toEither().recover { ee -> raise(SE.run { e.combine(ee) })) }.bind() }.toValidated()", + "arrow.core.recover" + ) +) public fun Validated.combineK(SE: Semigroup, y: Validated): Validated { return when (this) { is Valid -> this @@ -840,17 +1320,42 @@ public fun Validated.combineK(SE: Semigroup, y: Validated) /** * 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) + +internal const val ValidatedDeprMsg = "Validated functionally is being merged into Either.\n" + +private const val DeprAndNicheMsg = + "Validated functionaliy 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/map.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/map.kt index 1265ec598c6..ed9d5ba3af2 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 @@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalTypeInference::class) + package arrow.core import arrow.core.Either.Left @@ -6,6 +8,8 @@ import arrow.typeclasses.Monoid import arrow.typeclasses.Semigroup import kotlin.experimental.ExperimentalTypeInference import kotlin.collections.flatMap as _flatMap +import arrow.core.raise.RaiseAccumulate +import arrow.core.raise.fold /** * Combines to structures by taking the intersection of their shapes @@ -259,29 +263,56 @@ public fun Map>.sequence(): Either> = public fun Map>.sequenceEither(): Either> = sequence() -@Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(semigroup, f)", "arrow.core.traverse")) +@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 Map.traverseValidated( semigroup: Semigroup, f: (A) -> Validated ): Validated> = traverse(semigroup, f) +@Deprecated( + ValidatedDeprMsg + "Use the mapOrAccumulate API instead", + ReplaceWith( + "mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it.value).bind() }.toValidated()", + "arrow.core.mapOrAccumulate" + ) +) public inline fun Map.traverse( semigroup: Semigroup, f: (A) -> Validated ): Validated> = - foldLeft(mutableMapOf().valid() as Validated>) { acc, (k, v) -> - when (val res = f(v)) { - is Valid -> when (acc) { - is Valid -> acc.also { it.value[k] = res.value } - is Invalid -> acc - } - is Invalid -> when (acc) { - is Valid -> res - is Invalid -> semigroup.run { acc.value.combine(res.value).invalid() } - } - } - } + mapOrAccumulate({ a, b -> semigroup.run { a.combine(b) } }) { f(it.value).bind() }.toValidated() + +public inline fun Map.mapOrAccumulate( + combine: (E, E) -> E, + @BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B +): Either> { + var left: Any? = EmptyValue + val right = mutableMapOf() + for (element in this) + fold( + { transform(RaiseAccumulate(this), element) }, + { errors -> left = EmptyValue.combine(left, errors.reduce(combine), combine) }, + { right[element.key] = it } + ) + return if (left !== EmptyValue) EmptyValue.unbox(left).left() else right.right() +} + +public inline fun Map.mapOrAccumulate( + @BuilderInference transform: RaiseAccumulate.(Map.Entry) -> B +): Either, Map> { + val left = mutableListOf() + val right = mutableMapOf() + for (element in this) + fold({ transform(RaiseAccumulate(this), element) }, { error -> left.addAll(error) }, { right[element.key] = it }) + return left.toNonEmptyListOrNull()?.left() ?: right.right() +} @Deprecated("sequenceValidated is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence(semigroup)", "arrow.core.sequence")) public fun Map>.sequenceValidated(semigroup: Semigroup): Validated> = @@ -514,6 +545,13 @@ public fun Map.combine(SG: Semigroup, b: Map): Map = public fun Iterable>.combineAll(SG: Semigroup): Map = fold(Monoid.map(SG)) +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 align with Kotlin Std naming", ReplaceWith("fold(b, f)")) public inline fun Map.foldLeft(b: B, f: (B, Map.Entry) -> B): B { var result = b this.forEach { result = f(result, it) } 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 1781ffac2b8..ce906755709 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 @@ -23,10 +23,8 @@ import kotlin.jvm.JvmInline import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName -public inline fun either(@BuilderInference block: Raise.() -> A): Either { - contract { callsInPlace(block, EXACTLY_ONCE) } - return fold({ block.invoke(this) }, { Either.Left(it) }, { Either.Right(it) }) -} +public inline fun either(@BuilderInference block: Raise.() -> A): Either = + fold({ block.invoke(this) }, { Either.Left(it) }, { Either.Right(it) }) public inline fun nullable(block: NullableRaise.() -> A): A? { contract { callsInPlace(block, EXACTLY_ONCE) } @@ -61,7 +59,7 @@ public value class NullableRaise(private val cont: Raise) : Raise { @RaiseDSL public fun ensure(value: Boolean): Unit = ensure(value) { null } override fun raise(r: Nothing?): Nothing = cont.raise(r) - public fun Option.bind(): B = bind { raise(null) } + public fun Option.bind(): B = getOrElse { raise(null) } public fun B?.bind(): B { contract { returns() implies (this@bind != null) } @@ -83,7 +81,7 @@ public value class ResultRaise(private val cont: Raise) : Raise) : Raise { override fun raise(r: None): Nothing = cont.raise(r) - public fun Option.bind(): B = bind { raise(None) } + public fun Option.bind(): B = getOrElse { raise(None) } public fun ensure(value: Boolean): Unit = ensure(value) { None } public fun ensureNotNull(value: B?): B { 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 404fe1fb3d3..9b8f93d913c 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 @@ -3,6 +3,7 @@ @file:OptIn(ExperimentalTypeInference::class) package arrow.core.raise +import arrow.core.identity import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -673,3 +674,12 @@ public inline fun effect(@BuilderInference noinline block: suspend Raise< public typealias EagerEffect = Raise.() -> A public inline fun eagerEffect(@BuilderInference noinline block: Raise.() -> A): EagerEffect = block + +public suspend fun Effect.merge(): A = getOrElse(::identity) +public fun EagerEffect.merge(): A = getOrElse(::identity) + +@Suppress("IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION") +public suspend fun Effect.get(): A = getOrElse(::identity) + +@Suppress("IMPLICIT_NOTHING_TYPE_ARGUMENT_IN_RETURN_POSITION") +public fun EagerEffect.get(): A = getOrElse(::identity) 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 54432d38de7..0e6d020342e 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 @@ -108,3 +108,9 @@ public inline infix fun EagerEffect.catch( @BuilderInference crossinline recover: Raise.(T) -> A, ): EagerEffect = eagerEffect { catch { t: Throwable -> if (t is T) recover(t) else throw t } } + +public suspend inline infix fun Effect.getOrElse(onRaise: (E) -> A): A = + recover({ invoke() }, onRaise) + +public inline infix fun EagerEffect.getOrElse(onRaise: (E) -> A): A = + recover({ invoke() }, onRaise) 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 2b8ecc71bd7..fdf1d48a2a4 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 @@ -90,7 +90,6 @@ public inline fun fold( transform: (value: A) -> B, ): B { contract { - callsInPlace(program, EXACTLY_ONCE) callsInPlace(error, AT_MOST_ONCE) callsInPlace(recover, AT_MOST_ONCE) callsInPlace(transform, AT_MOST_ONCE) 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 f72ed5e1a31..a127995c9f2 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 @@ -4,11 +4,9 @@ package arrow.core.raise import arrow.core.Either import arrow.core.Ior -import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.Validated -import arrow.core.identity import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName @@ -24,18 +22,28 @@ public fun EagerEffect.toValidated(): Validated = fold({ Vali public suspend fun Effect.toIor(): Ior = fold({ Ior.Left(it) }) { Ior.Right(it) } 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 [E]. */ -public suspend fun Effect.orNull(): A? = fold({ _: E -> null }) { it } -public fun EagerEffect.orNull(): A? = fold({ _: E -> null }) { it } +public suspend fun Effect.getOrNull(): A? = getOrElse { null } + +/** Run the [EagerEffect] by returning [A], or `null` if raised with [E]. */ +public fun EagerEffect.getOrNull(): A? = getOrElse { null } /** Run the [Effect] by returning [Option] of [A], [orElse] run the fallback lambda and returning its result of [Option] of [A]. */ public suspend fun Effect.toOption(orElse: suspend (E) -> Option): Option = fold(orElse) { Some(it) } public inline fun EagerEffect.toOption(orElse: (E) -> Option): Option = fold(orElse) { Some(it) } -/** Run the [Effect] by returning [Option] of [A], or [None] if raised with [None]. */ -public suspend fun Effect.toOption(): Option = option { invoke() } -public fun EagerEffect.toOption(): Option = option { invoke() } - /** Run the [Effect] by returning [Result] of [A], [orElse] run the fallback lambda and returning its result of [Result] of [A]. */ public suspend fun Effect.toResult(orElse: suspend (E) -> Result): Result = fold({ Result.failure(it) }, { orElse(it) }, { Result.success(it) }) @@ -45,6 +53,3 @@ public inline fun EagerEffect.toResult(orElse: (E) -> Result): /** Run the [Effect] by returning [Result] of [A], or [Result.Failure] if raised with [Throwable]. */ public suspend fun Effect.toResult(): Result = result { invoke() } public fun EagerEffect.toResult(): Result = result { invoke() } - -public suspend fun Effect.merge(): A = fold(::identity, ::identity) -public fun EagerEffect.merge(): A = fold(::identity, ::identity) 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 1136f47a5a5..d997083e782 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 @@ -2,16 +2,16 @@ @file:Suppress("DEPRECATION") @file:JvmMultifileClass @file:JvmName("RaiseKt") + package arrow.core.raise import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.Some import arrow.core.Validated import arrow.core.continuations.EffectScope import arrow.core.identity +import arrow.core.nonFatalOrThrow import arrow.core.recover +import kotlin.coroutines.cancellation.CancellationException import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_MOST_ONCE import kotlin.contracts.InvocationKind.EXACTLY_ONCE @@ -39,7 +39,7 @@ public annotation class RaiseDSL * ```kotlin * fun Raise.failure(): Int = raise("failed") * - * fun Raise.recovered(): Int = + * fun recovered(): Int = * recover({ failure() }) { _: String -> 1 } * ``` * @@ -96,11 +96,11 @@ public annotation class RaiseDSL * * fun Raise.failure(): Int = raise("failed") * - * fun Raise.recovered(): Int = recover({ failure() }) { _: String -> 1 } + * fun recovered(): Int = recover({ failure() }) { _: String -> 1 } * --> * ```kotlin * fun test() { - * val either = either { failure() } + * val either: Either = either { failure() } * .recover { _: String -> recovered() } * * either shouldBe Either.Right(1) @@ -118,10 +118,12 @@ public interface Raise { @Deprecated("Use raise instead", ReplaceWith("raise(r)")) public fun shift(r: R): B = raise(r) + @RaiseDSL public suspend fun arrow.core.continuations.Effect.bind(): B = fold({ raise(it) }, ::identity) // Added for source compatibility with EffectScope / EagerScope + @RaiseDSL public suspend fun arrow.core.continuations.EagerEffect.bind(): B = fold({ raise(it) }, ::identity) @@ -150,6 +152,8 @@ public interface Raise { * @see [recover] if you want to attempt to recover from any _logical failure_. */ public operator fun EagerEffect.invoke(): A = invoke(this@Raise) + + @RaiseDSL public fun EagerEffect.bind(): A = invoke(this@Raise) /** @@ -160,6 +164,8 @@ public interface Raise { * @see [recover] if you want to attempt to recover from any _logical failure_. */ public suspend operator fun Effect.invoke(): A = invoke(this@Raise) + + @RaiseDSL public suspend fun Effect.bind(): A = invoke(this@Raise) /** @@ -189,96 +195,23 @@ public interface Raise { * * */ + @RaiseDSL public fun Either.bind(): A = when (this) { is Either.Left -> raise(value) is Either.Right -> value } - /* Will be removed in subsequent PRs for Arrow 2.x.x */ + + @Deprecated( + "Validated is deprecated in favor of Either.", + ReplaceWith("toEither().bind()") + ) + @RaiseDSL public fun Validated.bind(): A = when (this) { is Validated.Invalid -> raise(value) is Validated.Valid -> value } - /** - * Extract the [Result.success] value out of [Result], - * because [Result] works with [Throwable] as its error type you need to [transform] [Throwable] to [R]. - * - * Note that this functions can currently not be _inline_ without Context Receivers, - * and thus doesn't allow suspension in its error handler. - * To do so, use [Result.recover] and [bind]. - * - * - * ```kotlin - * suspend fun test() { - * val one: Result = Result.success(1) - * val failure: Result = Result.failure(RuntimeException("Boom!")) - * - * either { - * val x = one.bind { -1 } - * val y = failure.bind { failure: Throwable -> - * raise("Something bad happened: ${failure.message}") - * } - * val z = failure.recover { failure: Throwable -> - * delay(10) - * 1 - * }.bind { raise("Something bad happened: ${it.message}") } - * x + y + z - * } shouldBe Either.Left("Something bad happened: Boom!") - * } - * ``` - * - * - */ - public fun Result.bind(transform: (Throwable) -> R): A = - fold(::identity) { throwable -> raise(transform(throwable)) } - - /** - * Extract the [Some] value out of [Option], - * because [Option] works with [None] as its error type you need to [transform] [None] to [R]. - * - * Note that this functions can currently not be _inline_ without Context Receivers, - * and thus doesn't allow suspension in its error handler. - * To do so, use [Option.recover] and [bind]. - * - * - * ```kotlin - * suspend fun test() { - * val empty: Option = None - * either { - * val x: Int = empty.bind { _: None -> 1 } - * val y: Int = empty.bind { _: None -> raise("Something bad happened: Boom!") } - * val z: Int = empty.recover { _: None -> - * delay(10) - * 1 - * }.bind { raise("Something bad happened: Boom!") } - * x + y + z - * } shouldBe Either.Left("Something bad happened: Boom!") - * } - * ``` - * - * - */ - public fun Option.bind(transform: Raise.(None) -> A): A = - when (this) { - None -> transform(None) - is Some -> value - } - @RaiseDSL public suspend infix fun Effect.recover(@BuilderInference resolve: suspend Raise.(E) -> A): A = fold({ this@recover.invoke(this) }, { throw it }, { resolve(it) }) { it } @@ -286,7 +219,7 @@ public interface Raise { /** @see [recover] */ @RaiseDSL public infix fun EagerEffect.recover(@BuilderInference resolve: Raise.(E) -> A): A = - recover({ invoke() }, resolve) + recover({ invoke() }) { resolve(it) } /** * Execute the [Effect] resulting in [A], @@ -299,22 +232,23 @@ public interface Raise { public suspend fun Effect.recover( @BuilderInference recover: suspend Raise.(E) -> A, @BuilderInference catch: suspend Raise.(Throwable) -> A, - ): A = fold({ invoke() }, { catch(it) }, { recover(it) }, { it }) + ): A = recover({ invoke() }, { recover(it) }) { catch(it) } @RaiseDSL public suspend infix fun Effect.catch( @BuilderInference catch: suspend Raise.(Throwable) -> A, - ): A = fold({ catch(it) }, { raise(it) }, { it }) + ): A = catch({ invoke() }) { catch(it) } @RaiseDSL public infix fun EagerEffect.catch( @BuilderInference catch: Raise.(Throwable) -> A, - ): A = fold({ catch(it) }, { raise(it) }, { it }) + ): A = catch({ invoke() }) { catch(it) } } /** * Execute the [Raise] context function resulting in [A] or any _logical error_ of type [E], - * and recover by providing a fallback value of type [A] or raising a new error of type [R]. + * and recover by providing a transform [E] into a fallback value of type [A]. + * Base implementation of `effect { f() } getOrElse { fallback() }`. * * * ```kotlin - * suspend fun test() { - * either { - * recover({ raise("failed") }) { str -> str.length } - * } shouldBe Either.Right(6) + * fun test() { + * recover({ raise("failed") }) { str -> str.length } shouldBe 6 * - * either { + * either { * recover({ raise("failed") }) { str -> raise(-1) } * } shouldBe Either.Left(-1) * } * ``` - * + * * */ @RaiseDSL -public inline fun Raise.recover( +public inline fun recover( @BuilderInference action: Raise.() -> A, - @BuilderInference recover: Raise.(E) -> A, -): A { - contract { - callsInPlace(action, EXACTLY_ONCE) - callsInPlace(recover, AT_MOST_ONCE) - } - return fold({ action(this) }, { throw it }, { recover(it) }, { it }) -} + @BuilderInference recover: (E) -> A, +): A = fold(action, { throw it }, recover, ::identity) +/** + * Execute the [Raise] context function resulting in [A] or any _logical error_ of type [E], + * and [recover] by providing a transform [E] into a fallback value of type [A], + * or [catch] any unexpected exceptions by providing a transform [Throwable] into a fallback value of type [A], + * + * + * ```kotlin + * fun test() { + * recover( + * { raise("failed") }, + * { str -> str.length } + * ) { t -> t.message ?: -1 } shouldBe 6 + * + * fun Raise.boom(): Int = throw RuntimeException("BOOM") + * + * recover( + * { boom() }, + * { str -> str.length } + * ) { t -> t.message?.length ?: -1 } shouldBe 4 + * } + * ``` + * + * + */ @RaiseDSL -public inline fun Raise.recover( +public inline fun recover( @BuilderInference action: Raise.() -> A, - @BuilderInference recover: Raise.(E) -> A, - @BuilderInference catch: Raise.(Throwable) -> A, -): A { - contract { - callsInPlace(action, EXACTLY_ONCE) - callsInPlace(recover, AT_MOST_ONCE) - callsInPlace(catch, AT_MOST_ONCE) - } - return fold({ action(this) }, { catch(it) }, { recover(it) }, { it }) -} + @BuilderInference recover: (E) -> A, + @BuilderInference catch: (Throwable) -> A, +): A = fold(action, catch, recover, ::identity) +/** + * Execute the [Raise] context function resulting in [A] or any _logical error_ of type [E], + * and [recover] by providing a transform [E] into a fallback value of type [A], + * or [catch] any unexpected exceptions by providing a transform [Throwable] into a fallback value of type [A], + * + * + * ```kotlin + * fun test() { + * recover( + * { raise("failed") }, + * { str -> str.length } + * ) { t -> t.message ?: -1 } shouldBe 6 + * + * fun Raise.boom(): Int = throw RuntimeException("BOOM") + * + * recover( + * { boom() }, + * { str -> str.length } + * ) { t: RuntimeException -> t.message?.length ?: -1 } shouldBe 4 + * } + * ``` + * + * + */ @RaiseDSL -public inline fun Raise.catch( - @BuilderInference action: Raise.() -> A, - @BuilderInference catch: Raise.(Throwable) -> A, -): A { - contract { - callsInPlace(action, EXACTLY_ONCE) - callsInPlace(catch, AT_MOST_ONCE) +@JvmName("recoverReified") +public inline fun recover( + @BuilderInference action: Raise.() -> A, + @BuilderInference recover: (E) -> A, + @BuilderInference catch: (T) -> A, +): A = fold(action, { t -> if (t is T) catch(t) else throw t }, recover, ::identity) + +/** + * Allows safely catching exceptions without capturing [CancellationException], + * or fatal exceptions like `OutOfMemoryError` or `VirtualMachineError` on the JVM. + * + * + * ```kotlin + * fun test() { + * catch({ throw RuntimeException("BOOM") }) { t -> + * "fallback" + * } shouldBe "fallback" + * + * fun fetchId(): Int = throw RuntimeException("BOOM") + * + * either { + * catch({ fetchId() }) { t -> + * raise("something went wrong: ${t.message}") + * } + * } shouldBe Either.Left("something went wrong: BOOM") + * } + * ``` + * + * + * + * Alternatively, you can use `try { } catch { }` blocks with [nonFatalOrThrow]. + * This API offers a similar syntax as the top-level [catch] functions like [Either.catch]. + */ +@RaiseDSL +public inline fun catch(action: () -> A, catch: (Throwable) -> A): A = + try { + action() + } catch (t: Throwable) { + catch(t.nonFatalOrThrow()) } - return fold({ action(this) }, { catch(it) }, { raise(it) }, { it }) -} +/** + * Allows safely catching exceptions of type `T` without capturing [CancellationException], + * or fatal exceptions like `OutOfMemoryError` or `VirtualMachineError` on the JVM. + * + * + * ```kotlin + * fun test() { + * catch({ throw RuntimeException("BOOM") }) { t -> + * "fallback" + * } shouldBe "fallback" + * + * fun fetchId(): Int = throw RuntimeException("BOOM") + * + * either { + * catch({ fetchId() }) { t: RuntimeException -> + * raise("something went wrong: ${t.message}") + * } + * } shouldBe Either.Left("something went wrong: BOOM") + * } + * ``` + * + * + * + * Alternatively, you can use `try { } catch(e: T) { }` blocks. + * This API offers a similar syntax as the top-level [catch] functions like [Either.catch]. + */ @RaiseDSL @JvmName("catchReified") -public inline fun Raise.catch( - @BuilderInference action: Raise.() -> A, - @BuilderInference catch: Raise.(T) -> A, -): A { - contract { - callsInPlace(action, EXACTLY_ONCE) - callsInPlace(catch, AT_MOST_ONCE) - } - return catch(action) { t: Throwable -> if (t is T) catch(t) else throw t } -} +public inline fun catch(action: () -> A, catch: (T) -> A): A = + catch(action) { t: Throwable -> if (t is T) catch(t) else throw t } @RaiseDSL public inline fun Raise.ensure(condition: Boolean, raise: () -> R) { 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 431960c0d05..af77863614b 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 @@ -3,19 +3,20 @@ @file:JvmName("RaiseKt") package arrow.core.raise +import arrow.core.mapOrAccumulate import arrow.core.Either +import arrow.core.EitherNel import arrow.core.EmptyValue +import arrow.core.EmptyValue.combine +import arrow.core.EmptyValue.unbox import arrow.core.NonEmptyList -import arrow.core.Tuple4 -import arrow.core.Tuple5 -import arrow.core.Tuple6 -import arrow.core.Tuple7 -import arrow.core.Tuple8 -import arrow.core.emptyCombine -import arrow.core.nel -import arrow.typeclasses.Semigroup +import arrow.core.Validated +import arrow.core.collectionSizeOrDefault +import arrow.core.ValidatedNel +import arrow.core.nonEmptyListOf +import arrow.core.toNonEmptyListOrNull import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind +import kotlin.contracts.InvocationKind.AT_MOST_ONCE import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmMultifileClass @@ -23,257 +24,217 @@ import kotlin.jvm.JvmName /** - * Accumulate the errors from running both [action1] and [action2] - * using the given [semigroup]. + * Accumulate the errors from running both [action1] and [action2] using the given [combine] function. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference block: Raise.(A, B) -> C + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + block: (A, B) -> C ): C { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - } - val result1 = either(action1) - val result2 = either(action2) - return when (result1) { - is Either.Right -> - when (result2) { - is Either.Right -> block(result1.value, result2.value) - is Either.Left -> raise(result2.value) - } - is Either.Left -> - when (result2) { - is Either.Right -> raise(result1.value) - is Either.Left -> raise(semigroup.run { result1.value + result2.value }) - } + contract { callsInPlace(block, AT_MOST_ONCE) } + return zipOrAccumulate( + combine, + action1, + action2, + { }) { a, b, _ -> + block(a, b) } } /** - * Accumulate the errors from running [action1], [action2], and [action3] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], and [action3] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference block: Raise.(A, B, C) -> D + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + block: (A, B, C) -> D ): D { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2) { x, y -> x to y } }, - action3 - ) { xy, z -> block(xy.first, xy.second, z) } + combine, + action1, + action2, + action3, + { }) { a, b, c, _ -> + block(a, b, c) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], and [action4] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], and [action4] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference block: Raise.(A, B, C, D) -> E + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + block: (A, B, C, D) -> E ): E { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3) { x, y, z -> Triple(x, y, z) } }, - action4 - ) { xyz, z -> block(xyz.first, xyz.second, xyz.third, z) } + combine, + action1, + action2, + action3, + action4, + { }) { a, b, c, d, _ -> + block(a, b, c, d) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], and [action5] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference block: Raise.(A, B, C, D, E) -> F + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + block: (A, B, C, D, E) -> F ): F { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4) { x, y, z, u -> Tuple4(x, y, z, u) } }, - action5 - ) { xyzu, v -> block(xyzu.first, xyzu.second, xyzu.third, xyzu.fourth, v) } + combine, + action1, + action2, + action3, + action4, + action5, + { }) { a, b, c, d, e, _ -> + block(a, b, c, d, e) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], and [action6] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference block: Raise.(A, B, C, D, E, F) -> G + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + block: (A, B, C, D, E, F) -> G ): G { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5) { x, y, z, u, v -> Tuple5(x, y, z, u, v) } }, - action6 - ) { xyzuv, w -> block(xyzuv.first, xyzuv.second, xyzuv.third, xyzuv.fourth, xyzuv.fifth, w) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + { }) { a, b, c, d, e, f, _ -> + block(a, b, c, d, e, f) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], and [action7] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference block: Raise.(A, B, C, D, E, F, G) -> H + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + block: (A, B, C, D, E, F, G) -> H ): H { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6) { x, y, z, u, v, w -> Tuple6(x, y, z, u, v, w) } }, - action7 - ) { xyzuvw, a -> block(xyzuvw.first, xyzuvw.second, xyzuvw.third, xyzuvw.fourth, xyzuvw.fifth, xyzuvw.sixth, a) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + action7, + { }) { a, b, c, d, e, f, g, _ -> + block(a, b, c, d, e, f, g) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], and [action8] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference action8: Raise.() -> H, - @BuilderInference block: Raise.(A, B, C, D, E, F, G, H) -> I + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + block: (A, B, C, D, E, F, G, H) -> I ): I { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6, action7) { x, y, z, u, v, w, a -> Tuple7(x, y, z, u, v, w, a) } }, - action8 - ) { xyzuvwa, b -> block(xyzuvwa.first, xyzuvwa.second, xyzuvwa.third, xyzuvwa.fourth, xyzuvwa.fifth, xyzuvwa.sixth, xyzuvwa.seventh, b) } + combine, + action1, + action2, + action3, + action4, + action5, + action6, + action7, + action8, + { }) { a, b, c, d, e, f, g, h, _ -> + block(a, b, c, d, e, f, g, h) + } } /** - * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9] - * using the given [semigroup]. + * Accumulate the errors from running [action1], [action2], [action3], [action4], [action5], [action6], [action7], [action8], and [action9] using the given [combine]. */ @RaiseDSL public inline fun Raise.zipOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, - @BuilderInference action1: Raise.() -> A, - @BuilderInference action2: Raise.() -> B, - @BuilderInference action3: Raise.() -> C, - @BuilderInference action4: Raise.() -> D, - @BuilderInference action5: Raise.() -> E, - @BuilderInference action6: Raise.() -> F, - @BuilderInference action7: Raise.() -> G, - @BuilderInference action8: Raise.() -> H, - @BuilderInference action9: Raise.() -> I, - @BuilderInference block: Raise.(A, B, C, D, E, F, G, H, I) -> J + combine: (R, R) -> R, + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + @BuilderInference action9: RaiseAccumulate.() -> I, + block: (A, B, C, D, E, F, G, H, I) -> J ): J { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - callsInPlace(action9, InvocationKind.EXACTLY_ONCE) - } - return zipOrAccumulate( - semigroup, - { zipOrAccumulate(semigroup, action1, action2, action3, action4, action5, action6, action7, action8) { x, y, z, u, v, w, a, b -> Tuple8(x, y, z, u, v, w, a, b) } }, - action9 - ) { xyzuvwab, c -> block(xyzuvwab.first, xyzuvwab.second, xyzuvwab.third, xyzuvwab.fourth, xyzuvwab.fifth, xyzuvwab.sixth, xyzuvwab.seventh, xyzuvwab.eighth, c) } -} - -/** - * Re-raise any errors in [block] in a [NonEmptyList]. - */ -@RaiseDSL -public inline fun Raise>.mapErrorNel( - crossinline block: Raise.() -> A -): A { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return recover(block) { raise(it.nel()) } + contract { callsInPlace(block, AT_MOST_ONCE) } + var error: Any? = EmptyValue + val a = recover({ action1(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val b = recover({ action2(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val c = recover({ action3(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val d = recover({ action4(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val e = recover({ action5(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val f = recover({ action6(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val g = recover({ action7(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val h = recover({ action8(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + val i = recover({ action9(RaiseAccumulate(this)) }) { error = combine(error, it.reduce(combine), combine); EmptyValue } + return if (error !== EmptyValue) raise(unbox(error)) + else block(unbox(a), unbox(b), unbox(c), unbox(d), unbox(e), unbox(f), unbox(g), unbox(h), unbox(i)) } /** @@ -281,20 +242,17 @@ public inline fun Raise>.mapErrorNel( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline block: Raise.(A, B) -> C + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + block: (A, B) -> C ): C { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { x, y -> mapErrorNel { block(x, y) } } - ) + action1, + action2, + {}) { a, b, _ -> + block(a, b) + } } /** @@ -302,23 +260,19 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline block: Raise.(A, B, C) -> D + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + block: (A, B, C) -> D ): D { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { x, y, z -> mapErrorNel { block(x, y, z) } } - ) + action1, + action2, + action3, + {}) { a, b, c, _ -> + block(a, b, c) + } } /** @@ -326,26 +280,21 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline block: Raise.(A, B, C, D) -> E + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + block: (A, B, C, D) -> E ): E { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { x, y, z, u -> mapErrorNel { block(x, y, z, u) } } - ) + action1, + action2, + action3, + action4, + {}) { a, b, c, d, _ -> + block(a, b, c, d) + } } /** @@ -353,29 +302,23 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline block: Raise.(A, B, C, D, E) -> F + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + block: (A, B, C, D, E) -> F ): F { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { x, y, z, u, v -> mapErrorNel { block(x, y, z, u, v) } } - ) + action1, + action2, + action3, + action4, + action5, + {}) { a, b, c, d, e, _ -> + block(a, b, c, d, e) + } } /** @@ -383,32 +326,25 @@ public inline fun Raise>.zipOrAccumulate( */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F) -> G + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + block: (A, B, C, D, E, F) -> G ): G { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { x, y, z, u, v, w -> mapErrorNel { block(x, y, z, u, v, w) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + {}) { a, b, c, d, e, f, _ -> + block(a, b, c, d, e, f) + } } /** @@ -416,35 +352,27 @@ public inline fun Raise>.zipOrAccumulat */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G) -> H + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + block: (A, B, C, D, E, F, G) -> H ): H { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { x, y, z, u, v, w, a -> mapErrorNel { block(x, y, z, u, v, w, a) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + action7, + {}) { a, b, c, d, e, f, g, _ -> + block(a, b, c, d, e, f, g) + } } /** @@ -452,38 +380,29 @@ public inline fun Raise>.zipOrAccumu */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline action8: Raise.() -> H, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G, H) -> I + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + block: (A, B, C, D, E, F, G, H) -> I ): I { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - } + contract { callsInPlace(block, AT_MOST_ONCE) } return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { mapErrorNel(action8) }, - { x, y, z, u, v, w, a, b -> mapErrorNel { block(x, y, z, u, v, w, a, b) } } - ) + action1, + action2, + action3, + action4, + action5, + action6, + action7, + action8, + {}) { a, b, c, d, e, f, g, h, _ -> + block(a, b, c, d, e, f, g, h) + } } /** @@ -491,80 +410,100 @@ public inline fun Raise>.zipOrAcc */ @RaiseDSL public inline fun Raise>.zipOrAccumulate( - @BuilderInference crossinline action1: Raise.() -> A, - @BuilderInference crossinline action2: Raise.() -> B, - @BuilderInference crossinline action3: Raise.() -> C, - @BuilderInference crossinline action4: Raise.() -> D, - @BuilderInference crossinline action5: Raise.() -> E, - @BuilderInference crossinline action6: Raise.() -> F, - @BuilderInference crossinline action7: Raise.() -> G, - @BuilderInference crossinline action8: Raise.() -> H, - @BuilderInference crossinline action9: Raise.() -> I, - @BuilderInference crossinline block: Raise.(A, B, C, D, E, F, G, H, I) -> J + @BuilderInference action1: RaiseAccumulate.() -> A, + @BuilderInference action2: RaiseAccumulate.() -> B, + @BuilderInference action3: RaiseAccumulate.() -> C, + @BuilderInference action4: RaiseAccumulate.() -> D, + @BuilderInference action5: RaiseAccumulate.() -> E, + @BuilderInference action6: RaiseAccumulate.() -> F, + @BuilderInference action7: RaiseAccumulate.() -> G, + @BuilderInference action8: RaiseAccumulate.() -> H, + @BuilderInference action9: RaiseAccumulate.() -> I, + block: (A, B, C, D, E, F, G, H, I) -> J ): J { - contract { - callsInPlace(action1, InvocationKind.EXACTLY_ONCE) - callsInPlace(action2, InvocationKind.EXACTLY_ONCE) - callsInPlace(action3, InvocationKind.EXACTLY_ONCE) - callsInPlace(action4, InvocationKind.EXACTLY_ONCE) - callsInPlace(action5, InvocationKind.EXACTLY_ONCE) - callsInPlace(action6, InvocationKind.EXACTLY_ONCE) - callsInPlace(action7, InvocationKind.EXACTLY_ONCE) - callsInPlace(action8, InvocationKind.EXACTLY_ONCE) - callsInPlace(action9, InvocationKind.EXACTLY_ONCE) - } - return zipOrAccumulate( - Semigroup.nonEmptyList(), - { mapErrorNel(action1) }, - { mapErrorNel(action2) }, - { mapErrorNel(action3) }, - { mapErrorNel(action4) }, - { mapErrorNel(action5) }, - { mapErrorNel(action6) }, - { mapErrorNel(action7) }, - { mapErrorNel(action8) }, - { mapErrorNel(action9) }, - { x, y, z, u, v, w, a, b, c -> mapErrorNel { block(x, y, z, u, v, w, a, b, c) } } - ) + contract { callsInPlace(block, AT_MOST_ONCE) } + val error: MutableList = mutableListOf() + val a = recover({ action1(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val b = recover({ action2(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val c = recover({ action3(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val d = recover({ action4(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val e = recover({ action5(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val f = recover({ action6(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val g = recover({ action7(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val h = recover({ action8(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + val i = recover({ action9(RaiseAccumulate(this)) }) { error.addAll(it); EmptyValue } + error.toNonEmptyListOrNull()?.let { raise(it) } + return block(unbox(a), unbox(b), unbox(c), unbox(d), unbox(e), unbox(f), unbox(g), unbox(h), unbox(i)) } /** - * Accumulate the errors obtained by executing the [block] - * over every element of [list] using the given [semigroup]. + * Transform every element of [list] using the given [transform], or accumulate all the occurred errors using [combine]. */ @RaiseDSL public inline fun Raise.mapOrAccumulate( - semigroup: Semigroup<@UnsafeVariance R>, list: Iterable, - @BuilderInference block: Raise.(A) -> B + combine: (R, R) -> R, + @BuilderInference transform: RaiseAccumulate.(A) -> B ): List { - // this could be implemented using [zipOrAccumulate], - // but we can have a faster implementation using [buildList] var error: Any? = EmptyValue - val results = buildList { - list.forEach { - fold({ - block(it) - }, { newError -> - error = semigroup.emptyCombine(error, newError) - }, { - add(it) - }) - } - } - return when (val e = EmptyValue.unbox(error)) { - null -> results - else -> raise(e) + val results = ArrayList(list.collectionSizeOrDefault(10)) + for (item in list) { + fold, B, Unit>( + { transform(RaiseAccumulate(this), item) }, + { errors -> error = combine(error, errors.reduce(combine), combine) }, + { results.add(it) } + ) } + return if (error === EmptyValue) results else raise(unbox(error)) } /** - * Accumulate the errors obtained by executing the [block] - * over every element of [list]. + * Accumulate the errors obtained by executing the [transform] over every element of [list]. */ @RaiseDSL public inline fun Raise>.mapOrAccumulate( list: Iterable, - @BuilderInference crossinline block: Raise.(A) -> B -): List = - mapOrAccumulate(Semigroup.nonEmptyList(), list) { elt -> mapErrorNel { block(elt) } } + @BuilderInference transform: RaiseAccumulate.(A) -> B +): List { + val error = mutableListOf() + val results = ArrayList(list.collectionSizeOrDefault(10)) + for (item in list) { + fold, B, Unit>( + { transform(RaiseAccumulate(this), item) }, + { errors -> error.addAll(errors) }, + { results.add(it) } + ) + } + return error.toNonEmptyListOrNull()?.let { raise(it) } ?: results +} + + +/** + * Receiver type belonging to [mapOrAccumulate]. + * Allows binding both [Either] and [EitherNel] values for [Either.Left] types of [Error]. + * It extends [Raise] of [Error], and allows working over [Raise] of [NonEmptyList] of [Error] as well. + */ +public open class RaiseAccumulate( + public val raise: Raise> +) : Raise { + + @RaiseDSL + public override fun raise(r: Error): Nothing = + raise.raise(nonEmptyListOf(r)) + + @RaiseDSL + public fun EitherNel.bindNel(): A = when (this) { + is Either.Left -> raise.raise(value) + is Either.Right -> value + } + + @RaiseDSL + public fun ValidatedNel.bindNel(): A = when (this) { + is Validated.Invalid -> raise.raise(value) + is Validated.Valid -> value + } + + @RaiseDSL + public inline fun withNel(block: Raise>.() -> A): A = + block(raise) +} 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 83e1c161984..c8f085283c7 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 @@ -55,8 +55,9 @@ class IterableTest : StringSpec({ "mapAccumulating accumulates" { checkAll(Arb.list(Arb.int())) { ints -> - val res: Either, List> = - ints.mapOrAccumulate { i -> if (i % 2 == 0) i else raise(i) } + 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() 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 5606e0e2483..9f2571f0fdc 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 @@ -55,15 +55,17 @@ class MappersSpec : StringSpec({ } } - "effect - orNull" { + "effect - getOrNull" { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> effect { a.bind() }.orNull() shouldBe a.getOrNull() + effect { a.bind() }.getOrNull() shouldBe a.getOrNull() } } - "eagerEffect - orNull" { + "eagerEffect - getOrNull" { checkAll(Arb.either(Arb.int(), Arb.string())) { a -> eagerEffect { a.bind() }.orNull() shouldBe a.getOrNull() + eagerEffect { a.bind() }.getOrNull() shouldBe a.getOrNull() } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-01.kt index e8e55884b74..ec7c5b7cd2a 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-01.kt @@ -1,14 +1,19 @@ // This file was automatically generated from Iterable.kt by Knit tool. Do not edit. package arrow.core.examples.exampleIterable01 -import arrow.core.* +import arrow.core.left +import arrow.core.leftNel +import arrow.core.nonEmptyListOf +import arrow.core.mapOrAccumulate +import io.kotest.matchers.shouldBe -val padRight = listOf(1, 2).padZip(listOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] -val padLeft = listOf(1).padZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] -val noPadding = listOf(1, 2).padZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] - -fun main() { - println("padRight = $padRight") - println("padLeft = $padLeft") - println("noPadding = $noPadding") +fun test() { + listOf(1, 2, 3, 4).mapOrAccumulate({ a, b -> "$a, $b" }) { i -> + when(i) { + 1 -> "Either - $i".left().bind() + 2 -> "EitherNel - $i".leftNel().bindNel() + 3 -> raise("Raise - $i") + else -> withNel { raise(nonEmptyListOf("RaiseNel - $i")) } + } + } shouldBe "Either - 1, EitherNel - 2, Raise - 3, RaiseNel - 4".left() } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-02.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-02.kt index de7a53a88a3..6158cc8a53a 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-02.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-02.kt @@ -1,14 +1,19 @@ // This file was automatically generated from Iterable.kt by Knit tool. Do not edit. package arrow.core.examples.exampleIterable02 -import arrow.core.* +import arrow.core.left +import arrow.core.leftNel +import arrow.core.nonEmptyListOf +import arrow.core.mapOrAccumulate +import io.kotest.matchers.shouldBe -val padZipRight = listOf(1, 2).padZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, null)] -val padZipLeft = listOf(1).padZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] -val noPadding = listOf(1, 2).padZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] - -fun main() { - println("padZipRight = $padZipRight") - println("padZipLeft = $padZipLeft") - println("noPadding = $noPadding") +fun test() { + listOf(1, 2, 3, 4).mapOrAccumulate { i -> + when(i) { + 1 -> "Either - $i".left().bind() + 2 -> "EitherNel - $i".leftNel().bindNel() + 3 -> raise("Raise - $i") + else -> withNel { raise(nonEmptyListOf("RaiseNel - $i")) } + } + } shouldBe nonEmptyListOf("Either - 1", "EitherNel - 2", "Raise - 3", "RaiseNel - 4").left() } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-03.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-03.kt index f15d4349974..7220b01277e 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-03.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-03.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleIterable03 import arrow.core.* -val left = listOf(1, 2).leftPadZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a")] -val right = listOf(1).leftPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] -val both = listOf(1, 2).leftPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] +val padRight = listOf(1, 2).padZip(listOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] +val padLeft = listOf(1).padZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] +val noPadding = listOf(1, 2).padZip(listOf("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-iterable-04.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-04.kt index aa5492be95e..1a8bd707d50 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-04.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-04.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleIterable04 import arrow.core.* -val padRight = listOf(1, 2).leftPadZip(listOf("a")) // Result: [Pair(1, "a")] -val padLeft = listOf(1).leftPadZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] -val noPadding = listOf(1, 2).leftPadZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] +val padZipRight = listOf(1, 2).padZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, null)] +val padZipLeft = listOf(1).padZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] +val noPadding = listOf(1, 2).padZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] 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-iterable-05.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-05.kt index 8ad499f39ff..27490224dde 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-05.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-05.kt @@ -3,9 +3,9 @@ package arrow.core.examples.exampleIterable05 import arrow.core.* -val left = listOf(1, 2).rightPadZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] -val right = listOf(1).rightPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a")] -val both = listOf(1, 2).rightPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] +val left = listOf(1, 2).leftPadZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a")] +val right = listOf(1).leftPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] +val both = listOf(1, 2).leftPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] fun main() { println("left = $left") diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-06.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-06.kt index 0c9feac4761..7e3c5822db4 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-06.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-06.kt @@ -3,9 +3,9 @@ package arrow.core.examples.exampleIterable06 import arrow.core.* -val padRight = listOf(1, 2).rightPadZip(listOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] -val padLeft = listOf(1).rightPadZip(listOf("a", "b")) // Result: [Pair(1, "a")] -val noPadding = listOf(1, 2).rightPadZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] +val padRight = listOf(1, 2).leftPadZip(listOf("a")) // Result: [Pair(1, "a")] +val padLeft = listOf(1).leftPadZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(null, "b")] +val noPadding = listOf(1, 2).leftPadZip(listOf("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-iterable-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-07.kt index cefd2cecdbe..c17aa3f905b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-07.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-07.kt @@ -3,12 +3,12 @@ package arrow.core.examples.exampleIterable07 import arrow.core.* -fun main(args: Array) { - //sampleStart - val result = - listOf("A", "B").align(listOf(1, 2, 3)) { - "$it" - } - //sampleEnd - println(result) +val left = listOf(1, 2).rightPadZip(listOf("a")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(null, "b")] +val right = listOf(1).rightPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a")] +val both = listOf(1, 2).rightPadZip(listOf("a", "b")) { l, r -> l to r } // Result: [Pair(1, "a"), Pair(2, "b")] + +fun main() { + println("left = $left") + println("right = $right") + println("both = $both") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-08.kt index ecd6d9d8d12..2d0bc39d9f2 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-08.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-08.kt @@ -3,10 +3,12 @@ package arrow.core.examples.exampleIterable08 import arrow.core.* -fun main(args: Array) { - //sampleStart - val result = - listOf("A", "B").align(listOf(1, 2, 3)) - //sampleEnd - println(result) +val padRight = listOf(1, 2).rightPadZip(listOf("a")) // Result: [Pair(1, "a"), Pair(2, null)] +val padLeft = listOf(1).rightPadZip(listOf("a", "b")) // Result: [Pair(1, "a")] +val noPadding = listOf(1, 2).rightPadZip(listOf("a", "b")) // Result: [Pair(1, "a"), Pair(2, "b")] + +fun main() { + println("padRight = $padRight") + println("padLeft = $padLeft") + println("noPadding = $noPadding") } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-09.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-09.kt index 77a24907c74..171ca9eef8b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-09.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-09.kt @@ -6,7 +6,9 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf("A" to 1, "B" to 2).unzip() + listOf("A", "B").align(listOf(1, 2, 3)) { + "$it" + } //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-10.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-10.kt index 18947bafeec..5c8535c4b19 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-10.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-10.kt @@ -6,11 +6,7 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf("A:1", "B:2", "C:3").unzip { e -> - e.split(":").let { - it.first() to it.last() - } - } + listOf("A", "B").align(listOf(1, 2, 3)) //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-11.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-11.kt index 02cd4700e7b..fa2f025d97b 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-11.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-11.kt @@ -6,8 +6,7 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf(("A" to 1).bothIor(), ("B" to 2).bothIor(), "C".leftIor()) - .unalign() + listOf("A" to 1, "B" to 2).unzip() //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-12.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-12.kt index b26baaa2191..28758c5065c 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-12.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-12.kt @@ -6,9 +6,11 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf(1, 2, 3).unalign { - it.leftIor() + listOf("A:1", "B:2", "C:3").unzip { e -> + e.split(":").let { + it.first() to it.last() } + } //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-13.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-13.kt index aba3d491dba..f93dd99df72 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-13.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-13.kt @@ -6,7 +6,8 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf("A", "B", "C").split() + listOf(("A" to 1).bothIor(), ("B" to 2).bothIor(), "C".leftIor()) + .unalign() //sampleEnd println(result) } 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 1d230b0e4e8..c2143c1bc65 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 @@ -5,9 +5,10 @@ import arrow.core.* fun main(args: Array) { //sampleStart - val tags = List(10) { "#" } val result = - tags.interleave(listOf("A", "B", "C")) + listOf(1, 2, 3).unalign { + it.leftIor() + } //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-15.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-15.kt index 3b4f078741e..e915d242aca 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-15.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-15.kt @@ -6,7 +6,7 @@ import arrow.core.* fun main(args: Array) { //sampleStart val result = - listOf(1,2,3).unweave { i -> listOf("$i, ${i + 1}") } + listOf("A", "B", "C").split() //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-16.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-16.kt index 5868fe6d58d..7b2b976d4a1 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-16.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-16.kt @@ -5,10 +5,9 @@ import arrow.core.* fun main(args: Array) { //sampleStart + val tags = List(10) { "#" } val result = - listOf(1,2,3).ifThen(listOf("empty")) { i -> - listOf("$i, ${i + 1}") - } + tags.interleave(listOf("A", "B", "C")) //sampleEnd println(result) } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-17.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-17.kt new file mode 100644 index 00000000000..8d4b009b66d --- /dev/null +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-17.kt @@ -0,0 +1,12 @@ +// This file was automatically generated from Iterable.kt by Knit tool. Do not edit. +package arrow.core.examples.exampleIterable17 + +import arrow.core.* + +fun main(args: Array) { + //sampleStart + val result = + listOf(1,2,3).unweave { i -> listOf("$i, ${i + 1}") } + //sampleEnd + println(result) +} 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 new file mode 100644 index 00000000000..b127d9abb1b --- /dev/null +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-iterable-18.kt @@ -0,0 +1,14 @@ +// This file was automatically generated from Iterable.kt by Knit tool. Do not edit. +package arrow.core.examples.exampleIterable18 + +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) +} diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-01.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-01.kt index 8ce9d79d137..163c7db7da3 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-01.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-01.kt @@ -6,5 +6,5 @@ import arrow.core.raise.recover fun Raise.failure(): Int = raise("failed") -fun Raise.recovered(): Int = +fun recovered(): Int = recover({ failure() }) { _: String -> 1 } 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 b899d1dc504..991d8f9b5c3 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 @@ -10,10 +10,10 @@ import io.kotest.matchers.shouldBe fun Raise.failure(): Int = raise("failed") -fun Raise.recovered(): Int = recover({ failure() }) { _: String -> 1 } +fun recovered(): Int = recover({ failure() }) { _: String -> 1 } fun test() { - val either = either { failure() } + val either: Either = either { failure() } .recover { _: String -> recovered() } either shouldBe Either.Right(1) 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 bd7dd603842..35a6bde4d6e 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 @@ -4,22 +4,12 @@ package arrow.core.examples.exampleRaiseDsl05 import arrow.core.Either import arrow.core.raise.either import arrow.core.raise.recover -import kotlinx.coroutines.delay import io.kotest.matchers.shouldBe -suspend fun test() { - val one: Result = Result.success(1) - val failure: Result = Result.failure(RuntimeException("Boom!")) +fun test() { + recover({ raise("failed") }) { str -> str.length } shouldBe 6 - either { - val x = one.bind { -1 } - val y = failure.bind { failure: Throwable -> - raise("Something bad happened: ${failure.message}") - } - val z = failure.recover { failure: Throwable -> - delay(10) - 1 - }.bind { raise("Something bad happened: ${it.message}") } - x + y + z - } shouldBe Either.Left("Something bad happened: Boom!") + either { + recover({ raise("failed") }) { str -> raise(-1) } + } shouldBe Either.Left(-1) } 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 91b3169be00..af03934f90f 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 @@ -1,23 +1,20 @@ // This file was automatically generated from Raise.kt by Knit tool. Do not edit. package arrow.core.examples.exampleRaiseDsl06 -import arrow.core.Either -import arrow.core.None -import arrow.core.Option -import arrow.core.recover -import arrow.core.raise.either -import kotlinx.coroutines.delay +import arrow.core.raise.recover +import arrow.core.raise.Raise import io.kotest.matchers.shouldBe -suspend fun test() { - val empty: Option = None - either { - val x: Int = empty.bind { _: None -> 1 } - val y: Int = empty.bind { _: None -> raise("Something bad happened: Boom!") } - val z: Int = empty.recover { _: None -> - delay(10) - 1 - }.bind { raise("Something bad happened: Boom!") } - x + y + z - } shouldBe Either.Left("Something bad happened: Boom!") +fun test() { + recover( + { raise("failed") }, + { str -> str.length } + ) { t -> t.message ?: -1 } shouldBe 6 + + fun Raise.boom(): Int = throw RuntimeException("BOOM") + + recover( + { boom() }, + { str -> str.length } + ) { t -> t.message?.length ?: -1 } shouldBe 4 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-07.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-07.kt index f1a29105f21..113825263b8 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-07.kt +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-07.kt @@ -1,17 +1,20 @@ // This file was automatically generated from Raise.kt by Knit tool. Do not edit. package arrow.core.examples.exampleRaiseDsl07 -import arrow.core.Either -import arrow.core.raise.either import arrow.core.raise.recover +import arrow.core.raise.Raise import io.kotest.matchers.shouldBe -suspend fun test() { - either { - recover({ raise("failed") }) { str -> str.length } - } shouldBe Either.Right(6) +fun test() { + recover( + { raise("failed") }, + { str -> str.length } + ) { t -> t.message ?: -1 } shouldBe 6 - either { - recover({ raise("failed") }) { str -> raise(-1) } - } shouldBe Either.Left(-1) + fun Raise.boom(): Int = throw RuntimeException("BOOM") + + recover( + { boom() }, + { str -> str.length } + ) { t: RuntimeException -> t.message?.length ?: -1 } shouldBe 4 } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-08.kt b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-08.kt new file mode 100644 index 00000000000..8e85db7aef9 --- /dev/null +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-08.kt @@ -0,0 +1,21 @@ +// This file was automatically generated from Raise.kt by Knit tool. Do not edit. +package arrow.core.examples.exampleRaiseDsl08 + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.catch +import io.kotest.matchers.shouldBe + +fun test() { + catch({ throw RuntimeException("BOOM") }) { t -> + "fallback" + } shouldBe "fallback" + + fun fetchId(): Int = throw RuntimeException("BOOM") + + either { + catch({ fetchId() }) { t -> + raise("something went wrong: ${t.message}") + } + } shouldBe Either.Left("something went wrong: BOOM") +} 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 new file mode 100644 index 00000000000..44988dcb7a1 --- /dev/null +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/example-raise-dsl-09.kt @@ -0,0 +1,21 @@ +// This file was automatically generated from Raise.kt by Knit tool. Do not edit. +package arrow.core.examples.exampleRaiseDsl09 + +import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.catch +import io.kotest.matchers.shouldBe + +fun test() { + catch({ throw RuntimeException("BOOM") }) { t -> + "fallback" + } shouldBe "fallback" + + fun fetchId(): Int = throw RuntimeException("BOOM") + + either { + catch({ fetchId() }) { t: RuntimeException -> + raise("something went wrong: ${t.message}") + } + } shouldBe Either.Left("something went wrong: BOOM") +} 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 new file mode 100644 index 00000000000..debed4ee2b7 --- /dev/null +++ b/arrow-libs/core/arrow-core/src/jvmTest/kotlin/examples/test/IterableKnitTest.kt @@ -0,0 +1,17 @@ +// 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 + +class IterableKnitTest : StringSpec({ + "ExampleIterable01" { + arrow.core.examples.exampleIterable01.test() + } + + "ExampleIterable02" { + arrow.core.examples.exampleIterable02.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 45cd92ebfa1..b92972bff01 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 @@ -28,6 +28,14 @@ class RaiseKnitTest : StringSpec({ arrow.core.examples.exampleRaiseDsl07.test() } + "ExampleRaiseDsl08" { + arrow.core.examples.exampleRaiseDsl08.test() + } + + "ExampleRaiseDsl09" { + arrow.core.examples.exampleRaiseDsl09.test() + } + }) { override fun timeout(): Long = 1000 } 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 60ca7e688f3..dce1eff086e 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 @@ -574,22 +574,9 @@ public final class arrow/fx/coroutines/ScheduleKt { public static final fun retryOrElseEither (Larrow/fx/coroutines/Schedule;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } -public final class arrow/fx/coroutines/ScopedRaise : arrow/core/continuations/EffectScope, kotlinx/coroutines/CoroutineScope { - public fun (Larrow/core/continuations/EffectScope;Lkotlinx/coroutines/CoroutineScope;)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 final class arrow/fx/coroutines/ScopedRaiseAccumulate : arrow/core/raise/RaiseAccumulate, kotlinx/coroutines/CoroutineScope { + public fun (Larrow/core/raise/Raise;Lkotlinx/coroutines/CoroutineScope;)V public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext; - public fun recover (Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; - public fun shift (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; } public final class arrow/fx/coroutines/Use { 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 751402ea818..6b6b0b94dfc 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 @@ -1,10 +1,11 @@ package arrow.fx.coroutines +import arrow.core.raise.RaiseAccumulate import arrow.core.Either import arrow.core.NonEmptyList -import arrow.core.continuations.EffectScope -import arrow.core.continuations.either import arrow.core.flattenOrAccumulate +import arrow.core.raise.Raise +import arrow.core.raise.either import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll @@ -15,12 +16,12 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext public suspend fun Iterable.parMap( - ctx: CoroutineContext = EmptyCoroutineContext, + context: CoroutineContext = EmptyCoroutineContext, concurrency: Int, f: suspend CoroutineScope.(A) -> B ): List { val semaphore = Semaphore(concurrency) - return parMap(ctx) { + return parMap(context) { semaphore.withPermit { f(it) } } } @@ -33,16 +34,16 @@ public suspend fun Iterable.parMap( } /** Temporary intersection type, until we have context receivers */ -public class ScopedRaise( - raise: EffectScope, +public class ScopedRaiseAccumulate( + raise: Raise>, scope: CoroutineScope -) : CoroutineScope by scope, EffectScope by raise +) : CoroutineScope by scope, RaiseAccumulate(raise) public suspend fun Iterable.parMapOrAccumulate( context: CoroutineContext = EmptyCoroutineContext, concurrency: Int, combine: (Error, Error) -> Error, - transform: suspend ScopedRaise.(A) -> B + transform: suspend ScopedRaiseAccumulate.(A) -> B ): Either> = coroutineScope { val semaphore = Semaphore(concurrency) @@ -50,7 +51,7 @@ public suspend fun Iterable.parMapOrAccumulate( async(context) { either { semaphore.withPermit { - transform(ScopedRaise(this, this@coroutineScope), it) + transform(ScopedRaiseAccumulate(this, this@coroutineScope), it) } } } @@ -60,13 +61,13 @@ public suspend fun Iterable.parMapOrAccumulate( public suspend fun Iterable.parMapOrAccumulate( context: CoroutineContext = EmptyCoroutineContext, combine: (Error, Error) -> Error, - transform: suspend ScopedRaise.(A) -> B + transform: suspend ScopedRaiseAccumulate.(A) -> B ): Either> = coroutineScope { map { async(context) { either { - transform(ScopedRaise(this, this@coroutineScope), it) + transform(ScopedRaiseAccumulate(this, this@coroutineScope), it) } } }.awaitAll().flattenOrAccumulate(combine) @@ -75,7 +76,7 @@ public suspend fun Iterable.parMapOrAccumulate( public suspend fun Iterable.parMapOrAccumulate( context: CoroutineContext = EmptyCoroutineContext, concurrency: Int, - transform: suspend ScopedRaise.(A) -> B + transform: suspend ScopedRaiseAccumulate.(A) -> B ): Either, List> = coroutineScope { val semaphore = Semaphore(concurrency) @@ -83,7 +84,7 @@ public suspend fun Iterable.parMapOrAccumulate( async(context) { either { semaphore.withPermit { - transform(ScopedRaise(this, this@coroutineScope), it) + transform(ScopedRaiseAccumulate(this, this@coroutineScope), it) } } } @@ -92,13 +93,13 @@ public suspend fun Iterable.parMapOrAccumulate( public suspend fun Iterable.parMapOrAccumulate( context: CoroutineContext = EmptyCoroutineContext, - transform: suspend ScopedRaise.(A) -> B + transform: suspend ScopedRaiseAccumulate.(A) -> B ): Either, List> = coroutineScope { map { async(context) { either { - transform(ScopedRaise(this, this@coroutineScope), it) + transform(ScopedRaiseAccumulate(this, this@coroutineScope), it) } } }.awaitAll().flattenOrAccumulate() 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 8c000f4b090..62946e3d91a 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 @@ -1,9 +1,11 @@ package arrow.fx.coroutines import arrow.core.Either +import arrow.core.EitherNel import arrow.core.NonEmptyList import arrow.core.continuations.either import arrow.core.left +import arrow.core.nonEmptyListOf import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.should import io.kotest.matchers.shouldBe @@ -143,7 +145,7 @@ class ParMapTest : StringSpec({ "parMapOrAccumulate accumulates shifts" { checkAll(Arb.string()) { e -> (0 until 100).parMapOrAccumulate { _ -> - shift(e) + raise(e) } shouldBe NonEmptyList(e, (1 until 100).map { e }).left() } } 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 a42decca9e3..35aca64ed08 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 @@ -1,39 +1,50 @@ package arrow.optics.plugin.internals -fun generateLensDsl(ele: ADT, optic: DataClassDsl): Snippet = - Snippet( +import com.google.devtools.ksp.getDeclaredProperties + +fun generateLensDsl(ele: ADT, optic: DataClassDsl): Snippet { + val (className, import) = resolveClassName(ele) + return Snippet( `package` = ele.packageName, name = ele.simpleName, - content = processLensSyntax(ele, optic.foci) + content = processLensSyntax(ele, optic.foci, className), + imports = setOf(import) ) +} -fun generateOptionalDsl(ele: ADT, optic: DataClassDsl): Snippet = - 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) + content = processOptionalSyntax(ele, optic, className), + imports = setOf(import) ) +} -fun generatePrismDsl(ele: ADT, isoOptic: SealedClassDsl): Snippet = - Snippet( +fun generatePrismDsl(ele: ADT, isoOptic: SealedClassDsl): Snippet { + val (className, import) = resolveClassName(ele) + return Snippet( `package` = ele.packageName, name = ele.simpleName, - content = processPrismSyntax(ele, isoOptic) + content = processPrismSyntax(ele, isoOptic, className), + imports = setOf(import) ) +} -private fun processLensSyntax(ele: ADT, foci: List): String = - if (ele.typeParameters.isEmpty()) { +private fun processLensSyntax(ele: ADT, foci: List, className: String): String { + return if (ele.typeParameters.isEmpty()) { foci.joinToString(separator = "\n") { focus -> - """ - |${ele.visibilityModifierName} inline val $Iso.${focus.lensParamName()}: $Lens inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Lens.${focus.lensParamName()}: $Lens inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Optional.${focus.lensParamName()}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Prism.${focus.lensParamName()}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Getter.${focus.lensParamName()}: $Getter inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Setter.${focus.lensParamName()}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Traversal.${focus.lensParamName()}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Fold.${focus.lensParamName()}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} - |${ele.visibilityModifierName} inline val $Every.${focus.lensParamName()}: $Every inline get() = this + ${ele.sourceClassName}.${focus.lensParamName()} + """ + |${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() } } else { @@ -41,20 +52,21 @@ private fun processLensSyntax(ele: ADT, foci: List): String = val joinedTypeParams = ele.typeParameters.joinToString(separator=",") foci.joinToString(separator = "\n") { focus -> """ - |${ele.visibilityModifierName} inline fun $Iso.${focus.lensParamName()}(): $Lens = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Lens.${focus.lensParamName()}(): $Lens = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Optional.${focus.lensParamName()}(): $Optional = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Prism.${focus.lensParamName()}(): $Optional = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Getter.${focus.lensParamName()}(): $Getter = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.lensParamName()}(): $Setter = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Traversal.${focus.lensParamName()}(): $Traversal = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.lensParamName()}(): $Fold = this + ${ele.sourceClassName}.${focus.lensParamName()}() - |${ele.visibilityModifierName} inline fun $Every.${focus.lensParamName()}(): $Every = this + ${ele.sourceClassName}.${focus.lensParamName()}() + |${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): String { +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 -> @@ -66,42 +78,42 @@ private fun processOptionalSyntax(ele: ADT, optic: DataClassDsl): String { } if (ele.typeParameters.isEmpty()) { """ - |${ele.visibilityModifierName} inline val $Iso.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Lens.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Optional.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Prism.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Setter.${focus.paramName}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Traversal.${focus.paramName}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Fold.${focus.paramName}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Every.${focus.paramName}: $Every inline get() = this + ${ele.sourceClassName}.${focus.paramName} + |${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 + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Lens.${focus.paramName}(): $Optional = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Optional.${focus.paramName}(): $Optional = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Prism.${focus.paramName}(): $Optional = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.paramName}(): $Setter = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Traversal.${focus.paramName}(): $Traversal = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.paramName}(): $Fold = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Every.${focus.paramName}(): $Every = this + ${ele.sourceClassName}.${focus.paramName}() + |${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): String = - if (ele.typeParameters.isEmpty()) { +private fun processPrismSyntax(ele: ADT, dsl: SealedClassDsl, className: String): String { + return if (ele.typeParameters.isEmpty()) { dsl.foci.joinToString(separator = "\n\n") { focus -> - """ - |${ele.visibilityModifierName} inline val $Iso.${focus.paramName}: $Prism inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Lens.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Optional.${focus.paramName}: $Optional inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Prism.${focus.paramName}: $Prism inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Setter.${focus.paramName}: $Setter inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Traversal.${focus.paramName}: $Traversal inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Fold.${focus.paramName}: $Fold inline get() = this + ${ele.sourceClassName}.${focus.paramName} - |${ele.visibilityModifierName} inline val $Every.${focus.paramName}: $Every inline get() = this + ${ele.sourceClassName}.${focus.paramName} + """ + |${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() } } else { @@ -111,15 +123,31 @@ private fun processPrismSyntax(ele: ADT, dsl: SealedClassDsl): String = focus.refinedArguments.isEmpty() -> "" else -> focus.refinedArguments.joinToString(separator=",") } - """ - |${ele.visibilityModifierName} inline fun $Iso.${focus.paramName}(): $Prism = this + ${ele.sourceClassName}.${focus.paramName}() + """ + |${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 + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Prism.${focus.paramName}(): $Prism = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Setter.${focus.paramName}(): $Setter = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Traversal.${focus.paramName}(): $Traversal = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Fold.${focus.paramName}(): $Fold = this + ${ele.sourceClassName}.${focus.paramName}() - |${ele.visibilityModifierName} inline fun $Every.${focus.paramName}(): $Every = 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 resolveClassName(ele: ADT): Pair = if (hasPackageCollisions(ele)) { + val classNameAlias = ele.sourceClassName.replace(".", "") + val aliasImport = "import ${ele.sourceClassName} as $classNameAlias" + classNameAlias to aliasImport +} else ele.sourceClassName to "" + +private fun hasPackageCollisions(ele: ADT): Boolean = + ele.declaration.getDeclaredProperties().let { properties -> + ele.packageName + .split(".") + .any { p -> + properties.any { it.simpleName.asString() == p } + } + } 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 dffa7ddf7b6..9fe6cfd5c8f 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 @@ -46,5 +46,20 @@ class DSLTests { """.compilationSucceeds() } + @Test + fun `DSL for a data class with property named as a package directive`() { + """ + |package main.program + | + |$imports + | + |@optics + |data class Source(val program: String) { + | companion object + |} + | + """.compilationSucceeds() + } + // Db.content.at(At.map(), One).set(db, None) } diff --git a/build.gradle.kts b/build.gradle.kts index 1c8d26ad8fd..adc8515dc17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,9 @@ @file:Suppress("DSL_SCOPE_VIOLATION") +import org.jetbrains.dokka.gradle.DokkaMultiModuleTask +import org.jetbrains.dokka.gradle.DokkaTaskPartial +import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension + buildscript { repositories { mavenCentral() @@ -69,6 +73,31 @@ val enableCompatibilityMetadataVariant = providers.gradleProperty("kotlin.mpp.enableCompatibilityMetadataVariant") .orNull?.toBoolean() == true +subprojects { + this@subprojects.tasks.withType().configureEach { + this@subprojects.extensions.findByType()?.sourceSets?.forEach { kotlinSourceSet -> + dokkaSourceSets.named(kotlinSourceSet.name) { + perPackageOption { + matchingRegex.set(".*\\.internal.*") + suppress.set(true) + } + if (project.name == "arrow-fx-coroutines") externalDocumentationLink("https://kotlinlang.org/api/kotlinx.coroutines/") + skipDeprecated.set(true) + reportUndocumented.set(false) + val baseUrl: String = checkNotNull(properties["pom.smc.url"]?.toString()) + + kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> + sourceLink { + localDirectory.set(srcDir) + remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL()) + remoteLineSuffix.set("#L") + } + } + } + } + } +} + tasks { val generateDoc by creating(Exec::class) { group = "documentation" @@ -86,8 +115,24 @@ tasks { dokkaGfmMultiModule { removeChildTasks(undocumentedProjects) } dokkaHtmlMultiModule { removeChildTasks(undocumentedProjects) } dokkaJekyllMultiModule { removeChildTasks(undocumentedProjects) } + + getByName("knitPrepare").dependsOn(getTasksByName("dokka", true)) + + withType().configureEach { + outputDirectory.set(docFolder()) + moduleName.set("Arrow") + } + + register("cleanDocs") { + val folder = docFolder() + val content = folder.listFiles()?.filter { it != folder } + delete(content) + } } +fun docFolder(): File = + project.properties["githubpages"]?.let { file("docs").also { it.mkdir() } } ?: rootDir.resolve("arrow-site/docs/apidocs") + apiValidation { val ignoreApiValidation = if (!enableCompatibilityMetadataVariant) { listOf("arrow-optics-ksp-plugin", "arrow-site") diff --git a/gradle.properties b/gradle.properties index 34dd2421a6c..69de6a1556d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -35,3 +35,5 @@ ROOT_PROJECT=../gradle/main.gradle TEST_COVERAGE=../../gradle/test-coverage.gradle ANIMALSNIFFER=../../gradle/animalsniffer.gradle ANIMALSNIFFER_MPP=../../gradle/animalsniffer-mpp.gradle + +dokkaEnabled=false diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index fc10b601f7c..f398c33c4b0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists