From 76e0ee416adc1b3a3d275e906b65a8ee35948d75 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Mon, 29 Dec 2025 22:39:35 +0000 Subject: [PATCH 01/16] Add NonEmptyCollection builders --- .../kotlin/arrow/core/NonEmptyList.kt | 245 ++++++++++-- arrow-libs/core/arrow-core/build.gradle.kts | 1 + .../kotlin/arrow/core/NonEmptyCollection.kt | 124 ++++-- .../kotlin/arrow/core/NonEmptyList.kt | 376 ++++++++++++++---- .../kotlin/arrow/core/NonEmptySet.kt | 130 ++++-- .../arrow/core/raise/RaiseAccumulate.kt | 60 ++- .../kotlin/arrow/core/NonEmptyListTest.kt | 12 +- .../kotlin/arrow/core/NonEmptySetTest.kt | 4 +- .../kotlin/arrow/core/test/Generators.kt | 7 +- 9 files changed, 752 insertions(+), 207 deletions(-) diff --git a/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt b/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt index c15b2ff31f3..bd831161767 100644 --- a/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt +++ b/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt @@ -1,6 +1,5 @@ @file:JvmName("NonEmptyListHighArityKt") -@file:OptIn(ExperimentalContracts::class, PotentiallyUnsafeNonEmptyOperation::class) -@file:Suppress("WRONG_INVOCATION_KIND", "LEAKED_IN_PLACE_LAMBDA") +@file:OptIn(ExperimentalContracts::class) package arrow.core @@ -23,25 +22,22 @@ public inline fun NonEmptyList R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, map).wrapAsNonEmptyListOrThrow() -} - -public inline fun NonEmptyList.zip( - t1: NonEmptyList, - t2: NonEmptyList, - t3: NonEmptyList, - t4: NonEmptyList, - t5: NonEmptyList, - t6: NonEmptyList, - t7: NonEmptyList, - t8: NonEmptyList, - t9: NonEmptyList, - t10: NonEmptyList, - t11: NonEmptyList, - map: (A, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R, -): NonEmptyList { - contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -60,7 +56,24 @@ public inline fun NonE map: (A, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -80,7 +93,25 @@ public inline fun map: (A, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) -> R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -101,7 +132,26 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -123,7 +173,27 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -146,7 +216,28 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, t16.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + val i16 = t16.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size, t16.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next(), i16.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext() && i16.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -170,7 +261,29 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, t16.all, t17.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + val i16 = t16.iterator() + val i17 = t17.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size, t16.size, t17.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next(), i16.next(), i17.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext() && i16.hasNext() && i17.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -195,7 +308,30 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, t16.all, t17.all, t18.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + val i16 = t16.iterator() + val i17 = t17.iterator() + val i18 = t18.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size, t16.size, t17.size, t18.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next(), i16.next(), i17.next(), i18.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext() && i16.hasNext() && i17.hasNext() && i18.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -221,7 +357,31 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, t16.all, t17.all, t18.all, t19.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + val i16 = t16.iterator() + val i17 = t17.iterator() + val i18 = t18.iterator() + val i19 = t19.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size, t16.size, t17.size, t18.size, t19.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next(), i16.next(), i17.next(), i18.next(), i19.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext() && i16.hasNext() && i17.hasNext() && i18.hasNext() && i19.hasNext()) + this + } } public inline fun NonEmptyList.zip( @@ -248,5 +408,30 @@ public inline fun R, ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(t1.all, t2.all, t3.all, t4.all, t5.all, t6.all, t7.all, t8.all, t9.all, t10.all, t11.all, t12.all, t13.all, t14.all, t15.all, t16.all, t17.all, t18.all, t19.all, t20.all, map).wrapAsNonEmptyListOrThrow() + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + val i12 = t12.iterator() + val i13 = t13.iterator() + val i14 = t14.iterator() + val i15 = t15.iterator() + val i16 = t16.iterator() + val i17 = t17.iterator() + val i18 = t18.iterator() + val i19 = t19.iterator() + val i20 = t20.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size, t12.size, t13.size, t14.size, t15.size, t16.size, t17.size, t18.size, t19.size, t20.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next(), i12.next(), i13.next(), i14.next(), i15.next(), i16.next(), i17.next(), i18.next(), i19.next(), i20.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext() && i12.hasNext() && i13.hasNext() && i14.hasNext() && i15.hasNext() && i16.hasNext() && i17.hasNext() && i18.hasNext() && i19.hasNext() && i20.hasNext()) + this + } } diff --git a/arrow-libs/core/arrow-core/build.gradle.kts b/arrow-libs/core/arrow-core/build.gradle.kts index e739533eae2..0d3a1524ac4 100644 --- a/arrow-libs/core/arrow-core/build.gradle.kts +++ b/arrow-libs/core/arrow-core/build.gradle.kts @@ -9,6 +9,7 @@ plugins { kotlin { compilerOptions.freeCompilerArgs.add("-Xexpect-actual-classes") compilerOptions.freeCompilerArgs.add("-Xcontext-parameters") + compilerOptions.freeCompilerArgs.add("-Xallow-contracts-on-more-functions") sourceSets { val nonJvmAndJsMain by creating { dependsOn(nonJvmMain.get()) } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt index c53acfa70a1..5479dbce298 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt @@ -1,45 +1,71 @@ +@file:Suppress("API_NOT_AVAILABLE") +@file:OptIn(ExperimentalContracts::class) package arrow.core +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + /** * Common interface for collections that always have * at least one element (available from [head]). */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) public interface NonEmptyCollection : Collection { override fun isEmpty(): Boolean = false - public val head: E + public val head: E get() = first() public operator fun plus(element: @UnsafeVariance E): NonEmptyCollection public operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyCollection - public fun toNonEmptySet(): NonEmptySet = toNonEmptySetOrThrow() - public fun toNonEmptyList(): NonEmptyList = toNonEmptyListOrThrow() + public fun toNonEmptySet(): NonEmptySet = buildNonEmptySet(size) { + addAll(this@NonEmptyCollection) + this + } + + public fun toNonEmptyList(): NonEmptyList = buildNonEmptyList(size) { + addAll(this@NonEmptyCollection) + this + } // These functions take precedence over the extensions in [Collection]. // This way non-emptiness is tracked by the type system. public fun firstOrNull(): E = head - public fun lastOrNull(): E - - public fun distinct(): NonEmptyList = - delegate { it.distinct() } - public fun distinctBy(selector: (E) -> K): NonEmptyList = - delegate { it.distinctBy(selector) } - public fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = - delegate { it.flatMap(transform) } - public fun map(transform: (E) -> T): NonEmptyList = - delegate { it.map(transform) } - public fun mapIndexed(transform: (index:Int, E) -> T): NonEmptyList = - delegate { it.mapIndexed(transform) } - public fun zip(other: NonEmptyCollection): NonEmptyCollection> = - delegate { it.zip(other) } - - /** - * Convenience method which delegates the implementation to [Collection], - * and wraps the resulting [List] as a non-empty one. - */ - @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private inline fun delegate(crossinline f: (Collection) -> List): NonEmptyList = - f(this as Collection).wrapAsNonEmptyListOrThrow() + public fun lastOrNull(): E = last() + + public fun distinct(): NonEmptyList = toNonEmptySet().toNonEmptyList() + public fun distinctBy(selector: (E) -> K): NonEmptyList = buildNonEmptyList(size) { + add(head) // head is always distinct + val seen = hashSetOf() + var isFirst = true + for (e in this@NonEmptyCollection) { + if (seen.add(selector(e)) && !isFirst) add(e) + isFirst = false + } + this + } + public fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { + val iterator = this@NonEmptyCollection.iterator() + do addAll(transform(iterator.next())) while (iterator.hasNext()) + this + } + public fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { + val iterator = this@NonEmptyCollection.iterator() + do add(transform(iterator.next())) while (iterator.hasNext()) + this + } + public fun mapIndexed(transform: (index:Int, E) -> T): NonEmptyList = buildNonEmptyList(size) { + var i = 0 + val iterator = this@NonEmptyCollection.iterator() + do add(transform(i++, iterator.next())) while (iterator.hasNext()) + this + } + public fun zip(other: NonEmptyCollection): NonEmptyCollection> = buildNonEmptyList(minOf(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) { + val first = this@NonEmptyCollection.iterator() + val second = other.iterator() + do add(first.next() to second.next()) while (first.hasNext() && second.hasNext()) + this + } } /** @@ -48,5 +74,51 @@ public interface NonEmptyCollection : Collection { */ @RequiresOptIn @Retention(AnnotationRetention.BINARY) -@Target(AnnotationTarget.FUNCTION) +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR) public annotation class PotentiallyUnsafeNonEmptyOperation + +/** + * A mutable collection that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableCollection: Collection { + // underscored so that addAll(Nec) extension overload takes precedence + @IgnorableReturnValue + public fun _addAll(elements: Collection): Boolean + + @IgnorableReturnValue + public fun _add(element: E): Boolean +} + +@IgnorableReturnValue +public fun MonotoneMutableCollection.add(element: E): Boolean { + contract { returns() implies (this@add is NonEmptyCollection) } + return _add(element) +} + +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: Iterable): Boolean = when (elements) { + is Collection -> addAll(elements) + else -> { + var result = false + for (item in elements) if (add(item)) result = true + result + } +} + +@OptIn(ExperimentalContracts::class) +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: NonEmptyCollection): Boolean { + contract { returns() implies (this@addAll is NonEmptyCollection) } + return _addAll(elements) +} + +@OptIn(ExperimentalContracts::class) +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: Collection): Boolean = _addAll(elements) + +public fun MonotoneMutableCollection.isNonEmpty(): Boolean { + contract { returns(true) implies (this@isNonEmpty is NonEmptyCollection) } + return isNotEmpty() +} 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 513d70b31aa..98d54ee8088 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt @@ -3,7 +3,13 @@ package arrow.core +import arrow.core.Ior.Left +import arrow.core.Ior.Right +import arrow.core.Ior.Both import arrow.core.raise.RaiseAccumulate +import arrow.core.raise.either +import arrow.core.raise.mapOrAccumulate +import arrow.core.raise.withError import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @@ -154,12 +160,16 @@ public typealias Nel = NonEmptyList * - `a.zip(b, c) { ... }` can be used to compute over multiple `NonEmptyList` values preserving type information and __abstracting over arity__ with `zip` * */ +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) @JvmInline -public value class NonEmptyList @PublishedApi internal constructor( +public value class NonEmptyList @PotentiallyUnsafeNonEmptyOperation @PublishedApi internal constructor( public val all: List ) : List by all, NonEmptyCollection { - - public constructor(head: E, tail: List): this(listOf(head) + tail) + public constructor(head: E, tail: List): this(buildNonEmptyList(tail.size + 1) { + add(head) + addAll(tail) + this + }.all) override fun equals(other: Any?): Boolean = when (other) { is NonEmptyList<*> -> this.all == other.all @@ -173,57 +183,79 @@ public value class NonEmptyList @PublishedApi internal constructor( @JvmExposeBoxed @Suppress("USELESS_JVM_EXPOSE_BOXED") public fun toList(): List = all - public override val head: E - get() = all.first() - public val tail: List get() = all.subList(1, all.size) - override fun lastOrNull(): E = all.last() - - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - public override inline fun distinct(): NonEmptyList = - NonEmptyList(all.distinct()) - @Suppress("OVERRIDE_BY_INLINE") - public override inline fun distinctBy(selector: (E) -> K): NonEmptyList = - NonEmptyList(all.distinctBy(selector)) + public override inline fun distinctBy(selector: (E) -> K): NonEmptyList = buildNonEmptyList(size) { + add(head) // head is always distinct + val seen = hashSetOf() + var isFirst = true + for (e in all) { + if (seen.add(selector(e)) && !isFirst) add(e) + isFirst = false + } + this + } + // These can be simplified by introducing some forEachNonEmpty extension, but we'd need + // "KT-83404 Smart casts don't propagate past scoping functions" fixed first. @Suppress("OVERRIDE_BY_INLINE") - public override inline fun map(transform: (E) -> T): NonEmptyList = - NonEmptyList(all.map(transform)) + public override inline fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { + val iterator = all.iterator() + do add(transform(iterator.next())) while (iterator.hasNext()) + this + } @Suppress("OVERRIDE_BY_INLINE") - public override inline fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = - NonEmptyList(all.flatMap(transform)) + public override inline fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { + val iterator = all.iterator() + do addAll(transform(iterator.next())) while (iterator.hasNext()) + this + } @Suppress("OVERRIDE_BY_INLINE") - public override inline fun mapIndexed(transform: (index: Int, E) -> T): NonEmptyList = - NonEmptyList(all.mapIndexed(transform)) + public override inline fun mapIndexed(transform: (index: Int, E) -> T): NonEmptyList = buildNonEmptyList(size) { + val iterator = all.iterator() + var index = 0 + do add(transform(index++, iterator.next())) while (iterator.hasNext()) + this + } public operator fun plus(l: NonEmptyList<@UnsafeVariance E>): NonEmptyList = this + l.all - public override operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyList = - NonEmptyList(all + elements) + override fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyList = buildNonEmptyList(size + elements.collectionSizeOrDefault(10)) { + addAll(this@NonEmptyList) + addAll(elements) + this + } - public override operator fun plus(element: @UnsafeVariance E): NonEmptyList = - NonEmptyList(all + element) + override fun plus(element: @UnsafeVariance E): NonEmptyList = buildNonEmptyList(size + 1) { + addAll(this@NonEmptyList) + add(element) + this + } - @Suppress("WRONG_INVOCATION_KIND") public inline fun foldLeft(b: Acc, f: (Acc, E) -> Acc): Acc { contract { callsInPlace(f, InvocationKind.AT_LEAST_ONCE) } - return all.fold(b) { acc, e -> f(acc, e) } + var accumulator = b + val iterator = iterator() + do accumulator = f(accumulator, iterator.next()) while (iterator.hasNext()) + return accumulator } public inline fun coflatMap(f: (NonEmptyList) -> T): NonEmptyList { contract { callsInPlace(f, InvocationKind.AT_LEAST_ONCE) } - return buildList { + var current = this + return buildNonEmptyList(all.size + 1) { var i = 0 - // Inv: i < size - do add(f(NonEmptyList(all.subList(i, all.size)))) - while (++i < all.size) - }.let(::NonEmptyList) + do { + add(f(current)) + current = all.subList(++i, all.size).wrapAsNonEmptyListOrNull() ?: break + } while (true) + this + } } public fun extract(): E = @@ -232,15 +264,21 @@ public value class NonEmptyList @PublishedApi internal constructor( override fun toString(): String = all.toString() public fun align(other: NonEmptyList): NonEmptyList> = - NonEmptyList(all.align(other)) + padZip(other, ::Left, ::Right, ::Both) public fun padZip(other: NonEmptyList): NonEmptyList> = padZip(other, { it to null }, { null to it }, { a, b -> a to b }) - @Suppress("WRONG_INVOCATION_KIND") public inline fun padZip(other: NonEmptyList, left: (E) -> C, right: (B) -> C, both: (E, B) -> C): NonEmptyList { contract { callsInPlace(both, InvocationKind.AT_LEAST_ONCE) } - return all.padZip(other, left, right) { e, b -> both(e, b) }.let(::NonEmptyList) + val first = iterator() + val second = other.iterator() + return buildNonEmptyList(maxOf(this.collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) { + do add(both(first.next(), second.next())) while (first.hasNext() && second.hasNext()) + while (first.hasNext()) add(left(first.next())) + while (second.hasNext()) add(right(second.next())) + this + } } public companion object { @@ -260,26 +298,36 @@ public value class NonEmptyList @PublishedApi internal constructor( public fun zip(other: NonEmptyList): NonEmptyList> = zip(other, ::Pair) - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, map: (E, B) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b) { a, bb -> map(a, bb) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + return buildNonEmptyList(minOf(this.size, b.size)) { + do add(map(aa.next(), bb.next())) + while (aa.hasNext() && bb.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, map: (E, B, C) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c) { a, bb, cc -> map(a, bb, cc) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size)) { + do add(map(aa.next(), bb.next(), cc.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -287,10 +335,17 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d) { a, bb, cc, dd -> map(a, bb, cc, dd) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -299,10 +354,18 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e) { a, bb, cc, dd, ee -> map(a, bb, cc, dd, ee) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -312,10 +375,19 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F, G) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e, f) { a, bb, cc, dd, ee, ff -> map(a, bb, cc, dd, ee, ff) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + val ff = f.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size, f.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next(), ff.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext() && ff.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -326,10 +398,20 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F, G, H) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e, f, g) { a, bb, cc, dd, ee, ff, gg -> map(a, bb, cc, dd, ee, ff, gg) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + val ff = f.iterator() + val gg = g.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size, f.size, g.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next(), ff.next(), gg.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext() && ff.hasNext() && gg.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -341,10 +423,21 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F, G, H, I) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e, f, g, h) { a, bb, cc, dd, ee, ff, gg, hh -> map(a, bb, cc, dd, ee, ff, gg, hh) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + val ff = f.iterator() + val gg = g.iterator() + val hh = h.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size, f.size, g.size, h.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next(), ff.next(), gg.next(), hh.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext() && ff.hasNext() && gg.hasNext() && hh.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -357,10 +450,22 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F, G, H, I, J) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e, f, g, h, i) { a, bb, cc, dd, ee, ff, gg, hh, ii -> map(a, bb, cc, dd, ee, ff, gg, hh, ii) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + val ff = f.iterator() + val gg = g.iterator() + val hh = h.iterator() + val ii = i.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size, f.size, g.size, h.size, i.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next(), ff.next(), gg.next(), hh.next(), ii.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext() && ff.hasNext() && gg.hasNext() && hh.hasNext() && ii.hasNext()) + this + } } - @Suppress("WRONG_INVOCATION_KIND") public inline fun zip( b: NonEmptyList, c: NonEmptyList, @@ -374,18 +479,33 @@ public value class NonEmptyList @PublishedApi internal constructor( map: (E, B, C, D, F, G, H, I, J, K) -> Z ): NonEmptyList { contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } - return all.zip(b, c, d, e, f, g, h, i, j) { a, bb, cc, dd, ee, ff, gg, hh, ii, jj -> map(a, bb, cc, dd, ee, ff, gg, hh, ii, jj) }.let(::NonEmptyList) + val aa = iterator() + val bb = b.iterator() + val cc = c.iterator() + val dd = d.iterator() + val ee = e.iterator() + val ff = f.iterator() + val gg = g.iterator() + val hh = h.iterator() + val ii = i.iterator() + val jj = j.iterator() + return buildNonEmptyList(minOf(this.size, b.size, c.size, d.size, e.size, f.size, g.size, h.size, i.size, j.size)) { + do add(map(aa.next(), bb.next(), cc.next(), dd.next(), ee.next(), ff.next(), gg.next(), hh.next(), ii.next(), jj.next())) + while (aa.hasNext() && bb.hasNext() && cc.hasNext() && dd.hasNext() && ee.hasNext() && ff.hasNext() && gg.hasNext() && hh.hasNext() && ii.hasNext() && jj.hasNext()) + this + } } } @JvmName("nonEmptyListOf") -public fun nonEmptyListOf(head: E, vararg t: E): NonEmptyList = - NonEmptyList(listOf(head) + t) +public fun nonEmptyListOf(head: E, vararg t: E): NonEmptyList = NonEmptyList(head, t.asList()) @JvmName("nel") @Suppress("NOTHING_TO_INLINE") -public inline fun E.nel(): NonEmptyList = - NonEmptyList(listOf(this)) +public inline fun E.nel(): NonEmptyList = buildNonEmptyList(1) { + add(this@nel) + this +} public operator fun > NonEmptyList.compareTo(other: NonEmptyList): Int = all.compareTo(other.all) @@ -410,38 +530,43 @@ public inline fun > NonEmptyList.max(): E = public fun NonEmptyList>.unzip(): Pair, NonEmptyList> = this.unzip(::identity) -@Suppress("WRONG_INVOCATION_KIND") public inline fun NonEmptyList.unzip(f: (E) -> Pair): Pair, NonEmptyList> { contract { callsInPlace(f, InvocationKind.AT_LEAST_ONCE) } - val size = this.size - val listA = ArrayList(size) - val listB = ArrayList(size) - for (element in this) { - val (a, b) = f(element) + val size = size + val listA = MonotoneMutableList(size) + val listB = MonotoneMutableList(size) + val iterator = iterator() + do { + val (a, b) = f(iterator.next()) listA.add(a) listB.add(b) - } - return NonEmptyList(listA) to NonEmptyList(listB) + } while (iterator.hasNext()) + return listA.asNonEmptyList() to listB.asNonEmptyList() } public inline fun NonEmptyList.mapOrAccumulate( combine: (Error, Error) -> Error, @BuilderInference transform: RaiseAccumulate.(E) -> T -): Either> = - all.mapOrAccumulate(combine, transform).map(::NonEmptyList) +): Either> = either { + withError({ it.reduce(combine) }) { + mapOrAccumulate(this@mapOrAccumulate, transform) + } +} public inline fun NonEmptyList.mapOrAccumulate( @BuilderInference transform: RaiseAccumulate.(E) -> T -): Either, NonEmptyList> = - all.mapOrAccumulate(transform).map(::NonEmptyList) +): Either, NonEmptyList> = either { + mapOrAccumulate(this@mapOrAccumulate, transform) +} /** * Returns a [NonEmptyList] that contains a **copy** of the elements in [this]. */ -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) @JvmName("toNonEmptyListOrNull") -public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = - toList().wrapAsNonEmptyListOrNull() +public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = MonotoneMutableList(collectionSizeOrDefault(10)).run { + addAll(this@toNonEmptyListOrNull) + if (isNonEmpty()) asNonEmptyList() else null +} /** * Returns a [NonEmptyList] that contains a **copy** of the elements in [this]. @@ -453,10 +578,8 @@ public fun Iterable.toNonEmptyListOrNone(): Option> = /** * Returns a [NonEmptyList] that contains a **copy** of the elements in [this]. */ -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) @JvmName("toNonEmptyListOrThrow") -public fun Iterable.toNonEmptyListOrThrow(): NonEmptyList = - toList().wrapAsNonEmptyListOrThrow() +public fun Iterable.toNonEmptyListOrThrow(): NonEmptyList = toNonEmptyListOrNull() ?: throw IllegalArgumentException("Cannot create NonEmptyList from empty Iterable") /** * Returns a [NonEmptyList] that wraps the given [this], avoiding an additional copy. @@ -465,11 +588,7 @@ public fun Iterable.toNonEmptyListOrThrow(): NonEmptyList = * You are responsible for keeping the non-emptiness invariant at all times. */ @PotentiallyUnsafeNonEmptyOperation -public fun List.wrapAsNonEmptyListOrThrow(): NonEmptyList { - require(isNotEmpty()) - return NonEmptyList(this) -} - +public fun List.wrapAsNonEmptyListOrThrow(): NonEmptyList = wrapAsNonEmptyListOrNull() ?: throw IllegalArgumentException("Cannot wrap an empty list as NonEmptyList") /** * Returns a [NonEmptyList] that wraps the given [this], avoiding an additional copy. * @@ -481,3 +600,102 @@ public fun List.wrapAsNonEmptyListOrNull(): NonEmptyList? = when { isEmpty() -> null else -> NonEmptyList(this) } + +/** + * A mutable list that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableList: MonotoneMutableCollection, List { + @IgnorableReturnValue + public fun _addAll(index: Int, elements: Collection): Boolean + + @IgnorableReturnValue + public operator fun set(index: Int, element: E): E + + public fun _add(index: Int, element: E) + + override fun listIterator(): Iterator + + override fun listIterator(index: Int): Iterator + + override fun subList(fromIndex: Int, toIndex: Int): MonotoneMutableList + + public companion object { + public operator fun invoke(): MonotoneMutableList = Impl() + + public operator fun invoke(initialCapacity: Int): MonotoneMutableList = Impl(initialCapacity) + + public operator fun invoke(elements: Collection): MonotoneMutableList = Impl(elements) + } + + public interface Iterator : ListIterator { + public fun set(element: T) + + public fun add(element: T) + } + + private class IteratorImpl(private val underlying: MutableListIterator) : Iterator, ListIterator by underlying { + override fun set(element: T) = underlying.set(element) + + override fun add(element: T) = underlying.add(element) + } + + @OptIn(PotentiallyUnsafeNonEmptyOperation::class) + private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmptyCollection, List by underlying { + constructor() : this(ArrayList()) + constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) + constructor(elements: Collection) : this(ArrayList(elements)) + + override fun isEmpty(): Boolean = underlying.isEmpty() + + override fun _addAll(index: Int, elements: Collection) = underlying.addAll(index, elements) + + override fun set(index: Int, element: E) = underlying.set(index, element) + + override fun _add(index: Int, element: E) = underlying.add(index, element) + + override fun _addAll(elements: Collection) = underlying.addAll(elements) + + override fun _add(element: E) = underlying.add(element) + + override fun listIterator() = IteratorImpl(underlying.listIterator()) + override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) + override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) + override fun plus(element: E) = asNonEmptyList() + element + + override fun plus(elements: Iterable) = asNonEmptyList() + elements + } +} + +@IgnorableReturnValue +public fun MonotoneMutableList.addAll(index: Int, elements: Collection): Boolean = _addAll(index, elements) + +@IgnorableReturnValue +public fun MonotoneMutableList.addAll(index: Int, elements: NonEmptyCollection): Boolean { + contract { returns() implies (this@addAll is NonEmptyCollection) } + return _addAll(index, elements) +} + +public fun MonotoneMutableList.add(index: Int, element: E) { + contract { returns() implies (this@add is NonEmptyCollection) } + _add(index, element) +} + +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) + +public inline fun buildNonEmptyList( + builderAction: MonotoneMutableList.() -> L +): NonEmptyList where L : MonotoneMutableList, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableList()).asNonEmptyList() +} + +public inline fun buildNonEmptyList( + capacity: Int, + builderAction: MonotoneMutableList.() -> L +): NonEmptyList where L : MonotoneMutableList, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableList(capacity)).asNonEmptyList() +} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index bbe67ccffc7..d22eb956dce 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -1,4 +1,4 @@ -@file:OptIn(ExperimentalTypeInference::class, ExperimentalStdlibApi::class) +@file:OptIn(ExperimentalTypeInference::class, ExperimentalStdlibApi::class, ExperimentalContracts::class) @file:Suppress("API_NOT_AVAILABLE", "RESERVED_MEMBER_INSIDE_VALUE_CLASS") package arrow.core @@ -7,33 +7,42 @@ import arrow.core.raise.RaiseAccumulate import arrow.core.raise.either import arrow.core.raise.mapOrAccumulate import arrow.core.raise.withError +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmExposeBoxed import kotlin.jvm.JvmInline import kotlin.jvm.JvmStatic +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) @JvmInline -public value class NonEmptySet internal constructor( +public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation internal constructor( @PublishedApi internal val elements: Set ) : Set by elements, NonEmptyCollection { + public constructor(first: E, rest: Iterable) : this(buildNonEmptySet(rest.collectionSizeOrDefault(10) + 1) { + add(first) + addAll(rest) + this + }.elements) + + public override operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptySet = buildNonEmptySet(size + elements.collectionSizeOrDefault(10)) { + addAll(this@NonEmptySet) + addAll(elements) + this + } - public constructor(first: E, rest: Iterable) : this(setOf(first) + rest) - - public override operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptySet = - NonEmptySet(this.elements + elements) - - public override operator fun plus(element: @UnsafeVariance E): NonEmptySet = - NonEmptySet(this.elements + element) + public override operator fun plus(element: @UnsafeVariance E): NonEmptySet = buildNonEmptySet(size + 1) { + addAll(elements) + add(element) + this + } override fun isEmpty(): Boolean = false @JvmExposeBoxed @Suppress("USELESS_JVM_EXPOSE_BOXED") public fun toSet(): Set = elements - override val head: E get() = elements.first() - - override fun lastOrNull(): E = elements.last() - override fun toString(): String = elements.toString() override fun equals(other: Any?): Boolean = @@ -42,23 +51,7 @@ public value class NonEmptySet internal constructor( override fun hashCode(): Int = elements.hashCode() - public override fun distinct(): NonEmptyList = - NonEmptyList(elements.toList()) - - public override fun distinctBy(selector: (E) -> K): NonEmptyList = - NonEmptyList(elements.distinctBy(selector)) - - public override fun map(transform: (E) -> T): NonEmptyList = - NonEmptyList(elements.map(transform)) - - public override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = - NonEmptyList(elements.flatMap(transform)) - - public override fun mapIndexed(transform: (index: Int, E) -> T): NonEmptyList = - NonEmptyList(elements.mapIndexed(transform)) - - override fun zip(other: NonEmptyCollection): NonEmptyList> = - NonEmptyList(elements.zip(other)) + public override fun distinct(): NonEmptyList = toNonEmptyList() public companion object { @JvmStatic @JvmExposeBoxed @@ -90,9 +83,10 @@ public fun nonEmptySetOf(first: E, vararg rest: E): NonEmptySet = /** * Returns a [NonEmptySet] that contains a **copy** of the elements in [this]. */ -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun Iterable.toNonEmptySetOrNull(): NonEmptySet? = - toSet().wrapAsNonEmptySetOrNull() +public fun Iterable.toNonEmptySetOrNull(): NonEmptySet? = MonotoneMutableSet(collectionSizeOrDefault(10)).run { + addAll(this@toNonEmptySetOrNull) + if (isNonEmpty()) asNonEmptySet() else null +} /** * Returns a [NonEmptySet] that contains a **copy** of the elements in [this]. @@ -103,9 +97,7 @@ public fun Iterable.toNonEmptySetOrNone(): Option> = /** * Returns a [NonEmptySet] that contains a **copy** of the elements in [this]. */ -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun Iterable.toNonEmptySetOrThrow(): NonEmptySet = - toSet().wrapAsNonEmptySetOrThrow() +public fun Iterable.toNonEmptySetOrThrow(): NonEmptySet = toNonEmptySetOrNull() ?: throw IllegalArgumentException("Cannot create NonEmptySet from empty Iterable") @Deprecated("Same as Iterable extension", level = DeprecationLevel.HIDDEN) public fun Set.toNonEmptySetOrNull(): NonEmptySet? = @@ -122,10 +114,7 @@ public fun Set.toNonEmptySetOrNone(): Option> = * You are responsible for keeping the non-emptiness invariant at all times. */ @PotentiallyUnsafeNonEmptyOperation -public fun Set.wrapAsNonEmptySetOrThrow(): NonEmptySet { - require(isNotEmpty()) - return NonEmptySet(this) -} +public fun Set.wrapAsNonEmptySetOrThrow(): NonEmptySet = wrapAsNonEmptySetOrNull() ?: throw IllegalArgumentException("Cannot create NonEmptySet from empty Set") /** * Returns a [NonEmptySet] that wraps the given [this], avoiding an additional copy. @@ -138,3 +127,64 @@ public fun Set.wrapAsNonEmptySetOrNull(): NonEmptySet? = when { isEmpty() -> null else -> NonEmptySet(this) } + +/** + * A mutable list that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableSet: MonotoneMutableCollection, Set { + public companion object { + // linked by default to match mutableSetOf behavior + public operator fun invoke(): MonotoneMutableSet = Impl(isLinked = true) + public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity, isLinked = true) + public operator fun invoke(elements: Collection): MonotoneMutableSet = Impl(elements, isLinked = true) + + public fun hash(): MonotoneMutableSet = Impl(isLinked = false) + public fun hash(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity, isLinked = false) + public fun hash(elements: Collection): MonotoneMutableSet = Impl(elements, isLinked = false) + } + + @OptIn(PotentiallyUnsafeNonEmptyOperation::class) + private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmptyCollection, Set by underlying { + constructor(isLinked: Boolean) : this(if(isLinked) LinkedHashSet() else HashSet()) + constructor(initialCapacity: Int, isLinked: Boolean) : this(if(isLinked) LinkedHashSet(initialCapacity) else HashSet(initialCapacity)) + constructor(elements: Collection, isLinked: Boolean) : this(if(isLinked) LinkedHashSet(elements) else HashSet(elements)) + + override fun isEmpty(): Boolean = underlying.isEmpty() + + override fun _addAll(elements: Collection) = underlying.addAll(elements) + + override fun _add(element: E) = underlying.add(element) + + override fun plus(element: E) = buildNonEmptySet(size + 1) { + addAll(this@Impl) + add(element) + this + } + + override fun plus(elements: Iterable) = buildNonEmptySet(size) { + addAll(this@Impl) + addAll(elements) + this + } + } +} + +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +public fun L.asNonEmptySet(): NonEmptySet where L : Set, L : NonEmptyCollection = NonEmptySet(this) + +public inline fun buildNonEmptySet( + builderAction: MonotoneMutableSet.() -> L +): NonEmptySet where L : MonotoneMutableSet, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableSet()).asNonEmptySet() +} + +public inline fun buildNonEmptySet( + capacity: Int, + builderAction: MonotoneMutableSet.() -> L +): NonEmptySet where L : MonotoneMutableSet, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableSet(capacity)).asNonEmptySet() +} 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 6a18657988d..f8908437882 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 @@ -8,17 +8,22 @@ package arrow.core.raise import arrow.core.Either import arrow.core.EitherNel import arrow.core.Ior +import arrow.core.MonotoneMutableList +import arrow.core.MonotoneMutableSet import arrow.core.NonEmptyList import arrow.core.NonEmptySet -import arrow.core.PotentiallyUnsafeNonEmptyOperation +import arrow.core.add +import arrow.core.addAll +import arrow.core.asNonEmptyList +import arrow.core.asNonEmptySet import arrow.core.collectionSizeOrDefault import arrow.core.getOrElse +import arrow.core.isNonEmpty import arrow.core.nel import arrow.core.raise.RaiseAccumulate.Error import arrow.core.raise.RaiseAccumulate.Ok import arrow.core.raise.RaiseAccumulate.Value import arrow.core.toNonEmptyListOrNull -import arrow.core.wrapAsNonEmptySetOrThrow import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_LEAST_ONCE import kotlin.contracts.InvocationKind.AT_MOST_ONCE @@ -768,7 +773,21 @@ public inline fun Raise>.mapOrAccumulate( // For a NonEmptyList to be returned, there must be a B, which can only be produced by transform // thus transform must be called at least once (or alternatively an error is raised or an exception is thrown etc) contract { callsInPlace(transform, AT_LEAST_ONCE) } - return mapOrAccumulate(nonEmptyList.all) { transform(it) }.let(::NonEmptyList) + val list = MonotoneMutableList(nonEmptyList.size) + return accumulate { + var result: Value>? = null + val iterator = nonEmptyList.iterator() + do result = run { // Once language version is 2.2, we can use continue instead of return@run here + accumulating { + val transformed = transform(iterator.next()) + if (result is RaiseAccumulate.Error) return@run result + list.add(transformed) + if (result != null) return@run result + list.asNonEmptyList() + } + } while (iterator.hasNext()) + result.value + } } /** @@ -778,7 +797,7 @@ public inline fun Raise>.mapOrAccumulate( * [error accumulation](https://arrow-kt.io/learn/typed-errors/working-with-typed-errors/#accumulating-errors) * and how to use it in [validation](https://arrow-kt.io/learn/typed-errors/validation/). */ -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +@OptIn(ExperimentalRaiseAccumulateApi::class) @RaiseDSL @Suppress("WRONG_INVOCATION_KIND") public inline fun Raise>.mapOrAccumulate( @@ -786,11 +805,20 @@ public inline fun Raise>.mapOrAccumulate( @BuilderInference transform: RaiseAccumulate.(A) -> B ): NonEmptySet { contract { callsInPlace(transform, AT_LEAST_ONCE) } - return buildSet(nonEmptySet.size) { - forEachAccumulatingImpl(nonEmptySet.iterator()) { item, hasErrors -> - transform(item).also { if (!hasErrors) add(it) } - } - }.wrapAsNonEmptySetOrThrow() + val set = MonotoneMutableSet(nonEmptySet.size) + return accumulate { + var result: Value>? = null + val iterator = nonEmptySet.iterator() + do result = run { // Once language version is 2.2, we can use continue instead of return@run here + accumulating { + val transformed = transform(iterator.next()) + if (result is RaiseAccumulate.Error) return@run result + set.add(transformed) + set.asNonEmptySet() + } + } while (iterator.hasNext()) + result.value + } } @RaiseDSL @@ -1096,23 +1124,19 @@ private class RaiseNel(private val accumulate: Accumulate) : Raise @OptIn(ExperimentalRaiseAccumulateApi::class) private class ListAccumulate(private val raise: Raise>) : Accumulate, Raise> { - private val list: MutableList = mutableListOf() - - fun raiseSingle(r: Error): Nothing = raise.raise(NonEmptyList(list + r)) - override fun raise(r: NonEmptyList) = raise.raise(NonEmptyList(list + r.all)) + private val list = MonotoneMutableList() - // only valid if list is not empty - // errors are never removed from `list`, so once this is valid, it stays valid - private val error = Error { raise.raise(NonEmptyList(list)) } + fun raiseSingle(r: Error): Nothing = raise.raise(if (list.isNonEmpty()) list.asNonEmptyList() + r else r.nel()) + override fun raise(r: NonEmptyList) = raise.raise(if (list.isNonEmpty()) list.asNonEmptyList() + r else r) @ExperimentalRaiseAccumulateApi override fun accumulateAll(errors: NonEmptyList): Value { list.addAll(errors) - return error + return Error { raise.raise(list.asNonEmptyList()) } } @ExperimentalRaiseAccumulateApi - override val latestError: Value? get() = error.takeIf { list.isNotEmpty() } + override val latestError: Value? get() = if (list.isNonEmpty()) Error { raise.raise(list.asNonEmptyList()) } else null } @OptIn(ExperimentalRaiseAccumulateApi::class) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt index 334ca95f820..3d29fa151bf 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptyListTest.kt @@ -457,16 +457,10 @@ class NonEmptyListTest { @Test fun flatMap() = runTest { - fun transform(i: Int) = listOf(i) + 1 + fun transform(i: Int) = nonEmptyListOf(i, 1) - checkAll(Arb.list(Arb.int(), range = 0..20)) { a -> - val expected = a.flatMap(::transform) - - a.toNonEmptyListOrNull() - ?.flatMap { - transform(it).let(::NonEmptyList) - } - ?.shouldBe(expected) + checkAll(Arb.nonEmptyList(Arb.int(), range = 0..20)) { a -> + a.flatMap(::transform) shouldBe (a as List).flatMap(::transform) } } diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt index 32684808dda..a1366efbc41 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/NonEmptySetTest.kt @@ -237,8 +237,8 @@ class NonEmptySetTest { @Test fun toStringUsesUnderlyingImplementation() = runTest { checkAll(Arb.set(Arb.int(), 1..100)) { - NonEmptySet(it).toString() shouldBe it.toString() - NonEmptySet(MyVerySpecialSet(it)).toString() shouldBe "MyVerySpecialSet(${it.reversed()})" + it.wrapAsNonEmptySetOrThrow().toString() shouldBe it.toString() + MyVerySpecialSet(it).wrapAsNonEmptySetOrThrow().toString() shouldBe "MyVerySpecialSet(${it.reversed()})" } } } diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt index 3885baf1f0f..28ee3f99d8f 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt @@ -7,7 +7,7 @@ import io.kotest.property.arbitrary.bind import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.constant -import io.kotest.property.arbitrary.filter +import io.kotest.property.arbitrary.filterIsInstance import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.set @@ -29,10 +29,11 @@ import kotlin.coroutines.startCoroutine // copied from kotest-extensions-arrow +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, max(range.first, 1) .. range.last) - .filter { it.isNotEmpty() } - .map { NonEmptyList(it) } + .map { it.wrapAsNonEmptyListOrNull() } + .filterIsInstance() fun Arb.Companion.nonEmptySet(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.set(arb, max(range.first, 1) .. range.last).map { it.toNonEmptySetOrNull()!! } From f0159efffaba823afb55af9281f70f47f403da01 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Mon, 29 Dec 2025 22:59:21 +0000 Subject: [PATCH 02/16] Add missing zip overload and loosen `asNonEmptyList/Set` where clause --- .../kotlin/arrow/core/NonEmptyList.kt | 34 ++++++++++ .../arrow-core/api/android/arrow-core.api | 58 ++++++++++++++++ .../core/arrow-core/api/arrow-core.klib.api | 67 +++++++++++++++---- .../core/arrow-core/api/jvm/arrow-core.api | 58 ++++++++++++++++ .../kotlin/arrow/core/NonEmptyCollection.kt | 2 +- .../kotlin/arrow/core/NonEmptyList.kt | 8 +-- .../kotlin/arrow/core/NonEmptySet.kt | 21 ++++-- 7 files changed, 222 insertions(+), 26 deletions(-) diff --git a/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt b/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt index bd831161767..a5b916d621b 100644 --- a/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt +++ b/arrow-libs/core/arrow-core-high-arity/src/commonMain/kotlin/arrow/core/NonEmptyList.kt @@ -40,6 +40,40 @@ public inline fun NonEmptyList NonEmptyList.zip( + t1: NonEmptyList, + t2: NonEmptyList, + t3: NonEmptyList, + t4: NonEmptyList, + t5: NonEmptyList, + t6: NonEmptyList, + t7: NonEmptyList, + t8: NonEmptyList, + t9: NonEmptyList, + t10: NonEmptyList, + t11: NonEmptyList, + map: (A, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> R, +): NonEmptyList { + contract { callsInPlace(map, InvocationKind.AT_LEAST_ONCE) } + val i0 = iterator() + val i1 = t1.iterator() + val i2 = t2.iterator() + val i3 = t3.iterator() + val i4 = t4.iterator() + val i5 = t5.iterator() + val i6 = t6.iterator() + val i7 = t7.iterator() + val i8 = t8.iterator() + val i9 = t9.iterator() + val i10 = t10.iterator() + val i11 = t11.iterator() + return buildNonEmptyList(minOf(size, t1.size, t2.size, t3.size, t4.size, t5.size, t6.size, t7.size, t8.size, t9.size, t10.size, t11.size)) { + do add(map(i0.next(), i1.next(), i2.next(), i3.next(), i4.next(), i5.next(), i6.next(), i7.next(), i8.next(), i9.next(), i10.next(), i11.next())) + while (i0.hasNext() && i1.hasNext() && i2.hasNext() && i3.hasNext() && i4.hasNext() && i5.hasNext() && i6.hasNext() && i7.hasNext() && i8.hasNext() && i9.hasNext() && i10.hasNext() && i11.hasNext()) + this + } +} + public inline fun NonEmptyList.zip( t1: NonEmptyList, t2: NonEmptyList, diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index 4f419e93f28..9c5495df81d 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -349,6 +349,45 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { public static synthetic fun MemoizedDeepRecursiveFunction$default (Larrow/core/MemoizationCache;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/DeepRecursiveFunction; } +public abstract interface class arrow/core/MonotoneMutableCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { + public abstract fun _add (Ljava/lang/Object;)Z + public abstract fun _addAll (Ljava/util/Collection;)Z +} + +public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { + public static final field Companion Larrow/core/MonotoneMutableList$Companion; + public abstract fun _add (ILjava/lang/Object;)V + public abstract fun _addAll (ILjava/util/Collection;)Z + public abstract fun listIterator ()Larrow/core/MonotoneMutableList$Iterator; + public abstract fun listIterator (I)Larrow/core/MonotoneMutableList$Iterator; + public abstract fun set (ILjava/lang/Object;)Ljava/lang/Object; + public abstract fun subList (II)Larrow/core/MonotoneMutableList; +} + +public final class arrow/core/MonotoneMutableList$Companion { + public final fun invoke ()Larrow/core/MonotoneMutableList; + public final fun invoke (I)Larrow/core/MonotoneMutableList; + public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableList; +} + +public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { + public abstract fun add (Ljava/lang/Object;)V + public abstract fun set (Ljava/lang/Object;)V +} + +public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneMutableCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { + public static final field Companion Larrow/core/MonotoneMutableSet$Companion; +} + +public final class arrow/core/MonotoneMutableSet$Companion { + public final fun hash ()Larrow/core/MonotoneMutableSet; + public final fun hash (I)Larrow/core/MonotoneMutableSet; + public final fun hash (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; + public final fun invoke ()Larrow/core/MonotoneMutableSet; + public final fun invoke (I)Larrow/core/MonotoneMutableSet; + public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; +} + public abstract interface class arrow/core/NonEmptyCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { public abstract fun distinct-1X0FA-Y ()Ljava/util/List; public abstract fun distinctBy-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; @@ -371,7 +410,9 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun distinctBy-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun firstOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun flatMap-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun getHead (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun isEmpty (Larrow/core/NonEmptyCollection;)Z + public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; @@ -379,6 +420,14 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } +public final class arrow/core/NonEmptyCollectionKt { + public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z +} + public final class arrow/core/NonEmptyList : arrow/core/NonEmptyCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; public fun add (ILjava/lang/Object;)V @@ -493,6 +542,12 @@ public final class arrow/core/NonEmptyList$Companion { } public final class arrow/core/NonEmptyListKt { + public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; + public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun compareTo-8QhqC-A (Ljava/util/List;Ljava/util/List;)I public static final fun flatten-GZgkXh4 (Ljava/util/List;)Ljava/util/List; public static final fun mapOrAccumulate-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; @@ -588,6 +643,9 @@ public final class arrow/core/NonEmptySet$Companion { } public final class arrow/core/NonEmptySetKt { + public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; + public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index 454d0b1d310..5b6a5dc052a 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -44,11 +44,46 @@ abstract interface <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core/MemoizationCach abstract fun set(#A, #B): #B // arrow.core/MemoizationCache.set|set(1:0;1:1){}[0] } +abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableCollection : kotlin.collections/Collection<#A> { // arrow.core/MonotoneMutableCollection|null[0] + abstract fun _add(#A): kotlin/Boolean // arrow.core/MonotoneMutableCollection._add|_add(1:0){}[0] + abstract fun _addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneMutableCollection._addAll|_addAll(kotlin.collections.Collection<1:0>){}[0] +} + +abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core/MonotoneMutableCollection<#A>, kotlin.collections/List<#A> { // arrow.core/MonotoneMutableList|null[0] + abstract fun _add(kotlin/Int, #A) // arrow.core/MonotoneMutableList._add|_add(kotlin.Int;1:0){}[0] + abstract fun _addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneMutableList._addAll|_addAll(kotlin.Int;kotlin.collections.Collection<1:0>){}[0] + abstract fun listIterator(): arrow.core/MonotoneMutableList.Iterator<#A> // arrow.core/MonotoneMutableList.listIterator|listIterator(){}[0] + abstract fun listIterator(kotlin/Int): arrow.core/MonotoneMutableList.Iterator<#A> // arrow.core/MonotoneMutableList.listIterator|listIterator(kotlin.Int){}[0] + abstract fun set(kotlin/Int, #A): #A // arrow.core/MonotoneMutableList.set|set(kotlin.Int;1:0){}[0] + abstract fun subList(kotlin/Int, kotlin/Int): arrow.core/MonotoneMutableList<#A> // arrow.core/MonotoneMutableList.subList|subList(kotlin.Int;kotlin.Int){}[0] + + abstract interface <#A1: kotlin/Any?> Iterator : kotlin.collections/ListIterator<#A1> { // arrow.core/MonotoneMutableList.Iterator|null[0] + abstract fun add(#A1) // arrow.core/MonotoneMutableList.Iterator.add|add(1:0){}[0] + abstract fun set(#A1) // arrow.core/MonotoneMutableList.Iterator.set|set(1:0){}[0] + } + + final object Companion { // arrow.core/MonotoneMutableList.Companion|null[0] + final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(){0§}[0] + final fun <#A2: kotlin/Any?> invoke(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(kotlin.collections.Collection<0:0>){0§}[0] + final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(kotlin.Int){0§}[0] + } +} + +abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableSet : arrow.core/MonotoneMutableCollection<#A>, kotlin.collections/Set<#A> { // arrow.core/MonotoneMutableSet|null[0] + final object Companion { // arrow.core/MonotoneMutableSet.Companion|null[0] + final fun <#A2: kotlin/Any?> hash(): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(){0§}[0] + final fun <#A2: kotlin/Any?> hash(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(kotlin.collections.Collection<0:0>){0§}[0] + final fun <#A2: kotlin/Any?> hash(kotlin/Int): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(kotlin.Int){0§}[0] + final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(){0§}[0] + final fun <#A2: kotlin/Any?> invoke(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(kotlin.collections.Collection<0:0>){0§}[0] + final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(kotlin.Int){0§}[0] + } +} + abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin.collections/Collection<#A> { // arrow.core/NonEmptyCollection|null[0] - abstract val head // arrow.core/NonEmptyCollection.head|{}head[0] - abstract fun (): #A // arrow.core/NonEmptyCollection.head.|(){}[0] + open val head // arrow.core/NonEmptyCollection.head|{}head[0] + open fun (): #A // arrow.core/NonEmptyCollection.head.|(){}[0] - abstract fun lastOrNull(): #A // arrow.core/NonEmptyCollection.lastOrNull|lastOrNull(){}[0] abstract fun plus(#A): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(1:0){}[0] abstract fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(kotlin.collections.Iterable<1:0>){}[0] open fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] @@ -59,6 +94,7 @@ abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin. open fun distinct(): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.distinct|distinct(){}[0] open fun firstOrNull(): #A // arrow.core/NonEmptyCollection.firstOrNull|firstOrNull(){}[0] open fun isEmpty(): kotlin/Boolean // arrow.core/NonEmptyCollection.isEmpty|isEmpty(){}[0] + open fun lastOrNull(): #A // arrow.core/NonEmptyCollection.lastOrNull|lastOrNull(){}[0] open fun toNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.toNonEmptyList|toNonEmptyList(){}[0] open fun toNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/NonEmptyCollection.toNonEmptySet|toNonEmptySet(){}[0] } @@ -369,8 +405,6 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptyList : arrow.core/Non final val all // arrow.core/NonEmptyList.all|{}all[0] final fun (): kotlin.collections/List<#A> // arrow.core/NonEmptyList.all.|(){}[0] - final val head // arrow.core/NonEmptyList.head|{}head[0] - final fun (): #A // arrow.core/NonEmptyList.head.|(){}[0] final val size // arrow.core/NonEmptyList.size|{}size[0] final fun (): kotlin/Int // arrow.core/NonEmptyList.size.|(){}[0] final val tail // arrow.core/NonEmptyList.tail|{}tail[0] @@ -389,7 +423,6 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptyList : arrow.core/Non final fun isEmpty(): kotlin/Boolean // arrow.core/NonEmptyList.isEmpty|isEmpty(){}[0] final fun iterator(): kotlin.collections/Iterator<#A> // arrow.core/NonEmptyList.iterator|iterator(){}[0] final fun lastIndexOf(#A): kotlin/Int // arrow.core/NonEmptyList.lastIndexOf|lastIndexOf(1:0){}[0] - final fun lastOrNull(): #A // arrow.core/NonEmptyList.lastOrNull|lastOrNull(){}[0] final fun listIterator(): kotlin.collections/ListIterator<#A> // arrow.core/NonEmptyList.listIterator|listIterator(){}[0] final fun listIterator(kotlin/Int): kotlin.collections/ListIterator<#A> // arrow.core/NonEmptyList.listIterator|listIterator(kotlin.Int){}[0] final fun plus(#A): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyList.plus|plus(1:0){}[0] @@ -414,7 +447,6 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptyList : arrow.core/Non final inline fun <#A1: kotlin/Any?> foldLeft(#A1, kotlin/Function2<#A1, #A, #A1>): #A1 // arrow.core/NonEmptyList.foldLeft|foldLeft(0:0;kotlin.Function2<0:0,1:0,0:0>){0§}[0] final inline fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyList.map|map(kotlin.Function1<1:0,0:0>){0§}[0] final inline fun <#A1: kotlin/Any?> mapIndexed(kotlin/Function2): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyList.mapIndexed|mapIndexed(kotlin.Function2){0§}[0] - final inline fun distinct(): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyList.distinct|distinct(){}[0] final object Companion { // arrow.core/NonEmptyList.Companion|null[0] final val unit // arrow.core/NonEmptyList.Companion.unit|{}unit[0] @@ -433,15 +465,9 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptySet : arrow.core/NonE final val elements // arrow.core/NonEmptySet.elements|{}elements[0] final fun (): kotlin.collections/Set<#A> // arrow.core/NonEmptySet.elements.|(){}[0] - final val head // arrow.core/NonEmptySet.head|{}head[0] - final fun (): #A // arrow.core/NonEmptySet.head.|(){}[0] final val size // arrow.core/NonEmptySet.size|{}size[0] final fun (): kotlin/Int // arrow.core/NonEmptySet.size.|(){}[0] - final fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptySet.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] - final fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] - final fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.map|map(kotlin.Function1<1:0,0:0>){0§}[0] - final fun <#A1: kotlin/Any?> mapIndexed(kotlin/Function2): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.mapIndexed|mapIndexed(kotlin.Function2){0§}[0] final fun <#A1: kotlin/Any?> zip(arrow.core/NonEmptyCollection<#A1>): arrow.core/NonEmptyList> // arrow.core/NonEmptySet.zip|zip(arrow.core.NonEmptyCollection<0:0>){0§}[0] final fun contains(#A): kotlin/Boolean // arrow.core/NonEmptySet.contains|contains(1:0){}[0] final fun containsAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/NonEmptySet.containsAll|containsAll(kotlin.collections.Collection<1:0>){}[0] @@ -450,7 +476,6 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptySet : arrow.core/NonE final fun hashCode(): kotlin/Int // arrow.core/NonEmptySet.hashCode|hashCode(){}[0] final fun isEmpty(): kotlin/Boolean // arrow.core/NonEmptySet.isEmpty|isEmpty(){}[0] final fun iterator(): kotlin.collections/Iterator<#A> // arrow.core/NonEmptySet.iterator|iterator(){}[0] - final fun lastOrNull(): #A // arrow.core/NonEmptySet.lastOrNull|lastOrNull(){}[0] final fun plus(#A): arrow.core/NonEmptySet<#A> // arrow.core/NonEmptySet.plus|plus(1:0){}[0] final fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptySet<#A> // arrow.core/NonEmptySet.plus|plus(kotlin.collections.Iterable<1:0>){}[0] final fun toSet(): kotlin.collections/Set<#A> // arrow.core/NonEmptySet.toSet|toSet(){}[0] @@ -724,6 +749,8 @@ final const val arrow.core/RedundantAPI // arrow.core/RedundantAPI|{}RedundantAP final fun (arrow.core.raise/Traced).arrow.core.raise/withCause(arrow.core.raise/Traced): arrow.core.raise/Traced // arrow.core.raise/withCause|withCause@arrow.core.raise.Traced(arrow.core.raise.Traced){}[0] final fun (kotlin/String).arrow.core/escaped(): kotlin/String // arrow.core/escaped|escaped@kotlin.String(){}[0] final fun <#A: kotlin/Any> (kotlin/Function1<#A, kotlin/Boolean>).arrow.core/mapNullable(): kotlin/Function1<#A?, kotlin/Boolean> // arrow.core/mapNullable|mapNullable@kotlin.Function1<0:0,kotlin.Boolean>(){0§}[0] +final fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> (#B).arrow.core/asNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/asNonEmptyList|asNonEmptyList@0:1(){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> (#B).arrow.core/asNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/asNonEmptySet|asNonEmptySet@0:1(){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> (kotlin.sequences/Sequence<#A>).arrow.core/zip(kotlin.sequences/Sequence<#B>, kotlin.sequences/Sequence<#C>, kotlin.sequences/Sequence<#D>, kotlin.sequences/Sequence<#E>, kotlin.sequences/Sequence<#F>, kotlin.sequences/Sequence<#G>, kotlin.sequences/Sequence<#H>, kotlin.sequences/Sequence<#I>, kotlin.sequences/Sequence<#J>, kotlin/Function10<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): kotlin.sequences/Sequence<#K> // arrow.core/zip|zip@kotlin.sequences.Sequence<0:0>(kotlin.sequences.Sequence<0:1>;kotlin.sequences.Sequence<0:2>;kotlin.sequences.Sequence<0:3>;kotlin.sequences.Sequence<0:4>;kotlin.sequences.Sequence<0:5>;kotlin.sequences.Sequence<0:6>;kotlin.sequences.Sequence<0:7>;kotlin.sequences.Sequence<0:8>;kotlin.sequences.Sequence<0:9>;kotlin.Function10<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?> (kotlin.sequences/Sequence<#A>).arrow.core/zip(kotlin.sequences/Sequence<#B>, kotlin.sequences/Sequence<#C>, kotlin.sequences/Sequence<#D>, kotlin.sequences/Sequence<#E>, kotlin.sequences/Sequence<#F>, kotlin.sequences/Sequence<#G>, kotlin.sequences/Sequence<#H>, kotlin.sequences/Sequence<#I>, kotlin/Function9<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J>): kotlin.sequences/Sequence<#J> // arrow.core/zip|zip@kotlin.sequences.Sequence<0:0>(kotlin.sequences.Sequence<0:1>;kotlin.sequences.Sequence<0:2>;kotlin.sequences.Sequence<0:3>;kotlin.sequences.Sequence<0:4>;kotlin.sequences.Sequence<0:5>;kotlin.sequences.Sequence<0:6>;kotlin.sequences.Sequence<0:7>;kotlin.sequences.Sequence<0:8>;kotlin.Function9<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?> (arrow.core/Tuple8<#A, #B, #C, #D, #E, #F, #G, #H>).arrow.core/plus(#I): arrow.core/Tuple9<#A, #B, #C, #D, #E, #F, #G, #H, #I> // arrow.core/plus|plus@arrow.core.Tuple8<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7>(0:8){0§;1§;2§;3§;4§;5§;6§;7§;8§}[0] @@ -828,6 +855,14 @@ final fun <#A: kotlin/Any?> (#A).arrow.core/some(): arrow.core/Option<#A> // arr final fun <#A: kotlin/Any?> (#A?).arrow.core/toOption(): arrow.core/Option<#A> // arrow.core/toOption|toOption@0:0?(){0§}[0] final fun <#A: kotlin/Any?> (arrow.core.raise/Accumulate<#A>).arrow.core.raise/tolerant(arrow.core.raise/Raise>): arrow.core.raise/Accumulate<#A> // arrow.core.raise/tolerant|tolerant@arrow.core.raise.Accumulate<0:0>(arrow.core.raise.Raise>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/Either<#A, #A>).arrow.core/merge(): #A // arrow.core/merge|merge@arrow.core.Either<0:0,0:0>(){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/add(#A): kotlin/Boolean // arrow.core/add|add@arrow.core.MonotoneMutableCollection<0:0>(0:0){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(arrow.core.NonEmptyCollection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(kotlin.collections.Collection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(kotlin.collections/Iterable<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(kotlin.collections.Iterable<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/isNonEmpty(): kotlin/Boolean // arrow.core/isNonEmpty|isNonEmpty@arrow.core.MonotoneMutableCollection<0:0>(){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/add(kotlin/Int, #A) // arrow.core/add|add@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;0:0){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;arrow.core.NonEmptyCollection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;kotlin.collections.Collection<0:0>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/NonEmptyList>).arrow.core/flatten(): arrow.core/NonEmptyList<#A> // arrow.core/flatten|flatten@arrow.core.NonEmptyList>(){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/Option>).arrow.core/flatten(): arrow.core/Option<#A> // arrow.core/flatten|flatten@arrow.core.Option>(){0§}[0] final fun <#A: kotlin/Any?> (context(arrow.core.raise/Raise<#A>)).arrow.core.raise.context/raise(#A): kotlin/Nothing // arrow.core.raise.context/raise|raise(arrow.core.raise.Raise<0:0>)(0:0){0§}[0] @@ -905,6 +940,10 @@ final fun arrow.core/sort(kotlin/Long, kotlin/LongArray...): kotlin.collections/ final fun arrow.core/sort(kotlin/Short, kotlin/Short): kotlin/Pair // arrow.core/sort|sort(kotlin.Short;kotlin.Short){}[0] final fun arrow.core/sort(kotlin/Short, kotlin/Short, kotlin/Short): kotlin/Triple // arrow.core/sort|sort(kotlin.Short;kotlin.Short;kotlin.Short){}[0] final fun arrow.core/sort(kotlin/Short, kotlin/ShortArray...): kotlin.collections/List // arrow.core/sort|sort(kotlin.Short;kotlin.ShortArray...){}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (arrow.core.raise/Raise<#A>).arrow.core.raise/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise/ensureNotNull|ensureNotNull@arrow.core.raise.Raise<0:0>(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (context(arrow.core.raise/Raise<#A>)).arrow.core.raise.context/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise.context/ensureNotNull|ensureNotNull(arrow.core.raise.Raise<0:0>)(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?> (kotlin.collections/Map<#A, #B>).arrow.core/zip(kotlin.collections/Map<#A, #C>, kotlin.collections/Map<#A, #D>, kotlin.collections/Map<#A, #E>, kotlin.collections/Map<#A, #F>, kotlin.collections/Map<#A, #G>, kotlin.collections/Map<#A, #H>, kotlin.collections/Map<#A, #I>, kotlin.collections/Map<#A, #J>, kotlin.collections/Map<#A, #K>, kotlin/Function11<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L>): kotlin.collections/Map<#A, #L> // arrow.core/zip|zip@kotlin.collections.Map<0:0,0:1>(kotlin.collections.Map<0:0,0:2>;kotlin.collections.Map<0:0,0:3>;kotlin.collections.Map<0:0,0:4>;kotlin.collections.Map<0:0,0:5>;kotlin.collections.Map<0:0,0:6>;kotlin.collections.Map<0:0,0:7>;kotlin.collections.Map<0:0,0:8>;kotlin.collections.Map<0:0,0:9>;kotlin.collections.Map<0:0,0:10>;kotlin.Function11<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§}[0] diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index 4f419e93f28..9c5495df81d 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -349,6 +349,45 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { public static synthetic fun MemoizedDeepRecursiveFunction$default (Larrow/core/MemoizationCache;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/DeepRecursiveFunction; } +public abstract interface class arrow/core/MonotoneMutableCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { + public abstract fun _add (Ljava/lang/Object;)Z + public abstract fun _addAll (Ljava/util/Collection;)Z +} + +public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { + public static final field Companion Larrow/core/MonotoneMutableList$Companion; + public abstract fun _add (ILjava/lang/Object;)V + public abstract fun _addAll (ILjava/util/Collection;)Z + public abstract fun listIterator ()Larrow/core/MonotoneMutableList$Iterator; + public abstract fun listIterator (I)Larrow/core/MonotoneMutableList$Iterator; + public abstract fun set (ILjava/lang/Object;)Ljava/lang/Object; + public abstract fun subList (II)Larrow/core/MonotoneMutableList; +} + +public final class arrow/core/MonotoneMutableList$Companion { + public final fun invoke ()Larrow/core/MonotoneMutableList; + public final fun invoke (I)Larrow/core/MonotoneMutableList; + public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableList; +} + +public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { + public abstract fun add (Ljava/lang/Object;)V + public abstract fun set (Ljava/lang/Object;)V +} + +public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneMutableCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { + public static final field Companion Larrow/core/MonotoneMutableSet$Companion; +} + +public final class arrow/core/MonotoneMutableSet$Companion { + public final fun hash ()Larrow/core/MonotoneMutableSet; + public final fun hash (I)Larrow/core/MonotoneMutableSet; + public final fun hash (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; + public final fun invoke ()Larrow/core/MonotoneMutableSet; + public final fun invoke (I)Larrow/core/MonotoneMutableSet; + public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; +} + public abstract interface class arrow/core/NonEmptyCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { public abstract fun distinct-1X0FA-Y ()Ljava/util/List; public abstract fun distinctBy-0-xjo5U (Lkotlin/jvm/functions/Function1;)Ljava/util/List; @@ -371,7 +410,9 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun distinctBy-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun firstOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun flatMap-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun getHead (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun isEmpty (Larrow/core/NonEmptyCollection;)Z + public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; @@ -379,6 +420,14 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } +public final class arrow/core/NonEmptyCollectionKt { + public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z +} + public final class arrow/core/NonEmptyList : arrow/core/NonEmptyCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; public fun add (ILjava/lang/Object;)V @@ -493,6 +542,12 @@ public final class arrow/core/NonEmptyList$Companion { } public final class arrow/core/NonEmptyListKt { + public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; + public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun compareTo-8QhqC-A (Ljava/util/List;Ljava/util/List;)I public static final fun flatten-GZgkXh4 (Ljava/util/List;)Ljava/util/List; public static final fun mapOrAccumulate-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; @@ -588,6 +643,9 @@ public final class arrow/core/NonEmptySet$Companion { } public final class arrow/core/NonEmptySetKt { + public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; + public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt index 5479dbce298..27290b0d033 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt @@ -60,7 +60,7 @@ public interface NonEmptyCollection : Collection { do add(transform(i++, iterator.next())) while (iterator.hasNext()) this } - public fun zip(other: NonEmptyCollection): NonEmptyCollection> = buildNonEmptyList(minOf(collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) { + public fun zip(other: NonEmptyCollection): NonEmptyCollection> = buildNonEmptyList(minOf(size, other.size)) { val first = this@NonEmptyCollection.iterator() val second = other.iterator() do add(first.next() to second.next()) while (first.hasNext() && second.hasNext()) 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 98d54ee8088..17ed883d23f 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 @@ -273,7 +273,7 @@ public value class NonEmptyList @PotentiallyUnsafeNonEmptyOperation @Publ contract { callsInPlace(both, InvocationKind.AT_LEAST_ONCE) } val first = iterator() val second = other.iterator() - return buildNonEmptyList(maxOf(this.collectionSizeOrDefault(10), other.collectionSizeOrDefault(10))) { + return buildNonEmptyList(maxOf(size, other.size)) { do add(both(first.next(), second.next())) while (first.hasNext() && second.hasNext()) while (first.hasNext()) add(left(first.next())) while (second.hasNext()) add(right(second.next())) @@ -683,11 +683,11 @@ public fun MonotoneMutableList.add(index: Int, element: E) { } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) +public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) public inline fun buildNonEmptyList( builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : MonotoneMutableList, L : NonEmptyCollection { +): NonEmptyList where L : List, L : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableList()).asNonEmptyList() } @@ -695,7 +695,7 @@ public inline fun buildNonEmptyList( public inline fun buildNonEmptyList( capacity: Int, builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : MonotoneMutableList, L : NonEmptyCollection { +): NonEmptyList where L : List, L : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableList(capacity)).asNonEmptyList() } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index d22eb956dce..d2df823570a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -53,6 +53,13 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern public override fun distinct(): NonEmptyList = toNonEmptyList() + override fun zip(other: NonEmptyCollection): NonEmptyList> = buildNonEmptyList(minOf(size, other.size)) { + val first = this@NonEmptySet.iterator() + val second = other.iterator() + do add(first.next() to second.next()) while (first.hasNext() && second.hasNext()) + this + } + public companion object { @JvmStatic @JvmExposeBoxed public fun of(head: E, vararg t: E): NonEmptySet = @@ -172,19 +179,19 @@ public interface MonotoneMutableSet: MonotoneMutableCollection, Set { } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun L.asNonEmptySet(): NonEmptySet where L : Set, L : NonEmptyCollection = NonEmptySet(this) +public fun S.asNonEmptySet(): NonEmptySet where S : Set, S : NonEmptyCollection = NonEmptySet(this) -public inline fun buildNonEmptySet( - builderAction: MonotoneMutableSet.() -> L -): NonEmptySet where L : MonotoneMutableSet, L : NonEmptyCollection { +public inline fun buildNonEmptySet( + builderAction: MonotoneMutableSet.() -> S +): NonEmptySet where S : Set, S : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableSet()).asNonEmptySet() } -public inline fun buildNonEmptySet( +public inline fun buildNonEmptySet( capacity: Int, - builderAction: MonotoneMutableSet.() -> L -): NonEmptySet where L : MonotoneMutableSet, L : NonEmptyCollection { + builderAction: MonotoneMutableSet.() -> S +): NonEmptySet where S : Set, S : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableSet(capacity)).asNonEmptySet() } From 01162c6a52f20b707ebe7d45ac91c109b13900e2 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Mon, 29 Dec 2025 23:18:33 +0000 Subject: [PATCH 03/16] Remove unused functions and fix MonotoneX equality/hashCode --- .../core/arrow-core/api/android/arrow-core.api | 6 +----- .../core/arrow-core/api/arrow-core.klib.api | 7 +------ .../core/arrow-core/api/jvm/arrow-core.api | 6 +----- .../kotlin/arrow/core/NonEmptyList.kt | 7 +++---- .../commonMain/kotlin/arrow/core/NonEmptySet.kt | 17 +++++------------ 5 files changed, 11 insertions(+), 32 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index 9c5495df81d..b15ac561c5c 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -367,7 +367,6 @@ public abstract interface class arrow/core/MonotoneMutableList : arrow/core/Mono public final class arrow/core/MonotoneMutableList$Companion { public final fun invoke ()Larrow/core/MonotoneMutableList; public final fun invoke (I)Larrow/core/MonotoneMutableList; - public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableList; } public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { @@ -380,12 +379,8 @@ public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/Monot } public final class arrow/core/MonotoneMutableSet$Companion { - public final fun hash ()Larrow/core/MonotoneMutableSet; - public final fun hash (I)Larrow/core/MonotoneMutableSet; - public final fun hash (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; public final fun invoke ()Larrow/core/MonotoneMutableSet; public final fun invoke (I)Larrow/core/MonotoneMutableSet; - public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; } public abstract interface class arrow/core/NonEmptyCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { @@ -646,6 +641,7 @@ public final class arrow/core/NonEmptySetKt { public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index 5b6a5dc052a..bf6ebcb5952 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -64,18 +64,13 @@ abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core final object Companion { // arrow.core/MonotoneMutableList.Companion|null[0] final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(){0§}[0] - final fun <#A2: kotlin/Any?> invoke(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(kotlin.collections.Collection<0:0>){0§}[0] final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(kotlin.Int){0§}[0] } } abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableSet : arrow.core/MonotoneMutableCollection<#A>, kotlin.collections/Set<#A> { // arrow.core/MonotoneMutableSet|null[0] final object Companion { // arrow.core/MonotoneMutableSet.Companion|null[0] - final fun <#A2: kotlin/Any?> hash(): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(){0§}[0] - final fun <#A2: kotlin/Any?> hash(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(kotlin.collections.Collection<0:0>){0§}[0] - final fun <#A2: kotlin/Any?> hash(kotlin/Int): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.hash|hash(kotlin.Int){0§}[0] final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(){0§}[0] - final fun <#A2: kotlin/Any?> invoke(kotlin.collections/Collection<#A2>): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(kotlin.collections.Collection<0:0>){0§}[0] final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(kotlin.Int){0§}[0] } } @@ -943,7 +938,7 @@ final fun arrow.core/sort(kotlin/Short, kotlin/ShortArray...): kotlin.collection final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] -final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Int = ..., kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (arrow.core.raise/Raise<#A>).arrow.core.raise/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise/ensureNotNull|ensureNotNull@arrow.core.raise.Raise<0:0>(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (context(arrow.core.raise/Raise<#A>)).arrow.core.raise.context/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise.context/ensureNotNull|ensureNotNull(arrow.core.raise.Raise<0:0>)(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?> (kotlin.collections/Map<#A, #B>).arrow.core/zip(kotlin.collections/Map<#A, #C>, kotlin.collections/Map<#A, #D>, kotlin.collections/Map<#A, #E>, kotlin.collections/Map<#A, #F>, kotlin.collections/Map<#A, #G>, kotlin.collections/Map<#A, #H>, kotlin.collections/Map<#A, #I>, kotlin.collections/Map<#A, #J>, kotlin.collections/Map<#A, #K>, kotlin/Function11<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L>): kotlin.collections/Map<#A, #L> // arrow.core/zip|zip@kotlin.collections.Map<0:0,0:1>(kotlin.collections.Map<0:0,0:2>;kotlin.collections.Map<0:0,0:3>;kotlin.collections.Map<0:0,0:4>;kotlin.collections.Map<0:0,0:5>;kotlin.collections.Map<0:0,0:6>;kotlin.collections.Map<0:0,0:7>;kotlin.collections.Map<0:0,0:8>;kotlin.collections.Map<0:0,0:9>;kotlin.collections.Map<0:0,0:10>;kotlin.Function11<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§}[0] diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index 9c5495df81d..b15ac561c5c 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -367,7 +367,6 @@ public abstract interface class arrow/core/MonotoneMutableList : arrow/core/Mono public final class arrow/core/MonotoneMutableList$Companion { public final fun invoke ()Larrow/core/MonotoneMutableList; public final fun invoke (I)Larrow/core/MonotoneMutableList; - public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableList; } public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { @@ -380,12 +379,8 @@ public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/Monot } public final class arrow/core/MonotoneMutableSet$Companion { - public final fun hash ()Larrow/core/MonotoneMutableSet; - public final fun hash (I)Larrow/core/MonotoneMutableSet; - public final fun hash (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; public final fun invoke ()Larrow/core/MonotoneMutableSet; public final fun invoke (I)Larrow/core/MonotoneMutableSet; - public final fun invoke (Ljava/util/Collection;)Larrow/core/MonotoneMutableSet; } public abstract interface class arrow/core/NonEmptyCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { @@ -646,6 +641,7 @@ public final class arrow/core/NonEmptySetKt { public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; 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 17ed883d23f..fc77a7ce4e1 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 @@ -625,8 +625,6 @@ public interface MonotoneMutableList: MonotoneMutableCollection, List { public operator fun invoke(): MonotoneMutableList = Impl() public operator fun invoke(initialCapacity: Int): MonotoneMutableList = Impl(initialCapacity) - - public operator fun invoke(elements: Collection): MonotoneMutableList = Impl(elements) } public interface Iterator : ListIterator { @@ -645,7 +643,6 @@ public interface MonotoneMutableList: MonotoneMutableCollection, List { private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmptyCollection, List by underlying { constructor() : this(ArrayList()) constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) - constructor(elements: Collection) : this(ArrayList(elements)) override fun isEmpty(): Boolean = underlying.isEmpty() @@ -663,8 +660,10 @@ public interface MonotoneMutableList: MonotoneMutableCollection, List { override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) override fun plus(element: E) = asNonEmptyList() + element - override fun plus(elements: Iterable) = asNonEmptyList() + elements + override fun equals(other: Any?) = underlying == other + override fun hashCode() = underlying.hashCode() + override fun toString() = underlying.toString() } } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index d2df823570a..1eb60bf7b3d 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -142,21 +142,14 @@ public fun Set.wrapAsNonEmptySetOrNull(): NonEmptySet? = when { @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) public interface MonotoneMutableSet: MonotoneMutableCollection, Set { public companion object { - // linked by default to match mutableSetOf behavior - public operator fun invoke(): MonotoneMutableSet = Impl(isLinked = true) - public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity, isLinked = true) - public operator fun invoke(elements: Collection): MonotoneMutableSet = Impl(elements, isLinked = true) - - public fun hash(): MonotoneMutableSet = Impl(isLinked = false) - public fun hash(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity, isLinked = false) - public fun hash(elements: Collection): MonotoneMutableSet = Impl(elements, isLinked = false) + public operator fun invoke(): MonotoneMutableSet = Impl() + public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity) } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmptyCollection, Set by underlying { - constructor(isLinked: Boolean) : this(if(isLinked) LinkedHashSet() else HashSet()) - constructor(initialCapacity: Int, isLinked: Boolean) : this(if(isLinked) LinkedHashSet(initialCapacity) else HashSet(initialCapacity)) - constructor(elements: Collection, isLinked: Boolean) : this(if(isLinked) LinkedHashSet(elements) else HashSet(elements)) + constructor() : this(LinkedHashSet()) + constructor(initialCapacity: Int) : this(LinkedHashSet(initialCapacity)) override fun isEmpty(): Boolean = underlying.isEmpty() @@ -189,7 +182,7 @@ public inline fun buildNonEmptySet( } public inline fun buildNonEmptySet( - capacity: Int, + capacity: Int = 0, builderAction: MonotoneMutableSet.() -> S ): NonEmptySet where S : Set, S : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } From 966fddb1ab188928e78209b089b04eae7f47cd2b Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Mon, 29 Dec 2025 23:21:21 +0000 Subject: [PATCH 04/16] Fix MonotoneMutableSet.Impl equals/hashCode --- .../src/commonMain/kotlin/arrow/core/NonEmptySet.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 1eb60bf7b3d..57b9acc6c3e 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -168,6 +168,10 @@ public interface MonotoneMutableSet: MonotoneMutableCollection, Set { addAll(elements) this } + + override fun equals(other: Any?) = underlying == other + override fun hashCode() = underlying.hashCode() + override fun toString() = underlying.toString() } } From 9294c0ebead1026f500c6ed378b13e95b8781dc9 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Tue, 30 Dec 2025 01:32:52 +0000 Subject: [PATCH 05/16] Fi inlined bytecode issue --- .../src/commonTest/kotlin/arrow/core/test/Generators.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt index 28ee3f99d8f..07e7a8cc713 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/test/Generators.kt @@ -7,7 +7,6 @@ import io.kotest.property.arbitrary.bind import io.kotest.property.arbitrary.boolean import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.constant -import io.kotest.property.arbitrary.filterIsInstance import io.kotest.property.arbitrary.int import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.set @@ -32,11 +31,11 @@ import kotlin.coroutines.startCoroutine @OptIn(PotentiallyUnsafeNonEmptyOperation::class) fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, max(range.first, 1) .. range.last) - .map { it.wrapAsNonEmptyListOrNull() } - .filterIsInstance() + .map { it.wrapAsNonEmptyListOrThrow() } +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) fun Arb.Companion.nonEmptySet(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.set(arb, max(range.first, 1) .. range.last).map { it.toNonEmptySetOrNull()!! } + Arb.set(arb, max(range.first, 1) .. range.last).map { it.wrapAsNonEmptySetOrThrow() } fun Arb.Companion.sequence(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, range).map { it.asSequence() } From 4c808a8d7b65364162210b5d4771f233c3b3f273 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Tue, 30 Dec 2025 02:25:55 +0000 Subject: [PATCH 06/16] Override lambda-taking methods in NonEmptySet --- .../core/arrow-core/api/arrow-core.klib.api | 4 +++ .../kotlin/arrow/core/NonEmptySet.kt | 28 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index bf6ebcb5952..be9ba893485 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -463,6 +463,10 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptySet : arrow.core/NonE final val size // arrow.core/NonEmptySet.size|{}size[0] final fun (): kotlin/Int // arrow.core/NonEmptySet.size.|(){}[0] + final fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptySet.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] + final fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] + final fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.map|map(kotlin.Function1<1:0,0:0>){0§}[0] + final fun <#A1: kotlin/Any?> mapIndexed(kotlin/Function2): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.mapIndexed|mapIndexed(kotlin.Function2){0§}[0] final fun <#A1: kotlin/Any?> zip(arrow.core/NonEmptyCollection<#A1>): arrow.core/NonEmptyList> // arrow.core/NonEmptySet.zip|zip(arrow.core.NonEmptyCollection<0:0>){0§}[0] final fun contains(#A): kotlin/Boolean // arrow.core/NonEmptySet.contains|contains(1:0){}[0] final fun containsAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/NonEmptySet.containsAll|containsAll(kotlin.collections.Collection<1:0>){}[0] diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 57b9acc6c3e..ee3201b87d8 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -53,6 +53,34 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern public override fun distinct(): NonEmptyList = toNonEmptyList() + // Copied from NonEmptyCollection due to compilation bug with value classes and interface default methods + override fun distinctBy(selector: (E) -> K): NonEmptyList = buildNonEmptyList(size) { + add(head) // head is always distinct + val seen = hashSetOf() + var isFirst = true + for (e in elements) { + if (seen.add(selector(e)) && !isFirst) add(e) + isFirst = false + } + this + } + override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { + val iterator = elements.iterator() + do addAll(transform(iterator.next())) while (iterator.hasNext()) + this + } + override fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { + val iterator = elements.iterator() + do add(transform(iterator.next())) while (iterator.hasNext()) + this + } + override fun mapIndexed(transform: (index:Int, E) -> T): NonEmptyList = buildNonEmptyList(size) { + var i = 0 + val iterator = elements.iterator() + do add(transform(i++, iterator.next())) while (iterator.hasNext()) + this + } + override fun zip(other: NonEmptyCollection): NonEmptyList> = buildNonEmptyList(minOf(size, other.size)) { val first = this@NonEmptySet.iterator() val second = other.iterator() From 882dfb01dab27495726d1ea9ea2c0d1721c45f2c Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Tue, 30 Dec 2025 21:01:01 +0000 Subject: [PATCH 07/16] Extract into separate file --- .../arrow/core/MonotoneMutableCollection.kt | 210 ++++++++++++++++++ .../kotlin/arrow/core/NonEmptyCollection.kt | 51 ----- .../kotlin/arrow/core/NonEmptyList.kt | 98 -------- .../kotlin/arrow/core/NonEmptySet.kt | 63 +----- 4 files changed, 211 insertions(+), 211 deletions(-) create mode 100644 arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt new file mode 100644 index 00000000000..10ec4e62059 --- /dev/null +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt @@ -0,0 +1,210 @@ +@file:Suppress("API_NOT_AVAILABLE") +@file:OptIn(ExperimentalContracts::class) +package arrow.core + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + + +/** + * A mutable collection that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableCollection: Collection { + // underscored so that addAll(Nec) extension overload takes precedence + @IgnorableReturnValue + public fun _addAll(elements: Collection): Boolean + + @IgnorableReturnValue + public fun _add(element: E): Boolean +} + +@IgnorableReturnValue +public fun MonotoneMutableCollection.add(element: E): Boolean { + contract { returns() implies (this@add is NonEmptyCollection) } + return _add(element) +} + +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: Iterable): Boolean = when (elements) { + is Collection -> addAll(elements) + else -> { + var result = false + for (item in elements) if (add(item)) result = true + result + } +} + +@OptIn(ExperimentalContracts::class) +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: NonEmptyCollection): Boolean { + contract { returns() implies (this@addAll is NonEmptyCollection) } + return _addAll(elements) +} + +@OptIn(ExperimentalContracts::class) +@IgnorableReturnValue +public fun MonotoneMutableCollection.addAll(elements: Collection): Boolean = _addAll(elements) + +public fun MonotoneMutableCollection.isNonEmpty(): Boolean { + contract { returns(true) implies (this@isNonEmpty is NonEmptyCollection) } + return isNotEmpty() +} + +/** + * A mutable list that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableList: MonotoneMutableCollection, List { + @IgnorableReturnValue + public fun _addAll(index: Int, elements: Collection): Boolean + + @IgnorableReturnValue + public operator fun set(index: Int, element: E): E + + public fun _add(index: Int, element: E) + + override fun listIterator(): Iterator + + override fun listIterator(index: Int): Iterator + + override fun subList(fromIndex: Int, toIndex: Int): MonotoneMutableList + + public companion object { + public operator fun invoke(): MonotoneMutableList = Impl() + + public operator fun invoke(initialCapacity: Int): MonotoneMutableList = Impl(initialCapacity) + } + + public interface Iterator : ListIterator { + public fun set(element: T) + + public fun add(element: T) + } + + private class IteratorImpl(private val underlying: MutableListIterator) : Iterator, ListIterator by underlying { + override fun set(element: T) = underlying.set(element) + + override fun add(element: T) = underlying.add(element) + } + + @OptIn(PotentiallyUnsafeNonEmptyOperation::class) + private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmptyCollection, List by underlying { + constructor() : this(ArrayList()) + constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) + + override fun isEmpty(): Boolean = underlying.isEmpty() + + override fun _addAll(index: Int, elements: Collection) = underlying.addAll(index, elements) + + override fun set(index: Int, element: E) = underlying.set(index, element) + + override fun _add(index: Int, element: E) = underlying.add(index, element) + + override fun _addAll(elements: Collection) = underlying.addAll(elements) + + override fun _add(element: E) = underlying.add(element) + + override fun listIterator() = IteratorImpl(underlying.listIterator()) + override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) + override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) + override fun plus(element: E) = asNonEmptyList() + element + override fun plus(elements: Iterable) = asNonEmptyList() + elements + override fun equals(other: Any?) = underlying == other + override fun hashCode() = underlying.hashCode() + override fun toString() = underlying.toString() + } +} + +@IgnorableReturnValue +public fun MonotoneMutableList.addAll(index: Int, elements: Collection): Boolean = _addAll(index, elements) + +@IgnorableReturnValue +public fun MonotoneMutableList.addAll(index: Int, elements: NonEmptyCollection): Boolean { + contract { returns() implies (this@addAll is NonEmptyCollection) } + return _addAll(index, elements) +} + +public fun MonotoneMutableList.add(index: Int, element: E) { + contract { returns() implies (this@add is NonEmptyCollection) } + _add(index, element) +} + +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) + +public inline fun buildNonEmptyList( + builderAction: MonotoneMutableList.() -> L +): NonEmptyList where L : List, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableList()).asNonEmptyList() +} + +public inline fun buildNonEmptyList( + capacity: Int, + builderAction: MonotoneMutableList.() -> L +): NonEmptyList where L : List, L : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableList(capacity)).asNonEmptyList() +} + +/** + * A mutable list that can only grow by adding elements. + * Removing elements is not supported to preserve monotonicity. + */ +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +public interface MonotoneMutableSet: MonotoneMutableCollection, Set { + public companion object { + public operator fun invoke(): MonotoneMutableSet = Impl() + public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity) + } + + @OptIn(PotentiallyUnsafeNonEmptyOperation::class) + private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmptyCollection, Set by underlying { + constructor() : this(LinkedHashSet()) + constructor(initialCapacity: Int) : this(LinkedHashSet(initialCapacity)) + + override fun isEmpty(): Boolean = underlying.isEmpty() + + override fun _addAll(elements: Collection) = underlying.addAll(elements) + + override fun _add(element: E) = underlying.add(element) + + override fun plus(element: E) = buildNonEmptySet(size + 1) { + addAll(this@Impl) + add(element) + this + } + + override fun plus(elements: Iterable) = buildNonEmptySet(size) { + addAll(this@Impl) + addAll(elements) + this + } + + override fun equals(other: Any?) = underlying == other + override fun hashCode() = underlying.hashCode() + override fun toString() = underlying.toString() + } +} + +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +public fun S.asNonEmptySet(): NonEmptySet where S : Set, S : NonEmptyCollection = NonEmptySet(this) + +public inline fun buildNonEmptySet( + builderAction: MonotoneMutableSet.() -> S +): NonEmptySet where S : Set, S : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableSet()).asNonEmptySet() +} + +public inline fun buildNonEmptySet( + capacity: Int = 0, + builderAction: MonotoneMutableSet.() -> S +): NonEmptySet where S : Set, S : NonEmptyCollection { + contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } + return builderAction(MonotoneMutableSet(capacity)).asNonEmptySet() +} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt index 27290b0d033..f6f19ef5296 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt @@ -1,10 +1,5 @@ -@file:Suppress("API_NOT_AVAILABLE") -@file:OptIn(ExperimentalContracts::class) package arrow.core -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract - /** * Common interface for collections that always have * at least one element (available from [head]). @@ -76,49 +71,3 @@ public interface NonEmptyCollection : Collection { @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR) public annotation class PotentiallyUnsafeNonEmptyOperation - -/** - * A mutable collection that can only grow by adding elements. - * Removing elements is not supported to preserve monotonicity. - */ -@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableCollection: Collection { - // underscored so that addAll(Nec) extension overload takes precedence - @IgnorableReturnValue - public fun _addAll(elements: Collection): Boolean - - @IgnorableReturnValue - public fun _add(element: E): Boolean -} - -@IgnorableReturnValue -public fun MonotoneMutableCollection.add(element: E): Boolean { - contract { returns() implies (this@add is NonEmptyCollection) } - return _add(element) -} - -@IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: Iterable): Boolean = when (elements) { - is Collection -> addAll(elements) - else -> { - var result = false - for (item in elements) if (add(item)) result = true - result - } -} - -@OptIn(ExperimentalContracts::class) -@IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: NonEmptyCollection): Boolean { - contract { returns() implies (this@addAll is NonEmptyCollection) } - return _addAll(elements) -} - -@OptIn(ExperimentalContracts::class) -@IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: Collection): Boolean = _addAll(elements) - -public fun MonotoneMutableCollection.isNonEmpty(): Boolean { - contract { returns(true) implies (this@isNonEmpty is NonEmptyCollection) } - return isNotEmpty() -} 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 fc77a7ce4e1..efff5e72c0a 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 @@ -600,101 +600,3 @@ public fun List.wrapAsNonEmptyListOrNull(): NonEmptyList? = when { isEmpty() -> null else -> NonEmptyList(this) } - -/** - * A mutable list that can only grow by adding elements. - * Removing elements is not supported to preserve monotonicity. - */ -@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableList: MonotoneMutableCollection, List { - @IgnorableReturnValue - public fun _addAll(index: Int, elements: Collection): Boolean - - @IgnorableReturnValue - public operator fun set(index: Int, element: E): E - - public fun _add(index: Int, element: E) - - override fun listIterator(): Iterator - - override fun listIterator(index: Int): Iterator - - override fun subList(fromIndex: Int, toIndex: Int): MonotoneMutableList - - public companion object { - public operator fun invoke(): MonotoneMutableList = Impl() - - public operator fun invoke(initialCapacity: Int): MonotoneMutableList = Impl(initialCapacity) - } - - public interface Iterator : ListIterator { - public fun set(element: T) - - public fun add(element: T) - } - - private class IteratorImpl(private val underlying: MutableListIterator) : Iterator, ListIterator by underlying { - override fun set(element: T) = underlying.set(element) - - override fun add(element: T) = underlying.add(element) - } - - @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmptyCollection, List by underlying { - constructor() : this(ArrayList()) - constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) - - override fun isEmpty(): Boolean = underlying.isEmpty() - - override fun _addAll(index: Int, elements: Collection) = underlying.addAll(index, elements) - - override fun set(index: Int, element: E) = underlying.set(index, element) - - override fun _add(index: Int, element: E) = underlying.add(index, element) - - override fun _addAll(elements: Collection) = underlying.addAll(elements) - - override fun _add(element: E) = underlying.add(element) - - override fun listIterator() = IteratorImpl(underlying.listIterator()) - override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) - override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) - override fun plus(element: E) = asNonEmptyList() + element - override fun plus(elements: Iterable) = asNonEmptyList() + elements - override fun equals(other: Any?) = underlying == other - override fun hashCode() = underlying.hashCode() - override fun toString() = underlying.toString() - } -} - -@IgnorableReturnValue -public fun MonotoneMutableList.addAll(index: Int, elements: Collection): Boolean = _addAll(index, elements) - -@IgnorableReturnValue -public fun MonotoneMutableList.addAll(index: Int, elements: NonEmptyCollection): Boolean { - contract { returns() implies (this@addAll is NonEmptyCollection) } - return _addAll(index, elements) -} - -public fun MonotoneMutableList.add(index: Int, element: E) { - contract { returns() implies (this@add is NonEmptyCollection) } - _add(index, element) -} - -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) - -public inline fun buildNonEmptyList( - builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : List, L : NonEmptyCollection { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return builderAction(MonotoneMutableList()).asNonEmptyList() -} - -public inline fun buildNonEmptyList( - capacity: Int, - builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : List, L : NonEmptyCollection { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return builderAction(MonotoneMutableList(capacity)).asNonEmptyList() -} diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index ee3201b87d8..901effdc683 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -1,4 +1,4 @@ -@file:OptIn(ExperimentalTypeInference::class, ExperimentalStdlibApi::class, ExperimentalContracts::class) +@file:OptIn(ExperimentalTypeInference::class, ExperimentalStdlibApi::class) @file:Suppress("API_NOT_AVAILABLE", "RESERVED_MEMBER_INSIDE_VALUE_CLASS") package arrow.core @@ -7,9 +7,6 @@ import arrow.core.raise.RaiseAccumulate import arrow.core.raise.either import arrow.core.raise.mapOrAccumulate import arrow.core.raise.withError -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmExposeBoxed import kotlin.jvm.JvmInline @@ -162,61 +159,3 @@ public fun Set.wrapAsNonEmptySetOrNull(): NonEmptySet? = when { isEmpty() -> null else -> NonEmptySet(this) } - -/** - * A mutable list that can only grow by adding elements. - * Removing elements is not supported to preserve monotonicity. - */ -@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableSet: MonotoneMutableCollection, Set { - public companion object { - public operator fun invoke(): MonotoneMutableSet = Impl() - public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity) - } - - @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmptyCollection, Set by underlying { - constructor() : this(LinkedHashSet()) - constructor(initialCapacity: Int) : this(LinkedHashSet(initialCapacity)) - - override fun isEmpty(): Boolean = underlying.isEmpty() - - override fun _addAll(elements: Collection) = underlying.addAll(elements) - - override fun _add(element: E) = underlying.add(element) - - override fun plus(element: E) = buildNonEmptySet(size + 1) { - addAll(this@Impl) - add(element) - this - } - - override fun plus(elements: Iterable) = buildNonEmptySet(size) { - addAll(this@Impl) - addAll(elements) - this - } - - override fun equals(other: Any?) = underlying == other - override fun hashCode() = underlying.hashCode() - override fun toString() = underlying.toString() - } -} - -@OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun S.asNonEmptySet(): NonEmptySet where S : Set, S : NonEmptyCollection = NonEmptySet(this) - -public inline fun buildNonEmptySet( - builderAction: MonotoneMutableSet.() -> S -): NonEmptySet where S : Set, S : NonEmptyCollection { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return builderAction(MonotoneMutableSet()).asNonEmptySet() -} - -public inline fun buildNonEmptySet( - capacity: Int = 0, - builderAction: MonotoneMutableSet.() -> S -): NonEmptySet where S : Set, S : NonEmptyCollection { - contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } - return builderAction(MonotoneMutableSet(capacity)).asNonEmptySet() -} From 0d7ad8cd81330e8f9026a8cceb00d07966a62bb7 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Tue, 30 Dec 2025 21:04:50 +0000 Subject: [PATCH 08/16] Mild formatting changes --- .../src/commonMain/kotlin/arrow/core/NonEmptyList.kt | 1 + .../src/commonMain/kotlin/arrow/core/NonEmptySet.kt | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) 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 efff5e72c0a..cbca02b725f 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 @@ -165,6 +165,7 @@ public typealias Nel = NonEmptyList public value class NonEmptyList @PotentiallyUnsafeNonEmptyOperation @PublishedApi internal constructor( public val all: List ) : List by all, NonEmptyCollection { + public constructor(head: E, tail: List): this(buildNonEmptyList(tail.size + 1) { add(head) addAll(tail) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 901effdc683..8dfc5f2319e 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -50,7 +50,6 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern public override fun distinct(): NonEmptyList = toNonEmptyList() - // Copied from NonEmptyCollection due to compilation bug with value classes and interface default methods override fun distinctBy(selector: (E) -> K): NonEmptyList = buildNonEmptyList(size) { add(head) // head is always distinct val seen = hashSetOf() @@ -61,16 +60,19 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern } this } - override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { + + override fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { val iterator = elements.iterator() - do addAll(transform(iterator.next())) while (iterator.hasNext()) + do add(transform(iterator.next())) while (iterator.hasNext()) this } - override fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { + + override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { val iterator = elements.iterator() - do add(transform(iterator.next())) while (iterator.hasNext()) + do addAll(transform(iterator.next())) while (iterator.hasNext()) this } + override fun mapIndexed(transform: (index:Int, E) -> T): NonEmptyList = buildNonEmptyList(size) { var i = 0 val iterator = elements.iterator() From b484c79b54706a484765f24b6f5dba5035489fda Mon Sep 17 00:00:00 2001 From: kyay10 <12699034+kyay10@users.noreply.github.com> Date: Tue, 30 Dec 2025 21:35:40 +0000 Subject: [PATCH 09/16] Auto-update API files --- .../arrow-core/api/android/arrow-core.api | 36 +++++++++---------- .../core/arrow-core/api/jvm/arrow-core.api | 36 +++++++++---------- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index b15ac561c5c..ca34a289add 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -354,6 +354,24 @@ public abstract interface class arrow/core/MonotoneMutableCollection : java/util public abstract fun _addAll (Ljava/util/Collection;)Z } +public final class arrow/core/MonotoneMutableCollectionKt { + public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z + public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; + public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; + public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; + public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z +} + public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; public abstract fun _add (ILjava/lang/Object;)V @@ -415,14 +433,6 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } -public final class arrow/core/NonEmptyCollectionKt { - public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z - public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z -} - public final class arrow/core/NonEmptyList : arrow/core/NonEmptyCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; public fun add (ILjava/lang/Object;)V @@ -537,12 +547,6 @@ public final class arrow/core/NonEmptyList$Companion { } public final class arrow/core/NonEmptyListKt { - public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z - public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; - public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; - public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun compareTo-8QhqC-A (Ljava/util/List;Ljava/util/List;)I public static final fun flatten-GZgkXh4 (Ljava/util/List;)Ljava/util/List; public static final fun mapOrAccumulate-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; @@ -638,10 +642,6 @@ public final class arrow/core/NonEmptySet$Companion { } public final class arrow/core/NonEmptySetKt { - public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; - public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index b15ac561c5c..ca34a289add 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -354,6 +354,24 @@ public abstract interface class arrow/core/MonotoneMutableCollection : java/util public abstract fun _addAll (Ljava/util/Collection;)Z } +public final class arrow/core/MonotoneMutableCollectionKt { + public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z + public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; + public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; + public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; + public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; + public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z +} + public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; public abstract fun _add (ILjava/lang/Object;)V @@ -415,14 +433,6 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; } -public final class arrow/core/NonEmptyCollectionKt { - public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z - public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z -} - public final class arrow/core/NonEmptyList : arrow/core/NonEmptyCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; public fun add (ILjava/lang/Object;)V @@ -537,12 +547,6 @@ public final class arrow/core/NonEmptyList$Companion { } public final class arrow/core/NonEmptyListKt { - public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z - public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; - public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; - public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun compareTo-8QhqC-A (Ljava/util/List;Ljava/util/List;)I public static final fun flatten-GZgkXh4 (Ljava/util/List;)Ljava/util/List; public static final fun mapOrAccumulate-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; @@ -638,10 +642,6 @@ public final class arrow/core/NonEmptySet$Companion { } public final class arrow/core/NonEmptySetKt { - public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; - public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; public static final fun mapOrAccumulate-EyVDDLY (Ljava/util/Set;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun mapOrAccumulate-jkbboic (Ljava/util/Set;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;)Larrow/core/Either; public static final fun nonEmptySetOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/Set; From be1045dbf596ed22f9a271adace95cc484bfe5dd Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Wed, 31 Dec 2025 00:05:07 +0000 Subject: [PATCH 10/16] Provide defaults for `plus` --- .../arrow/core/MonotoneMutableCollection.kt | 26 +++---------------- .../kotlin/arrow/core/NonEmptyCollection.kt | 13 ++++++++-- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt index 10ec4e62059..5be177d7359 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt @@ -98,21 +98,16 @@ public interface MonotoneMutableList: MonotoneMutableCollection, List { override fun isEmpty(): Boolean = underlying.isEmpty() + override fun _addAll(elements: Collection) = underlying.addAll(elements) + override fun _add(element: E) = underlying.add(element) override fun _addAll(index: Int, elements: Collection) = underlying.addAll(index, elements) - override fun set(index: Int, element: E) = underlying.set(index, element) - override fun _add(index: Int, element: E) = underlying.add(index, element) - override fun _addAll(elements: Collection) = underlying.addAll(elements) - - override fun _add(element: E) = underlying.add(element) - override fun listIterator() = IteratorImpl(underlying.listIterator()) override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) - override fun plus(element: E) = asNonEmptyList() + element - override fun plus(elements: Iterable) = asNonEmptyList() + elements + override fun equals(other: Any?) = underlying == other override fun hashCode() = underlying.hashCode() override fun toString() = underlying.toString() @@ -170,21 +165,8 @@ public interface MonotoneMutableSet: MonotoneMutableCollection, Set { override fun isEmpty(): Boolean = underlying.isEmpty() override fun _addAll(elements: Collection) = underlying.addAll(elements) - override fun _add(element: E) = underlying.add(element) - override fun plus(element: E) = buildNonEmptySet(size + 1) { - addAll(this@Impl) - add(element) - this - } - - override fun plus(elements: Iterable) = buildNonEmptySet(size) { - addAll(this@Impl) - addAll(elements) - this - } - override fun equals(other: Any?) = underlying == other override fun hashCode() = underlying.hashCode() override fun toString() = underlying.toString() @@ -202,7 +184,7 @@ public inline fun buildNonEmptySet( } public inline fun buildNonEmptySet( - capacity: Int = 0, + capacity: Int, builderAction: MonotoneMutableSet.() -> S ): NonEmptySet where S : Set, S : NonEmptyCollection { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt index f6f19ef5296..0ddf8617b6c 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt @@ -9,8 +9,17 @@ public interface NonEmptyCollection : Collection { override fun isEmpty(): Boolean = false public val head: E get() = first() - public operator fun plus(element: @UnsafeVariance E): NonEmptyCollection - public operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyCollection + public operator fun plus(element: @UnsafeVariance E): NonEmptyCollection = buildNonEmptyList(size + 1) { + addAll(this@NonEmptyCollection) + add(element) + this + } + + public operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyCollection = buildNonEmptyList(size + elements.collectionSizeOrDefault(10)) { + addAll(this@NonEmptyCollection) + addAll(elements) + this + } public fun toNonEmptySet(): NonEmptySet = buildNonEmptySet(size) { addAll(this@NonEmptyCollection) From c76c580e931307165a7b6ed40f698ec2ce6a19d7 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Wed, 31 Dec 2025 00:16:08 +0000 Subject: [PATCH 11/16] Remove redundant opt-ins --- .../commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt index 5be177d7359..72d1f6b264c 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt @@ -37,14 +37,12 @@ public fun MonotoneMutableCollection.addAll(elements: Iterable): Boole } } -@OptIn(ExperimentalContracts::class) @IgnorableReturnValue public fun MonotoneMutableCollection.addAll(elements: NonEmptyCollection): Boolean { contract { returns() implies (this@addAll is NonEmptyCollection) } return _addAll(elements) } -@OptIn(ExperimentalContracts::class) @IgnorableReturnValue public fun MonotoneMutableCollection.addAll(elements: Collection): Boolean = _addAll(elements) From e6084355080747822dd13af833fea013387c9123 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Wed, 31 Dec 2025 00:42:22 +0000 Subject: [PATCH 12/16] Remove usage of 2.3 contracts, and change to effect-y API --- .../arrow-core/api/android/arrow-core.api | 24 ++++---- .../core/arrow-core/api/arrow-core.klib.api | 42 +++++++------- .../core/arrow-core/api/jvm/arrow-core.api | 24 ++++---- arrow-libs/core/arrow-core/build.gradle.kts | 1 - ...ection.kt => MonotoneCollectionBuilder.kt} | 55 +++++++++++-------- 5 files changed, 82 insertions(+), 64 deletions(-) rename arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/{MonotoneMutableCollection.kt => MonotoneCollectionBuilder.kt} (77%) diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index ca34a289add..2b52073d586 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -349,17 +349,20 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { public static synthetic fun MemoizedDeepRecursiveFunction$default (Larrow/core/MemoizationCache;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/DeepRecursiveFunction; } -public abstract interface class arrow/core/MonotoneMutableCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneCollectionBuilder { public abstract fun _add (Ljava/lang/Object;)Z public abstract fun _addAll (Ljava/util/Collection;)Z } -public final class arrow/core/MonotoneMutableCollectionKt { - public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z +public abstract interface class arrow/core/MonotoneCollectionBuilder$NonEmpty { +} + +public final class arrow/core/MonotoneCollectionBuilderKt { + public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)Z public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)Z public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; @@ -368,11 +371,10 @@ public final class arrow/core/MonotoneMutableCollectionKt { public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; - public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z + public static final fun isNonEmpty (Ljava/util/Collection;)Z } -public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneCollectionBuilder, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; public abstract fun _add (ILjava/lang/Object;)V public abstract fun _addAll (ILjava/util/Collection;)Z @@ -392,7 +394,7 @@ public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/u public abstract fun set (Ljava/lang/Object;)V } -public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneMutableCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneCollectionBuilder, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableSet$Companion; } @@ -428,6 +430,8 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; + public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Object;)Larrow/core/NonEmptyCollection; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; public static fun toNonEmptySet-5sCjGKo (Larrow/core/NonEmptyCollection;)Ljava/util/Set; public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index be9ba893485..1763aa461c6 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -39,17 +39,19 @@ abstract interface <#A: in kotlin/Any?> arrow.core.raise/Raise { // arrow.core.r open suspend fun <#A1: kotlin/Any?> (kotlin.coroutines/SuspendFunction1, #A1>).invoke(): #A1 // arrow.core.raise/Raise.invoke|invoke@kotlin.coroutines.SuspendFunction1,0:0>(){0§}[0] } +abstract interface <#A: in kotlin/Any?> arrow.core/MonotoneCollectionBuilder { // arrow.core/MonotoneCollectionBuilder|null[0] + abstract fun _add(#A): kotlin/Boolean // arrow.core/MonotoneCollectionBuilder._add|_add(1:0){}[0] + abstract fun _addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneCollectionBuilder._addAll|_addAll(kotlin.collections.Collection<1:0>){}[0] + + abstract interface NonEmpty // arrow.core/MonotoneCollectionBuilder.NonEmpty|null[0] +} + abstract interface <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core/MemoizationCache { // arrow.core/MemoizationCache|null[0] abstract fun get(#A): #B? // arrow.core/MemoizationCache.get|get(1:0){}[0] abstract fun set(#A, #B): #B // arrow.core/MemoizationCache.set|set(1:0;1:1){}[0] } -abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableCollection : kotlin.collections/Collection<#A> { // arrow.core/MonotoneMutableCollection|null[0] - abstract fun _add(#A): kotlin/Boolean // arrow.core/MonotoneMutableCollection._add|_add(1:0){}[0] - abstract fun _addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneMutableCollection._addAll|_addAll(kotlin.collections.Collection<1:0>){}[0] -} - -abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core/MonotoneMutableCollection<#A>, kotlin.collections/List<#A> { // arrow.core/MonotoneMutableList|null[0] +abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core/MonotoneCollectionBuilder<#A>, kotlin.collections/List<#A> { // arrow.core/MonotoneMutableList|null[0] abstract fun _add(kotlin/Int, #A) // arrow.core/MonotoneMutableList._add|_add(kotlin.Int;1:0){}[0] abstract fun _addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneMutableList._addAll|_addAll(kotlin.Int;kotlin.collections.Collection<1:0>){}[0] abstract fun listIterator(): arrow.core/MonotoneMutableList.Iterator<#A> // arrow.core/MonotoneMutableList.listIterator|listIterator(){}[0] @@ -68,7 +70,7 @@ abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core } } -abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableSet : arrow.core/MonotoneMutableCollection<#A>, kotlin.collections/Set<#A> { // arrow.core/MonotoneMutableSet|null[0] +abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableSet : arrow.core/MonotoneCollectionBuilder<#A>, kotlin.collections/Set<#A> { // arrow.core/MonotoneMutableSet|null[0] final object Companion { // arrow.core/MonotoneMutableSet.Companion|null[0] final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(){0§}[0] final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableSet<#A2> // arrow.core/MonotoneMutableSet.Companion.invoke|invoke(kotlin.Int){0§}[0] @@ -79,8 +81,6 @@ abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin. open val head // arrow.core/NonEmptyCollection.head|{}head[0] open fun (): #A // arrow.core/NonEmptyCollection.head.|(){}[0] - abstract fun plus(#A): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(1:0){}[0] - abstract fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(kotlin.collections.Iterable<1:0>){}[0] open fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] open fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyCollection.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] open fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyCollection.map|map(kotlin.Function1<1:0,0:0>){0§}[0] @@ -90,6 +90,8 @@ abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin. open fun firstOrNull(): #A // arrow.core/NonEmptyCollection.firstOrNull|firstOrNull(){}[0] open fun isEmpty(): kotlin/Boolean // arrow.core/NonEmptyCollection.isEmpty|isEmpty(){}[0] open fun lastOrNull(): #A // arrow.core/NonEmptyCollection.lastOrNull|lastOrNull(){}[0] + open fun plus(#A): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(1:0){}[0] + open fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(kotlin.collections.Iterable<1:0>){}[0] open fun toNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.toNonEmptyList|toNonEmptyList(){}[0] open fun toNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/NonEmptyCollection.toNonEmptySet|toNonEmptySet(){}[0] } @@ -747,9 +749,10 @@ final const val arrow.core/RedundantAPI // arrow.core/RedundantAPI|{}RedundantAP final fun (arrow.core.raise/Traced).arrow.core.raise/withCause(arrow.core.raise/Traced): arrow.core.raise/Traced // arrow.core.raise/withCause|withCause@arrow.core.raise.Traced(arrow.core.raise.Traced){}[0] final fun (kotlin/String).arrow.core/escaped(): kotlin/String // arrow.core/escaped|escaped@kotlin.String(){}[0] +final fun <#A: arrow.core/MonotoneCollectionBuilder<*> & kotlin.collections/Collection<*>> (#A).arrow.core/isNonEmpty(): kotlin/Boolean // arrow.core/isNonEmpty|isNonEmpty@0:0(){0§&arrow.core.MonotoneCollectionBuilder<*>>}[0] final fun <#A: kotlin/Any> (kotlin/Function1<#A, kotlin/Boolean>).arrow.core/mapNullable(): kotlin/Function1<#A?, kotlin/Boolean> // arrow.core/mapNullable|mapNullable@kotlin.Function1<0:0,kotlin.Boolean>(){0§}[0] -final fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> (#B).arrow.core/asNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/asNonEmptyList|asNonEmptyList@0:1(){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] -final fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> (#B).arrow.core/asNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/asNonEmptySet|asNonEmptySet@0:1(){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/List<#A>> (#B).arrow.core/asNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/asNonEmptyList|asNonEmptyList@0:1(){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] +final fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/Set<#A>> (#B).arrow.core/asNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/asNonEmptySet|asNonEmptySet@0:1(){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?> (kotlin.sequences/Sequence<#A>).arrow.core/zip(kotlin.sequences/Sequence<#B>, kotlin.sequences/Sequence<#C>, kotlin.sequences/Sequence<#D>, kotlin.sequences/Sequence<#E>, kotlin.sequences/Sequence<#F>, kotlin.sequences/Sequence<#G>, kotlin.sequences/Sequence<#H>, kotlin.sequences/Sequence<#I>, kotlin.sequences/Sequence<#J>, kotlin/Function10<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K>): kotlin.sequences/Sequence<#K> // arrow.core/zip|zip@kotlin.sequences.Sequence<0:0>(kotlin.sequences.Sequence<0:1>;kotlin.sequences.Sequence<0:2>;kotlin.sequences.Sequence<0:3>;kotlin.sequences.Sequence<0:4>;kotlin.sequences.Sequence<0:5>;kotlin.sequences.Sequence<0:6>;kotlin.sequences.Sequence<0:7>;kotlin.sequences.Sequence<0:8>;kotlin.sequences.Sequence<0:9>;kotlin.Function10<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?> (kotlin.sequences/Sequence<#A>).arrow.core/zip(kotlin.sequences/Sequence<#B>, kotlin.sequences/Sequence<#C>, kotlin.sequences/Sequence<#D>, kotlin.sequences/Sequence<#E>, kotlin.sequences/Sequence<#F>, kotlin.sequences/Sequence<#G>, kotlin.sequences/Sequence<#H>, kotlin.sequences/Sequence<#I>, kotlin/Function9<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J>): kotlin.sequences/Sequence<#J> // arrow.core/zip|zip@kotlin.sequences.Sequence<0:0>(kotlin.sequences.Sequence<0:1>;kotlin.sequences.Sequence<0:2>;kotlin.sequences.Sequence<0:3>;kotlin.sequences.Sequence<0:4>;kotlin.sequences.Sequence<0:5>;kotlin.sequences.Sequence<0:6>;kotlin.sequences.Sequence<0:7>;kotlin.sequences.Sequence<0:8>;kotlin.Function9<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§}[0] final fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?> (arrow.core/Tuple8<#A, #B, #C, #D, #E, #F, #G, #H>).arrow.core/plus(#I): arrow.core/Tuple9<#A, #B, #C, #D, #E, #F, #G, #H, #I> // arrow.core/plus|plus@arrow.core.Tuple8<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7>(0:8){0§;1§;2§;3§;4§;5§;6§;7§;8§}[0] @@ -854,11 +857,10 @@ final fun <#A: kotlin/Any?> (#A).arrow.core/some(): arrow.core/Option<#A> // arr final fun <#A: kotlin/Any?> (#A?).arrow.core/toOption(): arrow.core/Option<#A> // arrow.core/toOption|toOption@0:0?(){0§}[0] final fun <#A: kotlin/Any?> (arrow.core.raise/Accumulate<#A>).arrow.core.raise/tolerant(arrow.core.raise/Raise>): arrow.core.raise/Accumulate<#A> // arrow.core.raise/tolerant|tolerant@arrow.core.raise.Accumulate<0:0>(arrow.core.raise.Raise>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/Either<#A, #A>).arrow.core/merge(): #A // arrow.core/merge|merge@arrow.core.Either<0:0,0:0>(){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/add(#A): kotlin/Boolean // arrow.core/add|add@arrow.core.MonotoneMutableCollection<0:0>(0:0){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(arrow.core.NonEmptyCollection<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(kotlin.collections.Collection<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/addAll(kotlin.collections/Iterable<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableCollection<0:0>(kotlin.collections.Iterable<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableCollection<#A>).arrow.core/isNonEmpty(): kotlin/Boolean // arrow.core/isNonEmpty|isNonEmpty@arrow.core.MonotoneMutableCollection<0:0>(){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/add(#A): kotlin/Boolean // arrow.core/add|add@arrow.core.MonotoneCollectionBuilder<0:0>(0:0){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(arrow.core.NonEmptyCollection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Collection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Iterable<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Iterable<0:0>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/add(kotlin/Int, #A) // arrow.core/add|add@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;0:0){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;arrow.core.NonEmptyCollection<0:0>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;kotlin.collections.Collection<0:0>){0§}[0] @@ -939,10 +941,10 @@ final fun arrow.core/sort(kotlin/Long, kotlin/LongArray...): kotlin.collections/ final fun arrow.core/sort(kotlin/Short, kotlin/Short): kotlin/Pair // arrow.core/sort|sort(kotlin.Short;kotlin.Short){}[0] final fun arrow.core/sort(kotlin/Short, kotlin/Short, kotlin/Short): kotlin/Triple // arrow.core/sort|sort(kotlin.Short;kotlin.Short;kotlin.Short){}[0] final fun arrow.core/sort(kotlin/Short, kotlin/ShortArray...): kotlin.collections/List // arrow.core/sort|sort(kotlin.Short;kotlin.ShortArray...){}[0] -final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] -final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] -final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] -final inline fun <#A: kotlin/Any?, #B: arrow.core/NonEmptyCollection<#A> & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Int = ..., kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.NonEmptyCollection<0:0>>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Function1,0:1>){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/List<#A>> arrow.core/buildNonEmptyList(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptyList<#A> // arrow.core/buildNonEmptyList|buildNonEmptyList(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Function1,0:1>){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] +final inline fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/Set<#A>> arrow.core/buildNonEmptySet(kotlin/Int, kotlin/Function1, #B>): arrow.core/NonEmptySet<#A> // arrow.core/buildNonEmptySet|buildNonEmptySet(kotlin.Int;kotlin.Function1,0:1>){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (arrow.core.raise/Raise<#A>).arrow.core.raise/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise/ensureNotNull|ensureNotNull@arrow.core.raise.Raise<0:0>(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any> (context(arrow.core.raise/Raise<#A>)).arrow.core.raise.context/ensureNotNull(#B?, kotlin/Function0<#A>): #B // arrow.core.raise.context/ensureNotNull|ensureNotNull(arrow.core.raise.Raise<0:0>)(0:1?;kotlin.Function0<0:0>){0§;1§}[0] final inline fun <#A: kotlin/Any?, #B: kotlin/Any?, #C: kotlin/Any?, #D: kotlin/Any?, #E: kotlin/Any?, #F: kotlin/Any?, #G: kotlin/Any?, #H: kotlin/Any?, #I: kotlin/Any?, #J: kotlin/Any?, #K: kotlin/Any?, #L: kotlin/Any?> (kotlin.collections/Map<#A, #B>).arrow.core/zip(kotlin.collections/Map<#A, #C>, kotlin.collections/Map<#A, #D>, kotlin.collections/Map<#A, #E>, kotlin.collections/Map<#A, #F>, kotlin.collections/Map<#A, #G>, kotlin.collections/Map<#A, #H>, kotlin.collections/Map<#A, #I>, kotlin.collections/Map<#A, #J>, kotlin.collections/Map<#A, #K>, kotlin/Function11<#A, #B, #C, #D, #E, #F, #G, #H, #I, #J, #K, #L>): kotlin.collections/Map<#A, #L> // arrow.core/zip|zip@kotlin.collections.Map<0:0,0:1>(kotlin.collections.Map<0:0,0:2>;kotlin.collections.Map<0:0,0:3>;kotlin.collections.Map<0:0,0:4>;kotlin.collections.Map<0:0,0:5>;kotlin.collections.Map<0:0,0:6>;kotlin.collections.Map<0:0,0:7>;kotlin.collections.Map<0:0,0:8>;kotlin.collections.Map<0:0,0:9>;kotlin.collections.Map<0:0,0:10>;kotlin.Function11<0:0,0:1,0:2,0:3,0:4,0:5,0:6,0:7,0:8,0:9,0:10,0:11>){0§;1§;2§;3§;4§;5§;6§;7§;8§;9§;10§;11§}[0] diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index ca34a289add..2b52073d586 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -349,17 +349,20 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { public static synthetic fun MemoizedDeepRecursiveFunction$default (Larrow/core/MemoizationCache;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lkotlin/DeepRecursiveFunction; } -public abstract interface class arrow/core/MonotoneMutableCollection : java/util/Collection, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneCollectionBuilder { public abstract fun _add (Ljava/lang/Object;)Z public abstract fun _addAll (Ljava/util/Collection;)Z } -public final class arrow/core/MonotoneMutableCollectionKt { - public static final fun add (Larrow/core/MonotoneMutableCollection;Ljava/lang/Object;)Z +public abstract interface class arrow/core/MonotoneCollectionBuilder$NonEmpty { +} + +public final class arrow/core/MonotoneCollectionBuilderKt { + public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)Z public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneMutableCollection;Ljava/util/Collection;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)Z + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)Z public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; @@ -368,11 +371,10 @@ public final class arrow/core/MonotoneMutableCollectionKt { public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static synthetic fun buildNonEmptySet$default (ILkotlin/jvm/functions/Function1;ILjava/lang/Object;)Ljava/util/Set; - public static final fun isNonEmpty (Larrow/core/MonotoneMutableCollection;)Z + public static final fun isNonEmpty (Ljava/util/Collection;)Z } -public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneMutableCollection, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneCollectionBuilder, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; public abstract fun _add (ILjava/lang/Object;)V public abstract fun _addAll (ILjava/util/Collection;)Z @@ -392,7 +394,7 @@ public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/u public abstract fun set (Ljava/lang/Object;)V } -public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneMutableCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { +public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneCollectionBuilder, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableSet$Companion; } @@ -428,6 +430,8 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; + public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Object;)Larrow/core/NonEmptyCollection; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; public static fun toNonEmptySet-5sCjGKo (Larrow/core/NonEmptyCollection;)Ljava/util/Set; public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; diff --git a/arrow-libs/core/arrow-core/build.gradle.kts b/arrow-libs/core/arrow-core/build.gradle.kts index 0d3a1524ac4..e739533eae2 100644 --- a/arrow-libs/core/arrow-core/build.gradle.kts +++ b/arrow-libs/core/arrow-core/build.gradle.kts @@ -9,7 +9,6 @@ plugins { kotlin { compilerOptions.freeCompilerArgs.add("-Xexpect-actual-classes") compilerOptions.freeCompilerArgs.add("-Xcontext-parameters") - compilerOptions.freeCompilerArgs.add("-Xallow-contracts-on-more-functions") sourceSets { val nonJvmAndJsMain by creating { dependsOn(nonJvmMain.get()) } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt similarity index 77% rename from arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt rename to arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt index 72d1f6b264c..70f7df1bc75 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneMutableCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt @@ -2,33 +2,42 @@ @file:OptIn(ExperimentalContracts::class) package arrow.core +import arrow.core.MonotoneCollectionBuilder.NonEmpty import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract - /** - * A mutable collection that can only grow by adding elements. + * A builder for collections that can only grow by adding elements. * Removing elements is not supported to preserve monotonicity. */ @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableCollection: Collection { +public interface MonotoneCollectionBuilder { // underscored so that addAll(Nec) extension overload takes precedence + // Turning this into an abstract class doesn't work well because + // contracts on methods don't work well for some reason? @IgnorableReturnValue public fun _addAll(elements: Collection): Boolean @IgnorableReturnValue public fun _add(element: E): Boolean + + /** + * Marker interface for builders that guarantee at least one element has been added. + * @see MonotoneCollectionBuilder + * @see buildNonEmptyList + */ + public interface NonEmpty } @IgnorableReturnValue -public fun MonotoneMutableCollection.add(element: E): Boolean { - contract { returns() implies (this@add is NonEmptyCollection) } +public fun MonotoneCollectionBuilder.add(element: E): Boolean { + contract { returns() implies (this@add is NonEmpty) } return _add(element) } @IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: Iterable): Boolean = when (elements) { +public fun MonotoneCollectionBuilder.addAll(elements: Iterable): Boolean = when (elements) { is Collection -> addAll(elements) else -> { var result = false @@ -38,16 +47,16 @@ public fun MonotoneMutableCollection.addAll(elements: Iterable): Boole } @IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: NonEmptyCollection): Boolean { - contract { returns() implies (this@addAll is NonEmptyCollection) } +public fun MonotoneCollectionBuilder.addAll(elements: NonEmptyCollection): Boolean { + contract { returns() implies (this@addAll is NonEmpty) } return _addAll(elements) } @IgnorableReturnValue -public fun MonotoneMutableCollection.addAll(elements: Collection): Boolean = _addAll(elements) +public fun MonotoneCollectionBuilder.addAll(elements: Collection): Boolean = _addAll(elements) -public fun MonotoneMutableCollection.isNonEmpty(): Boolean { - contract { returns(true) implies (this@isNonEmpty is NonEmptyCollection) } +public fun C.isNonEmpty(): Boolean where C : Collection<*>, C : MonotoneCollectionBuilder<*> { + contract { returns(true) implies (this@isNonEmpty is NonEmpty) } return isNotEmpty() } @@ -56,7 +65,7 @@ public fun MonotoneMutableCollection.isNonEmpty(): Boolean { * Removing elements is not supported to preserve monotonicity. */ @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableList: MonotoneMutableCollection, List { +public interface MonotoneMutableList: MonotoneCollectionBuilder, List { @IgnorableReturnValue public fun _addAll(index: Int, elements: Collection): Boolean @@ -90,7 +99,7 @@ public interface MonotoneMutableList: MonotoneMutableCollection, List { } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmptyCollection, List by underlying { + private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmpty, List by underlying { constructor() : this(ArrayList()) constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) @@ -117,21 +126,21 @@ public fun MonotoneMutableList.addAll(index: Int, elements: Collection @IgnorableReturnValue public fun MonotoneMutableList.addAll(index: Int, elements: NonEmptyCollection): Boolean { - contract { returns() implies (this@addAll is NonEmptyCollection) } + contract { returns() implies (this@addAll is NonEmpty) } return _addAll(index, elements) } public fun MonotoneMutableList.add(index: Int, element: E) { - contract { returns() implies (this@add is NonEmptyCollection) } + contract { returns() implies (this@add is NonEmpty) } _add(index, element) } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmptyCollection = NonEmptyList(this) +public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmpty = NonEmptyList(this) public inline fun buildNonEmptyList( builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : List, L : NonEmptyCollection { +): NonEmptyList where L : List, L : NonEmpty { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableList()).asNonEmptyList() } @@ -139,7 +148,7 @@ public inline fun buildNonEmptyList( public inline fun buildNonEmptyList( capacity: Int, builderAction: MonotoneMutableList.() -> L -): NonEmptyList where L : List, L : NonEmptyCollection { +): NonEmptyList where L : List, L : NonEmpty { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableList(capacity)).asNonEmptyList() } @@ -149,14 +158,14 @@ public inline fun buildNonEmptyList( * Removing elements is not supported to preserve monotonicity. */ @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) -public interface MonotoneMutableSet: MonotoneMutableCollection, Set { +public interface MonotoneMutableSet: MonotoneCollectionBuilder, Set { public companion object { public operator fun invoke(): MonotoneMutableSet = Impl() public operator fun invoke(initialCapacity: Int): MonotoneMutableSet = Impl(initialCapacity) } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmptyCollection, Set by underlying { + private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmpty, Set by underlying { constructor() : this(LinkedHashSet()) constructor(initialCapacity: Int) : this(LinkedHashSet(initialCapacity)) @@ -172,11 +181,11 @@ public interface MonotoneMutableSet: MonotoneMutableCollection, Set { } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) -public fun S.asNonEmptySet(): NonEmptySet where S : Set, S : NonEmptyCollection = NonEmptySet(this) +public fun S.asNonEmptySet(): NonEmptySet where S : Set, S : NonEmpty = NonEmptySet(this) public inline fun buildNonEmptySet( builderAction: MonotoneMutableSet.() -> S -): NonEmptySet where S : Set, S : NonEmptyCollection { +): NonEmptySet where S : Set, S : NonEmpty { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableSet()).asNonEmptySet() } @@ -184,7 +193,7 @@ public inline fun buildNonEmptySet( public inline fun buildNonEmptySet( capacity: Int, builderAction: MonotoneMutableSet.() -> S -): NonEmptySet where S : Set, S : NonEmptyCollection { +): NonEmptySet where S : Set, S : NonEmpty { contract { callsInPlace(builderAction, InvocationKind.EXACTLY_ONCE) } return builderAction(MonotoneMutableSet(capacity)).asNonEmptySet() } From 9ae716f6f7b5c32a5c61aa6196d5be46e505d34d Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Wed, 31 Dec 2025 00:49:49 +0000 Subject: [PATCH 13/16] Remove NonEmptyCollection.plus default impls and NonEmptySet overrides --- .../arrow-core/api/android/arrow-core.api | 2 -- .../core/arrow-core/api/arrow-core.klib.api | 8 ++--- .../core/arrow-core/api/jvm/arrow-core.api | 2 -- .../kotlin/arrow/core/NonEmptyCollection.kt | 12 ++------ .../kotlin/arrow/core/NonEmptySet.kt | 30 ------------------- 5 files changed, 4 insertions(+), 50 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index 2b52073d586..d4838fd85d6 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -430,8 +430,6 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; - public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; - public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Object;)Larrow/core/NonEmptyCollection; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; public static fun toNonEmptySet-5sCjGKo (Larrow/core/NonEmptyCollection;)Ljava/util/Set; public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index 1763aa461c6..98e3e04e743 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -81,6 +81,8 @@ abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin. open val head // arrow.core/NonEmptyCollection.head|{}head[0] open fun (): #A // arrow.core/NonEmptyCollection.head.|(){}[0] + abstract fun plus(#A): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(1:0){}[0] + abstract fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(kotlin.collections.Iterable<1:0>){}[0] open fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] open fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyCollection.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] open fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptyCollection.map|map(kotlin.Function1<1:0,0:0>){0§}[0] @@ -90,8 +92,6 @@ abstract interface <#A: out kotlin/Any?> arrow.core/NonEmptyCollection : kotlin. open fun firstOrNull(): #A // arrow.core/NonEmptyCollection.firstOrNull|firstOrNull(){}[0] open fun isEmpty(): kotlin/Boolean // arrow.core/NonEmptyCollection.isEmpty|isEmpty(){}[0] open fun lastOrNull(): #A // arrow.core/NonEmptyCollection.lastOrNull|lastOrNull(){}[0] - open fun plus(#A): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(1:0){}[0] - open fun plus(kotlin.collections/Iterable<#A>): arrow.core/NonEmptyCollection<#A> // arrow.core/NonEmptyCollection.plus|plus(kotlin.collections.Iterable<1:0>){}[0] open fun toNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptyCollection.toNonEmptyList|toNonEmptyList(){}[0] open fun toNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/NonEmptyCollection.toNonEmptySet|toNonEmptySet(){}[0] } @@ -465,10 +465,6 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptySet : arrow.core/NonE final val size // arrow.core/NonEmptySet.size|{}size[0] final fun (): kotlin/Int // arrow.core/NonEmptySet.size.|(){}[0] - final fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptySet.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] - final fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] - final fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.map|map(kotlin.Function1<1:0,0:0>){0§}[0] - final fun <#A1: kotlin/Any?> mapIndexed(kotlin/Function2): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.mapIndexed|mapIndexed(kotlin.Function2){0§}[0] final fun <#A1: kotlin/Any?> zip(arrow.core/NonEmptyCollection<#A1>): arrow.core/NonEmptyList> // arrow.core/NonEmptySet.zip|zip(arrow.core.NonEmptyCollection<0:0>){0§}[0] final fun contains(#A): kotlin/Boolean // arrow.core/NonEmptySet.contains|contains(1:0){}[0] final fun containsAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/NonEmptySet.containsAll|containsAll(kotlin.collections.Collection<1:0>){}[0] diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index 2b52073d586..d4838fd85d6 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -430,8 +430,6 @@ public final class arrow/core/NonEmptyCollection$DefaultImpls { public static fun lastOrNull (Larrow/core/NonEmptyCollection;)Ljava/lang/Object; public static fun map-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static fun mapIndexed-0-xjo5U (Larrow/core/NonEmptyCollection;Lkotlin/jvm/functions/Function2;)Ljava/util/List; - public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Iterable;)Larrow/core/NonEmptyCollection; - public static fun plus (Larrow/core/NonEmptyCollection;Ljava/lang/Object;)Larrow/core/NonEmptyCollection; public static fun toNonEmptyList-1X0FA-Y (Larrow/core/NonEmptyCollection;)Ljava/util/List; public static fun toNonEmptySet-5sCjGKo (Larrow/core/NonEmptyCollection;)Ljava/util/Set; public static fun zip (Larrow/core/NonEmptyCollection;Larrow/core/NonEmptyCollection;)Larrow/core/NonEmptyCollection; diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt index 0ddf8617b6c..f5a3db4dbfe 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyCollection.kt @@ -9,17 +9,9 @@ public interface NonEmptyCollection : Collection { override fun isEmpty(): Boolean = false public val head: E get() = first() - public operator fun plus(element: @UnsafeVariance E): NonEmptyCollection = buildNonEmptyList(size + 1) { - addAll(this@NonEmptyCollection) - add(element) - this - } + public operator fun plus(element: @UnsafeVariance E): NonEmptyCollection - public operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyCollection = buildNonEmptyList(size + elements.collectionSizeOrDefault(10)) { - addAll(this@NonEmptyCollection) - addAll(elements) - this - } + public operator fun plus(elements: Iterable<@UnsafeVariance E>): NonEmptyCollection public fun toNonEmptySet(): NonEmptySet = buildNonEmptySet(size) { addAll(this@NonEmptyCollection) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 8dfc5f2319e..82286045bb0 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -50,36 +50,6 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern public override fun distinct(): NonEmptyList = toNonEmptyList() - override fun distinctBy(selector: (E) -> K): NonEmptyList = buildNonEmptyList(size) { - add(head) // head is always distinct - val seen = hashSetOf() - var isFirst = true - for (e in elements) { - if (seen.add(selector(e)) && !isFirst) add(e) - isFirst = false - } - this - } - - override fun map(transform: (E) -> T): NonEmptyList = buildNonEmptyList(size) { - val iterator = elements.iterator() - do add(transform(iterator.next())) while (iterator.hasNext()) - this - } - - override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = buildNonEmptyList(size) { - val iterator = elements.iterator() - do addAll(transform(iterator.next())) while (iterator.hasNext()) - this - } - - override fun mapIndexed(transform: (index:Int, E) -> T): NonEmptyList = buildNonEmptyList(size) { - var i = 0 - val iterator = elements.iterator() - do add(transform(i++, iterator.next())) while (iterator.hasNext()) - this - } - override fun zip(other: NonEmptyCollection): NonEmptyList> = buildNonEmptyList(minOf(size, other.size)) { val first = this@NonEmptySet.iterator() val second = other.iterator() From 7cbfa3b5e25a6346511a9b899a3e012823236572 Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Wed, 31 Dec 2025 01:23:15 +0000 Subject: [PATCH 14/16] Bring back Nes overrides due to KT-80101 --- .../src/commonMain/kotlin/arrow/core/NonEmptySet.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 82286045bb0..4715633ec1e 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -50,6 +50,16 @@ public value class NonEmptySet @PotentiallyUnsafeNonEmptyOperation intern public override fun distinct(): NonEmptyList = toNonEmptyList() + // BEGIN: overrides due to KT-80101 NoSuchMethodError when inheriting function implementations in interfaces + public override fun distinctBy(selector: (E) -> K): NonEmptyList = super.distinctBy(selector) + + public override fun map(transform: (E) -> T): NonEmptyList = super.map(transform) + + public override fun flatMap(transform: (E) -> NonEmptyCollection): NonEmptyList = super.flatMap(transform) + + public override fun mapIndexed(transform: (index: Int, E) -> T): NonEmptyList = super.mapIndexed(transform) + // END + override fun zip(other: NonEmptyCollection): NonEmptyList> = buildNonEmptyList(minOf(size, other.size)) { val first = this@NonEmptySet.iterator() val second = other.iterator() From e98ea13a26d3a1a4677d1d5bf3efd03a5fe36299 Mon Sep 17 00:00:00 2001 From: kyay10 <12699034+kyay10@users.noreply.github.com> Date: Wed, 31 Dec 2025 02:26:03 +0000 Subject: [PATCH 15/16] Auto-update API files --- arrow-libs/core/arrow-core/api/arrow-core.klib.api | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index 98e3e04e743..0fd182ef03a 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -465,6 +465,10 @@ final value class <#A: out kotlin/Any?> arrow.core/NonEmptySet : arrow.core/NonE final val size // arrow.core/NonEmptySet.size|{}size[0] final fun (): kotlin/Int // arrow.core/NonEmptySet.size.|(){}[0] + final fun <#A1: kotlin/Any?> distinctBy(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A> // arrow.core/NonEmptySet.distinctBy|distinctBy(kotlin.Function1<1:0,0:0>){0§}[0] + final fun <#A1: kotlin/Any?> flatMap(kotlin/Function1<#A, arrow.core/NonEmptyCollection<#A1>>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.flatMap|flatMap(kotlin.Function1<1:0,arrow.core.NonEmptyCollection<0:0>>){0§}[0] + final fun <#A1: kotlin/Any?> map(kotlin/Function1<#A, #A1>): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.map|map(kotlin.Function1<1:0,0:0>){0§}[0] + final fun <#A1: kotlin/Any?> mapIndexed(kotlin/Function2): arrow.core/NonEmptyList<#A1> // arrow.core/NonEmptySet.mapIndexed|mapIndexed(kotlin.Function2){0§}[0] final fun <#A1: kotlin/Any?> zip(arrow.core/NonEmptyCollection<#A1>): arrow.core/NonEmptyList> // arrow.core/NonEmptySet.zip|zip(arrow.core.NonEmptyCollection<0:0>){0§}[0] final fun contains(#A): kotlin/Boolean // arrow.core/NonEmptySet.contains|contains(1:0){}[0] final fun containsAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/NonEmptySet.containsAll|containsAll(kotlin.collections.Collection<1:0>){}[0] From 9e92636fc16ab221e452e96de5bf41206dfc90bb Mon Sep 17 00:00:00 2001 From: Youssef Shoaib Date: Sun, 11 Jan 2026 10:39:41 +0000 Subject: [PATCH 16/16] Reduce API surface --- .../arrow-core/api/android/arrow-core.api | 27 +---- .../core/arrow-core/api/arrow-core.klib.api | 28 +---- .../core/arrow-core/api/jvm/arrow-core.api | 27 +---- .../arrow/core/MonotoneCollectionBuilder.kt | 109 +++--------------- .../kotlin/arrow/core/NonEmptyList.kt | 6 +- .../kotlin/arrow/core/NonEmptySet.kt | 6 +- .../arrow/core/raise/RaiseAccumulate.kt | 19 ++- 7 files changed, 56 insertions(+), 166 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/android/arrow-core.api b/arrow-libs/core/arrow-core/api/android/arrow-core.api index d4838fd85d6..7cad018a180 100644 --- a/arrow-libs/core/arrow-core/api/android/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/android/arrow-core.api @@ -350,38 +350,28 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { } public abstract interface class arrow/core/MonotoneCollectionBuilder { - public abstract fun _add (Ljava/lang/Object;)Z - public abstract fun _addAll (Ljava/util/Collection;)Z + public abstract fun _add (Ljava/lang/Object;)V + public abstract fun _addAll (Ljava/util/Collection;)V } public abstract interface class arrow/core/MonotoneCollectionBuilder$NonEmpty { } public final class arrow/core/MonotoneCollectionBuilderKt { - public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)Z - public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)V public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static final fun isNonEmpty (Ljava/util/Collection;)Z } public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneCollectionBuilder, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; - public abstract fun _add (ILjava/lang/Object;)V - public abstract fun _addAll (ILjava/util/Collection;)Z - public abstract fun listIterator ()Larrow/core/MonotoneMutableList$Iterator; - public abstract fun listIterator (I)Larrow/core/MonotoneMutableList$Iterator; - public abstract fun set (ILjava/lang/Object;)Ljava/lang/Object; - public abstract fun subList (II)Larrow/core/MonotoneMutableList; } public final class arrow/core/MonotoneMutableList$Companion { @@ -389,11 +379,6 @@ public final class arrow/core/MonotoneMutableList$Companion { public final fun invoke (I)Larrow/core/MonotoneMutableList; } -public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { - public abstract fun add (Ljava/lang/Object;)V - public abstract fun set (Ljava/lang/Object;)V -} - public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneCollectionBuilder, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableSet$Companion; } diff --git a/arrow-libs/core/arrow-core/api/arrow-core.klib.api b/arrow-libs/core/arrow-core/api/arrow-core.klib.api index 0fd182ef03a..bb3db2f4fd9 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.klib.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.klib.api @@ -40,8 +40,8 @@ abstract interface <#A: in kotlin/Any?> arrow.core.raise/Raise { // arrow.core.r } abstract interface <#A: in kotlin/Any?> arrow.core/MonotoneCollectionBuilder { // arrow.core/MonotoneCollectionBuilder|null[0] - abstract fun _add(#A): kotlin/Boolean // arrow.core/MonotoneCollectionBuilder._add|_add(1:0){}[0] - abstract fun _addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneCollectionBuilder._addAll|_addAll(kotlin.collections.Collection<1:0>){}[0] + abstract fun _add(#A) // arrow.core/MonotoneCollectionBuilder._add|_add(1:0){}[0] + abstract fun _addAll(kotlin.collections/Collection<#A>) // arrow.core/MonotoneCollectionBuilder._addAll|_addAll(kotlin.collections.Collection<1:0>){}[0] abstract interface NonEmpty // arrow.core/MonotoneCollectionBuilder.NonEmpty|null[0] } @@ -52,18 +52,6 @@ abstract interface <#A: kotlin/Any?, #B: kotlin/Any?> arrow.core/MemoizationCach } abstract interface <#A: kotlin/Any?> arrow.core/MonotoneMutableList : arrow.core/MonotoneCollectionBuilder<#A>, kotlin.collections/List<#A> { // arrow.core/MonotoneMutableList|null[0] - abstract fun _add(kotlin/Int, #A) // arrow.core/MonotoneMutableList._add|_add(kotlin.Int;1:0){}[0] - abstract fun _addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/MonotoneMutableList._addAll|_addAll(kotlin.Int;kotlin.collections.Collection<1:0>){}[0] - abstract fun listIterator(): arrow.core/MonotoneMutableList.Iterator<#A> // arrow.core/MonotoneMutableList.listIterator|listIterator(){}[0] - abstract fun listIterator(kotlin/Int): arrow.core/MonotoneMutableList.Iterator<#A> // arrow.core/MonotoneMutableList.listIterator|listIterator(kotlin.Int){}[0] - abstract fun set(kotlin/Int, #A): #A // arrow.core/MonotoneMutableList.set|set(kotlin.Int;1:0){}[0] - abstract fun subList(kotlin/Int, kotlin/Int): arrow.core/MonotoneMutableList<#A> // arrow.core/MonotoneMutableList.subList|subList(kotlin.Int;kotlin.Int){}[0] - - abstract interface <#A1: kotlin/Any?> Iterator : kotlin.collections/ListIterator<#A1> { // arrow.core/MonotoneMutableList.Iterator|null[0] - abstract fun add(#A1) // arrow.core/MonotoneMutableList.Iterator.add|add(1:0){}[0] - abstract fun set(#A1) // arrow.core/MonotoneMutableList.Iterator.set|set(1:0){}[0] - } - final object Companion { // arrow.core/MonotoneMutableList.Companion|null[0] final fun <#A2: kotlin/Any?> invoke(): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(){0§}[0] final fun <#A2: kotlin/Any?> invoke(kotlin/Int): arrow.core/MonotoneMutableList<#A2> // arrow.core/MonotoneMutableList.Companion.invoke|invoke(kotlin.Int){0§}[0] @@ -749,7 +737,6 @@ final const val arrow.core/RedundantAPI // arrow.core/RedundantAPI|{}RedundantAP final fun (arrow.core.raise/Traced).arrow.core.raise/withCause(arrow.core.raise/Traced): arrow.core.raise/Traced // arrow.core.raise/withCause|withCause@arrow.core.raise.Traced(arrow.core.raise.Traced){}[0] final fun (kotlin/String).arrow.core/escaped(): kotlin/String // arrow.core/escaped|escaped@kotlin.String(){}[0] -final fun <#A: arrow.core/MonotoneCollectionBuilder<*> & kotlin.collections/Collection<*>> (#A).arrow.core/isNonEmpty(): kotlin/Boolean // arrow.core/isNonEmpty|isNonEmpty@0:0(){0§&arrow.core.MonotoneCollectionBuilder<*>>}[0] final fun <#A: kotlin/Any> (kotlin/Function1<#A, kotlin/Boolean>).arrow.core/mapNullable(): kotlin/Function1<#A?, kotlin/Boolean> // arrow.core/mapNullable|mapNullable@kotlin.Function1<0:0,kotlin.Boolean>(){0§}[0] final fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/List<#A>> (#B).arrow.core/asNonEmptyList(): arrow.core/NonEmptyList<#A> // arrow.core/asNonEmptyList|asNonEmptyList@0:1(){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] final fun <#A: kotlin/Any?, #B: arrow.core/MonotoneCollectionBuilder.NonEmpty & kotlin.collections/Set<#A>> (#B).arrow.core/asNonEmptySet(): arrow.core/NonEmptySet<#A> // arrow.core/asNonEmptySet|asNonEmptySet@0:1(){0§;1§&arrow.core.MonotoneCollectionBuilder.NonEmpty>}[0] @@ -857,13 +844,10 @@ final fun <#A: kotlin/Any?> (#A).arrow.core/some(): arrow.core/Option<#A> // arr final fun <#A: kotlin/Any?> (#A?).arrow.core/toOption(): arrow.core/Option<#A> // arrow.core/toOption|toOption@0:0?(){0§}[0] final fun <#A: kotlin/Any?> (arrow.core.raise/Accumulate<#A>).arrow.core.raise/tolerant(arrow.core.raise/Raise>): arrow.core.raise/Accumulate<#A> // arrow.core.raise/tolerant|tolerant@arrow.core.raise.Accumulate<0:0>(arrow.core.raise.Raise>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/Either<#A, #A>).arrow.core/merge(): #A // arrow.core/merge|merge@arrow.core.Either<0:0,0:0>(){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/add(#A): kotlin/Boolean // arrow.core/add|add@arrow.core.MonotoneCollectionBuilder<0:0>(0:0){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(arrow.core.NonEmptyCollection<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Collection<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Iterable<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Iterable<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/add(kotlin/Int, #A) // arrow.core/add|add@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;0:0){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, arrow.core/NonEmptyCollection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;arrow.core.NonEmptyCollection<0:0>){0§}[0] -final fun <#A: kotlin/Any?> (arrow.core/MonotoneMutableList<#A>).arrow.core/addAll(kotlin/Int, kotlin.collections/Collection<#A>): kotlin/Boolean // arrow.core/addAll|addAll@arrow.core.MonotoneMutableList<0:0>(kotlin.Int;kotlin.collections.Collection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/add(#A) // arrow.core/add|add@arrow.core.MonotoneCollectionBuilder<0:0>(0:0){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(arrow.core/NonEmptyCollection<#A>) // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(arrow.core.NonEmptyCollection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Collection<#A>) // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Collection<0:0>){0§}[0] +final fun <#A: kotlin/Any?> (arrow.core/MonotoneCollectionBuilder<#A>).arrow.core/addAll(kotlin.collections/Iterable<#A>) // arrow.core/addAll|addAll@arrow.core.MonotoneCollectionBuilder<0:0>(kotlin.collections.Iterable<0:0>){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/NonEmptyList>).arrow.core/flatten(): arrow.core/NonEmptyList<#A> // arrow.core/flatten|flatten@arrow.core.NonEmptyList>(){0§}[0] final fun <#A: kotlin/Any?> (arrow.core/Option>).arrow.core/flatten(): arrow.core/Option<#A> // arrow.core/flatten|flatten@arrow.core.Option>(){0§}[0] final fun <#A: kotlin/Any?> (context(arrow.core.raise/Raise<#A>)).arrow.core.raise.context/raise(#A): kotlin/Nothing // arrow.core.raise.context/raise|raise(arrow.core.raise.Raise<0:0>)(0:0){0§}[0] diff --git a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api index d4838fd85d6..7cad018a180 100644 --- a/arrow-libs/core/arrow-core/api/jvm/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/jvm/arrow-core.api @@ -350,38 +350,28 @@ public final class arrow/core/MemoizedDeepRecursiveFunctionKt { } public abstract interface class arrow/core/MonotoneCollectionBuilder { - public abstract fun _add (Ljava/lang/Object;)Z - public abstract fun _addAll (Ljava/util/Collection;)Z + public abstract fun _add (Ljava/lang/Object;)V + public abstract fun _addAll (Ljava/util/Collection;)V } public abstract interface class arrow/core/MonotoneCollectionBuilder$NonEmpty { } public final class arrow/core/MonotoneCollectionBuilderKt { - public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)Z - public static final fun add (Larrow/core/MonotoneMutableList;ILjava/lang/Object;)V - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)Z - public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILarrow/core/NonEmptyCollection;)Z - public static final fun addAll (Larrow/core/MonotoneMutableList;ILjava/util/Collection;)Z + public static final fun add (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Object;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Larrow/core/NonEmptyCollection;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/lang/Iterable;)V + public static final fun addAll (Larrow/core/MonotoneCollectionBuilder;Ljava/util/Collection;)V public static final fun asNonEmptyList (Ljava/util/List;)Ljava/util/List; public static final fun asNonEmptySet (Ljava/util/Set;)Ljava/util/Set; public static final fun buildNonEmptyList (ILkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptyList (Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun buildNonEmptySet (ILkotlin/jvm/functions/Function1;)Ljava/util/Set; public static final fun buildNonEmptySet (Lkotlin/jvm/functions/Function1;)Ljava/util/Set; - public static final fun isNonEmpty (Ljava/util/Collection;)Z } public abstract interface class arrow/core/MonotoneMutableList : arrow/core/MonotoneCollectionBuilder, java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableList$Companion; - public abstract fun _add (ILjava/lang/Object;)V - public abstract fun _addAll (ILjava/util/Collection;)Z - public abstract fun listIterator ()Larrow/core/MonotoneMutableList$Iterator; - public abstract fun listIterator (I)Larrow/core/MonotoneMutableList$Iterator; - public abstract fun set (ILjava/lang/Object;)Ljava/lang/Object; - public abstract fun subList (II)Larrow/core/MonotoneMutableList; } public final class arrow/core/MonotoneMutableList$Companion { @@ -389,11 +379,6 @@ public final class arrow/core/MonotoneMutableList$Companion { public final fun invoke (I)Larrow/core/MonotoneMutableList; } -public abstract interface class arrow/core/MonotoneMutableList$Iterator : java/util/ListIterator, kotlin/jvm/internal/markers/KMappedMarker { - public abstract fun add (Ljava/lang/Object;)V - public abstract fun set (Ljava/lang/Object;)V -} - public abstract interface class arrow/core/MonotoneMutableSet : arrow/core/MonotoneCollectionBuilder, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/MonotoneMutableSet$Companion; } diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt index 70f7df1bc75..12f5e314343 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/MonotoneCollectionBuilder.kt @@ -14,13 +14,10 @@ import kotlin.contracts.contract @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) public interface MonotoneCollectionBuilder { // underscored so that addAll(Nec) extension overload takes precedence - // Turning this into an abstract class doesn't work well because - // contracts on methods don't work well for some reason? - @IgnorableReturnValue - public fun _addAll(elements: Collection): Boolean + // Turning this into an abstract class doesn't work well because of KT-83602 + public fun _addAll(elements: Collection) - @IgnorableReturnValue - public fun _add(element: E): Boolean + public fun _add(element: E) /** * Marker interface for builders that guarantee at least one element has been added. @@ -30,34 +27,31 @@ public interface MonotoneCollectionBuilder { public interface NonEmpty } -@IgnorableReturnValue -public fun MonotoneCollectionBuilder.add(element: E): Boolean { +public fun MonotoneCollectionBuilder.add(element: E) { contract { returns() implies (this@add is NonEmpty) } return _add(element) } -@IgnorableReturnValue -public fun MonotoneCollectionBuilder.addAll(elements: Iterable): Boolean = when (elements) { +public fun MonotoneCollectionBuilder.addAll(elements: Iterable): Unit = when (elements) { is Collection -> addAll(elements) - else -> { - var result = false - for (item in elements) if (add(item)) result = true - result - } + else -> for (item in elements) add(item) } -@IgnorableReturnValue -public fun MonotoneCollectionBuilder.addAll(elements: NonEmptyCollection): Boolean { +public fun MonotoneCollectionBuilder.addAll(elements: NonEmptyCollection) { contract { returns() implies (this@addAll is NonEmpty) } - return _addAll(elements) + _addAll(elements) } -@IgnorableReturnValue -public fun MonotoneCollectionBuilder.addAll(elements: Collection): Boolean = _addAll(elements) +public fun MonotoneCollectionBuilder.addAll(elements: Collection): Unit = _addAll(elements) + +@SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) +private abstract class MonotoneMutableCollectionImpl(private val underlying: MutableCollection) : MonotoneCollectionBuilder, NonEmpty { + final override fun _addAll(elements: Collection) { underlying.addAll(elements) } + final override fun _add(element: E) { underlying.add(element) } -public fun C.isNonEmpty(): Boolean where C : Collection<*>, C : MonotoneCollectionBuilder<*> { - contract { returns(true) implies (this@isNonEmpty is NonEmpty) } - return isNotEmpty() + final override fun equals(other: Any?) = underlying == other + final override fun hashCode() = underlying.hashCode() + final override fun toString() = underlying.toString() } /** @@ -66,75 +60,19 @@ public fun C.isNonEmpty(): Boolean where C : Collection<*>, C : MonotoneColl */ @SubclassOptInRequired(PotentiallyUnsafeNonEmptyOperation::class) public interface MonotoneMutableList: MonotoneCollectionBuilder, List { - @IgnorableReturnValue - public fun _addAll(index: Int, elements: Collection): Boolean - - @IgnorableReturnValue - public operator fun set(index: Int, element: E): E - - public fun _add(index: Int, element: E) - - override fun listIterator(): Iterator - - override fun listIterator(index: Int): Iterator - - override fun subList(fromIndex: Int, toIndex: Int): MonotoneMutableList - public companion object { public operator fun invoke(): MonotoneMutableList = Impl() public operator fun invoke(initialCapacity: Int): MonotoneMutableList = Impl(initialCapacity) } - public interface Iterator : ListIterator { - public fun set(element: T) - - public fun add(element: T) - } - - private class IteratorImpl(private val underlying: MutableListIterator) : Iterator, ListIterator by underlying { - override fun set(element: T) = underlying.set(element) - - override fun add(element: T) = underlying.add(element) - } - @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableList) : MonotoneMutableList, NonEmpty, List by underlying { + private class Impl private constructor(underlying: MutableList) : MonotoneMutableCollectionImpl(underlying), MonotoneMutableList, List by underlying { constructor() : this(ArrayList()) constructor(initialCapacity: Int) : this(ArrayList(initialCapacity)) - - override fun isEmpty(): Boolean = underlying.isEmpty() - - override fun _addAll(elements: Collection) = underlying.addAll(elements) - override fun _add(element: E) = underlying.add(element) - override fun _addAll(index: Int, elements: Collection) = underlying.addAll(index, elements) - override fun set(index: Int, element: E) = underlying.set(index, element) - override fun _add(index: Int, element: E) = underlying.add(index, element) - - override fun listIterator() = IteratorImpl(underlying.listIterator()) - override fun listIterator(index: Int) = IteratorImpl(underlying.listIterator(index)) - override fun subList(fromIndex: Int, toIndex: Int) = Impl(underlying.subList(fromIndex, toIndex)) - - override fun equals(other: Any?) = underlying == other - override fun hashCode() = underlying.hashCode() - override fun toString() = underlying.toString() } } -@IgnorableReturnValue -public fun MonotoneMutableList.addAll(index: Int, elements: Collection): Boolean = _addAll(index, elements) - -@IgnorableReturnValue -public fun MonotoneMutableList.addAll(index: Int, elements: NonEmptyCollection): Boolean { - contract { returns() implies (this@addAll is NonEmpty) } - return _addAll(index, elements) -} - -public fun MonotoneMutableList.add(index: Int, element: E) { - contract { returns() implies (this@add is NonEmpty) } - _add(index, element) -} - @OptIn(PotentiallyUnsafeNonEmptyOperation::class) public fun L.asNonEmptyList(): NonEmptyList where L : List, L : NonEmpty = NonEmptyList(this) @@ -165,18 +103,9 @@ public interface MonotoneMutableSet: MonotoneCollectionBuilder, Set { } @OptIn(PotentiallyUnsafeNonEmptyOperation::class) - private class Impl private constructor(private val underlying: MutableSet) : MonotoneMutableSet, NonEmpty, Set by underlying { + private class Impl private constructor(underlying: MutableSet) : MonotoneMutableCollectionImpl(underlying), MonotoneMutableSet, NonEmpty, Set by underlying { constructor() : this(LinkedHashSet()) constructor(initialCapacity: Int) : this(LinkedHashSet(initialCapacity)) - - override fun isEmpty(): Boolean = underlying.isEmpty() - - override fun _addAll(elements: Collection) = underlying.addAll(elements) - override fun _add(element: E) = underlying.add(element) - - override fun equals(other: Any?) = underlying == other - override fun hashCode() = underlying.hashCode() - override fun toString() = underlying.toString() } } 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 cbca02b725f..34ac204595b 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 @@ -563,11 +563,9 @@ public inline fun NonEmptyList.mapOrAccumulate( /** * Returns a [NonEmptyList] that contains a **copy** of the elements in [this]. */ +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) @JvmName("toNonEmptyListOrNull") -public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = MonotoneMutableList(collectionSizeOrDefault(10)).run { - addAll(this@toNonEmptyListOrNull) - if (isNonEmpty()) asNonEmptyList() else null -} +public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = toList().wrapAsNonEmptyListOrNull() /** * Returns a [NonEmptyList] that contains a **copy** of the elements in [this]. diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt index 4715633ec1e..d444a0cb1f7 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptySet.kt @@ -97,10 +97,8 @@ public fun nonEmptySetOf(first: E, vararg rest: E): NonEmptySet = /** * Returns a [NonEmptySet] that contains a **copy** of the elements in [this]. */ -public fun Iterable.toNonEmptySetOrNull(): NonEmptySet? = MonotoneMutableSet(collectionSizeOrDefault(10)).run { - addAll(this@toNonEmptySetOrNull) - if (isNonEmpty()) asNonEmptySet() else null -} +@OptIn(PotentiallyUnsafeNonEmptyOperation::class) +public fun Iterable.toNonEmptySetOrNull(): NonEmptySet? = toSet().wrapAsNonEmptySetOrNull() /** * Returns a [NonEmptySet] that contains a **copy** of the elements in [this]. 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 f8908437882..e76758df870 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 @@ -12,18 +12,20 @@ import arrow.core.MonotoneMutableList import arrow.core.MonotoneMutableSet import arrow.core.NonEmptyList import arrow.core.NonEmptySet +import arrow.core.PotentiallyUnsafeNonEmptyOperation import arrow.core.add import arrow.core.addAll import arrow.core.asNonEmptyList import arrow.core.asNonEmptySet +import arrow.core.buildNonEmptyList import arrow.core.collectionSizeOrDefault import arrow.core.getOrElse -import arrow.core.isNonEmpty import arrow.core.nel import arrow.core.raise.RaiseAccumulate.Error import arrow.core.raise.RaiseAccumulate.Ok import arrow.core.raise.RaiseAccumulate.Value import arrow.core.toNonEmptyListOrNull +import arrow.core.wrapAsNonEmptyListOrNull import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_LEAST_ONCE import kotlin.contracts.InvocationKind.AT_MOST_ONCE @@ -1126,8 +1128,16 @@ private class RaiseNel(private val accumulate: Accumulate) : Raise private class ListAccumulate(private val raise: Raise>) : Accumulate, Raise> { private val list = MonotoneMutableList() - fun raiseSingle(r: Error): Nothing = raise.raise(if (list.isNonEmpty()) list.asNonEmptyList() + r else r.nel()) - override fun raise(r: NonEmptyList) = raise.raise(if (list.isNonEmpty()) list.asNonEmptyList() + r else r) + fun raiseSingle(r: Error): Nothing = raise.raise(buildNonEmptyList(list.size + 1) { + addAll(list) + add(r) + this + }) + override fun raise(r: NonEmptyList) = raise.raise(buildNonEmptyList(list.size + r.size) { + addAll(list) + addAll(r) + this + }) @ExperimentalRaiseAccumulateApi override fun accumulateAll(errors: NonEmptyList): Value { @@ -1135,8 +1145,9 @@ private class ListAccumulate(private val raise: Raise return Error { raise.raise(list.asNonEmptyList()) } } + @OptIn(PotentiallyUnsafeNonEmptyOperation::class) @ExperimentalRaiseAccumulateApi - override val latestError: Value? get() = if (list.isNonEmpty()) Error { raise.raise(list.asNonEmptyList()) } else null + override val latestError: Value? get() = list.wrapAsNonEmptyListOrNull()?.let { Error { raise.raise(it) } } } @OptIn(ExperimentalRaiseAccumulateApi::class)