From b387e6e7e126435d8910fd77d83628bb1a2c2361 Mon Sep 17 00:00:00 2001 From: Alejandro Serrano Date: Mon, 30 Jan 2023 16:37:09 +0100 Subject: [PATCH 1/5] Implement NonEmptyList using value class --- arrow-libs/core/arrow-core/api/arrow-core.api | 134 ++++++++++------ .../kotlin/arrow/core/NonEmptyList.kt | 150 +++++++----------- .../kotlin/arrow/core/test/Generators.kt | 3 +- .../java/arrow/core/NonEmptyListUsage.java | 23 ++- 4 files changed, 163 insertions(+), 147 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index d4d232c57c8..fd21600fda9 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -515,64 +515,108 @@ public final class arrow/core/Memoization { public static final fun memoize (Lkotlin/jvm/functions/Function5;)Lkotlin/jvm/functions/Function5; } -public final class arrow/core/NonEmptyList : kotlin/collections/AbstractList { +public final class arrow/core/NonEmptyList : java/util/List, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Larrow/core/NonEmptyList$Companion; - public fun (Ljava/lang/Object;Ljava/util/List;)V - public synthetic fun (Ljava/util/List;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun align (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun coflatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; + public fun add (ILjava/lang/Object;)V + public fun add (Ljava/lang/Object;)Z + public fun addAll (ILjava/util/Collection;)Z + public fun addAll (Ljava/util/Collection;)Z + public static final fun align-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final synthetic fun box-impl (Ljava/util/List;)Larrow/core/NonEmptyList; + public fun clear ()V + public static final fun coflatMap-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static fun constructor-impl (Ljava/lang/Object;Ljava/util/List;)Ljava/util/List; + public static fun constructor-impl (Ljava/util/List;)Ljava/util/List; + public fun contains (Ljava/lang/Object;)Z + public static fun contains-impl (Ljava/util/List;Ljava/lang/Object;)Z + public fun containsAll (Ljava/util/Collection;)Z + public static fun containsAll-impl (Ljava/util/List;Ljava/util/Collection;)Z public fun equals (Ljava/lang/Object;)Z - public final fun extract ()Ljava/lang/Object; - public final fun flatMap (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public final fun foldLeft (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; + public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z + public static final fun extract-impl (Ljava/util/List;)Ljava/lang/Object; + public static final fun flatMap-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun foldLeft-impl (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; public static final fun fromList (Ljava/util/List;)Larrow/core/Option; - public static final fun fromListUnsafe (Ljava/util/List;)Larrow/core/NonEmptyList; + public static final fun fromListUnsafe (Ljava/util/List;)Ljava/util/List; public fun get (I)Ljava/lang/Object; + public static fun get-impl (Ljava/util/List;I)Ljava/lang/Object; public final fun getAll ()Ljava/util/List; - public final fun getHead ()Ljava/lang/Object; + public static final fun getHead-impl (Ljava/util/List;)Ljava/lang/Object; public fun getSize ()I - public final fun getTail ()Ljava/util/List; + public static fun getSize-impl (Ljava/util/List;)I + public static final fun getTail-impl (Ljava/util/List;)Ljava/util/List; public fun hashCode ()I + public static fun hashCode-impl (Ljava/util/List;)I + public fun indexOf (Ljava/lang/Object;)I + public static fun indexOf-impl (Ljava/util/List;Ljava/lang/Object;)I public fun isEmpty ()Z - public final fun map (Lkotlin/jvm/functions/Function1;)Larrow/core/NonEmptyList; - public final fun padZip (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun plus (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun plus (Ljava/lang/Object;)Larrow/core/NonEmptyList; - public final fun plus (Ljava/util/List;)Larrow/core/NonEmptyList; - public final fun salign (Larrow/typeclasses/Semigroup;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun toList ()Ljava/util/List; + public static fun isEmpty-impl (Ljava/util/List;)Z + public fun iterator ()Ljava/util/Iterator; + public static fun iterator-impl (Ljava/util/List;)Ljava/util/Iterator; + public fun lastIndexOf (Ljava/lang/Object;)I + public static fun lastIndexOf-impl (Ljava/util/List;Ljava/lang/Object;)I + public fun listIterator ()Ljava/util/ListIterator; + public fun listIterator (I)Ljava/util/ListIterator; + public static fun listIterator-impl (Ljava/util/List;)Ljava/util/ListIterator; + public static fun listIterator-impl (Ljava/util/List;I)Ljava/util/ListIterator; + public static final fun map-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; + public static final fun of (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; + public static final fun ofOrNull (Ljava/lang/Iterable;)Ljava/util/List; + public static final fun padZip-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final fun plus-0-xjo5U (Ljava/util/List;Ljava/lang/Object;)Ljava/util/List; + public static final fun plus-0-xjo5U (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final fun plus-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public fun remove (I)Ljava/lang/Object; + public fun remove (Ljava/lang/Object;)Z + public fun removeAll (Ljava/util/Collection;)Z + public fun replaceAll (Ljava/util/function/UnaryOperator;)V + public fun retainAll (Ljava/util/Collection;)Z + public static final fun salign-BnObD6c (Ljava/util/List;Larrow/typeclasses/Semigroup;Ljava/util/List;)Ljava/util/List; + public fun set (ILjava/lang/Object;)Ljava/lang/Object; + public synthetic fun size ()I + public fun sort (Ljava/util/Comparator;)V + public fun subList (II)Ljava/util/List; + public static fun subList-impl (Ljava/util/List;II)Ljava/util/List; + public fun toArray ()[Ljava/lang/Object; + public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object; + public static final fun toList-impl (Ljava/util/List;)Ljava/util/List; public fun toString ()Ljava/lang/String; - public final fun zip (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function10;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function9;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function8;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function7;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function6;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function5;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function4;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function3;)Larrow/core/NonEmptyList; - public final fun zip (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function2;)Larrow/core/NonEmptyList; + public static fun toString-impl (Ljava/util/List;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/util/List; + public static final fun zip-BdUWqYY (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function5;)Ljava/util/List; + public static final fun zip-EkAgaZI (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function10;)Ljava/util/List; + public static final fun zip-FrVv2gs (Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function2;)Ljava/util/List; + public static final fun zip-QNErI5A (Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function3;)Ljava/util/List; + public static final fun zip-Sy0iXXA (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function4;)Ljava/util/List; + public static final fun zip-Vwi0aTY (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function7;)Ljava/util/List; + public static final fun zip-e5uF9gA (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function6;)Ljava/util/List; + public static final fun zip-oYG1GSg (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function8;)Ljava/util/List; + public static final fun zip-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; + public static final fun zip-vi6g5TI (Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Ljava/util/List;Lkotlin/jvm/functions/Function9;)Ljava/util/List; } public final class arrow/core/NonEmptyList$Companion { public final fun fromList (Ljava/util/List;)Larrow/core/Option; - public final fun fromListUnsafe (Ljava/util/List;)Larrow/core/NonEmptyList; - public final fun getUnit ()Larrow/core/NonEmptyList; + public final fun fromListUnsafe (Ljava/util/List;)Ljava/util/List; + public final fun getUnit-1X0FA-Y ()Ljava/util/List; + public final fun of (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; + public final fun ofOrNull (Ljava/lang/Iterable;)Ljava/util/List; } public final class arrow/core/NonEmptyListKt { - public static final fun compareTo (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)I - public static final fun flatten (Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; - public static final fun max (Larrow/core/NonEmptyList;)Ljava/lang/Comparable; - public static final fun maxBy (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun min (Larrow/core/NonEmptyList;)Ljava/lang/Comparable; - public static final fun minBy (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; - public static final fun nel (Ljava/lang/Object;)Larrow/core/NonEmptyList; - public static final fun nonEmptyListOf (Ljava/lang/Object;[Ljava/lang/Object;)Larrow/core/NonEmptyList; + public static final fun 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 max-GZgkXh4 (Ljava/util/List;)Ljava/lang/Comparable; + public static final fun maxBy-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun min-GZgkXh4 (Ljava/util/List;)Ljava/lang/Comparable; + public static final fun minBy-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun nel (Ljava/lang/Object;)Ljava/util/List; + public static final fun nonEmptyListOf (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; public static final fun toNonEmptyListOrNone (Ljava/lang/Iterable;)Larrow/core/Option; - public static final fun toNonEmptyListOrNull (Ljava/lang/Iterable;)Larrow/core/NonEmptyList; - public static final fun unzip (Larrow/core/NonEmptyList;)Lkotlin/Pair; - public static final fun unzip (Larrow/core/NonEmptyList;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; + public static final fun toNonEmptyListOrNull (Ljava/lang/Iterable;)Ljava/util/List; + public static final fun unzip-GZgkXh4 (Ljava/util/List;)Lkotlin/Pair; + public static final fun unzip-ZALtuoE (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Lkotlin/Pair; } public final class arrow/core/NonFatalKt { @@ -1880,14 +1924,14 @@ public final class arrow/typeclasses/Semigroup$Companion { public final class arrow/typeclasses/Semigroup$Companion$NonEmptyListSemigroup : arrow/typeclasses/Semigroup { public static final field INSTANCE Larrow/typeclasses/Semigroup$Companion$NonEmptyListSemigroup; - public fun append (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; public synthetic fun append (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun combine (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public fun append-dcR1Ndc (Ljava/util/List;Ljava/util/List;)Ljava/util/List; public synthetic fun combine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun maybeCombine (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public fun combine-dcR1Ndc (Ljava/util/List;Ljava/util/List;)Ljava/util/List; public synthetic fun maybeCombine (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; - public fun plus (Larrow/core/NonEmptyList;Larrow/core/NonEmptyList;)Larrow/core/NonEmptyList; + public fun maybeCombine-7cP5QJY (Ljava/util/List;Ljava/util/List;)Ljava/util/List; public synthetic fun plus (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + public fun plus-dcR1Ndc (Ljava/util/List;Ljava/util/List;)Ljava/util/List; } public final class arrow/typeclasses/Semigroup$DefaultImpls { 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 4f10a35ba14..1a51bc9da0a 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/NonEmptyList.kt @@ -1,6 +1,8 @@ package arrow.core import arrow.typeclasses.Semigroup +import kotlin.jvm.JvmInline +import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic public typealias Nel = NonEmptyList @@ -144,33 +146,37 @@ public typealias Nel = NonEmptyList * - `a.zip(b, c) { ... }` can be used to compute over multiple `NonEmptyList` values preserving type information and __abstracting over arity__ with `zip` * */ -public class NonEmptyList( - public val head: A, - public val tail: List -) : AbstractList() { - - private constructor(list: List) : this(list[0], list.drop(1)) - - override val size: Int = - 1 + tail.size - +@JvmInline +public value class NonEmptyList @PublishedApi internal constructor( public val all: List - get() = toList() +) : List by all { + + public constructor(head: A, tail: List): this(listOf(head) + tail) - public override operator fun get(index: Int): A { - if (index < 0 || index >= size) throw IndexOutOfBoundsException("$index is not in 1..${size - 1}") - return if (index == 0) head else tail[index - 1] + @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") + override fun equals(other: Any?): Boolean = when (other) { + is NonEmptyList<*> -> this.all == other.all + else -> this.all == other } + @Suppress("RESERVED_MEMBER_INSIDE_VALUE_CLASS") + override fun hashCode(): Int = all.hashCode() + override fun isEmpty(): Boolean = false - public fun toList(): List = listOf(head) + tail + public fun toList(): List = all + + public val head: A + get() = all.first() + + public val tail: List + get() = all.drop(1) public inline fun map(f: (A) -> B): NonEmptyList = - NonEmptyList(f(head), tail.map(f)) + NonEmptyList(all.map(f)) public inline fun flatMap(f: (A) -> NonEmptyList): NonEmptyList = - f(head) + tail.flatMap { f(it).all } + NonEmptyList(all.flatMap { f(it).all }) public operator fun plus(l: NonEmptyList<@UnsafeVariance A>): NonEmptyList = NonEmptyList(all + l.all) @@ -182,46 +188,42 @@ public class NonEmptyList( NonEmptyList(all + a) public inline fun foldLeft(b: B, f: (B, A) -> B): B = - this.tail.fold(f(b, this.head), f) - - public fun coflatMap(f: (NonEmptyList) -> B): NonEmptyList { - val buf = mutableListOf() - tailrec fun consume(list: List): List = - if (list.isEmpty()) { - buf - } else { - val tail = list.subList(1, list.size) - buf += f(NonEmptyList(list[0], tail)) - consume(tail) + all.fold(b, f) + + public fun coflatMap(f: (NonEmptyList) -> B): NonEmptyList = + buildList { + var current = all + while (current.isNotEmpty()) { + add(f(NonEmptyList(current))) + current = current.drop(1) } - return NonEmptyList(f(this), consume(this.tail)) - } + }.let(::NonEmptyList) public fun extract(): A = this.head - override fun equals(other: Any?): Boolean = - super.equals(other) - - override fun hashCode(): Int = - super.hashCode() - override fun toString(): String = "NonEmptyList(${all.joinToString()})" public fun align(b: NonEmptyList): NonEmptyList> = - NonEmptyList(Ior.Both(head, b.head), tail.align(b.tail)) + NonEmptyList(all.align(b)) public fun salign(SA: Semigroup<@UnsafeVariance A>, b: NonEmptyList<@UnsafeVariance A>): NonEmptyList = - SA.run { - NonEmptyList(head.combine(b.head), tail.salign(SA, b.tail).toList()) - } + NonEmptyList(all.salign(SA, b).toList()) public fun padZip(other: NonEmptyList): NonEmptyList> = - NonEmptyList(head to other.head, tail.padZip(other.tail)) + NonEmptyList(all.padZip(other)) public companion object { + @JvmStatic @JvmName("of") + public fun of(first: A, vararg tail: A): NonEmptyList = + NonEmptyList(listOf(first) + tail) + + @JvmStatic @JvmName("ofOrNull") + public fun ofOrNull(list: Iterable): NonEmptyList? = + list.firstOrNull()?.let { NonEmptyList(list.toList()) } + @Deprecated( "Use toNonEmptyListOrNull instead", ReplaceWith( @@ -230,7 +232,7 @@ public class NonEmptyList( "import arrow.core.toOption" ) ) - @JvmStatic + @JvmStatic @JvmName("fromList") public fun fromList(l: List): Option> = if (l.isEmpty()) None else Some(NonEmptyList(l)) @@ -241,8 +243,8 @@ public class NonEmptyList( "import arrow.core.toNonEmptyListOrNull" ) ) - @JvmStatic - public fun fromListUnsafe(l: List): NonEmptyList = + @JvmStatic @JvmName("fromListUnsafe") + public inline fun fromListUnsafe(l: List): NonEmptyList = NonEmptyList(l) @PublishedApi @@ -257,20 +259,14 @@ public class NonEmptyList( b: NonEmptyList, map: (A, B) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head), - tail.zip(b.tail, map) - ) + NonEmptyList(all.zip(b.all, map)) public inline fun zip( b: NonEmptyList, c: NonEmptyList, map: (A, B, C) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head), - tail.zip(b.tail, c.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, map)) public inline fun zip( b: NonEmptyList, @@ -278,10 +274,7 @@ public class NonEmptyList( d: NonEmptyList, map: (A, B, C, D) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head), - tail.zip(b.tail, c.tail, d.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, map)) public inline fun zip( b: NonEmptyList, @@ -290,10 +283,7 @@ public class NonEmptyList( e: NonEmptyList, map: (A, B, C, D, E) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, map)) public inline fun zip( b: NonEmptyList, @@ -303,10 +293,7 @@ public class NonEmptyList( f: NonEmptyList, map: (A, B, C, D, E, F) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, map)) public inline fun zip( b: NonEmptyList, @@ -317,10 +304,7 @@ public class NonEmptyList( g: NonEmptyList, map: (A, B, C, D, E, F, G) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, map)) public inline fun zip( b: NonEmptyList, @@ -332,10 +316,7 @@ public class NonEmptyList( h: NonEmptyList, map: (A, B, C, D, E, F, G, H) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, map)) public inline fun zip( b: NonEmptyList, @@ -348,10 +329,7 @@ public class NonEmptyList( i: NonEmptyList, map: (A, B, C, D, E, F, G, H, I) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head, i.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, i.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, map)) public inline fun zip( b: NonEmptyList, @@ -365,17 +343,16 @@ public class NonEmptyList( j: NonEmptyList, map: (A, B, C, D, E, F, G, H, I, J) -> Z ): NonEmptyList = - NonEmptyList( - map(head, b.head, c.head, d.head, e.head, f.head, g.head, h.head, i.head, j.head), - tail.zip(b.tail, c.tail, d.tail, e.tail, f.tail, g.tail, h.tail, i.tail, j.tail, map) - ) + NonEmptyList(all.zip(b.all, c.all, d.all, e.all, f.all, g.all, h.all, i.all, j.all, map)) } +@JvmName("nonEmptyListOf") public fun nonEmptyListOf(head: A, vararg t: A): NonEmptyList = - NonEmptyList(head, t.asList()) + NonEmptyList(listOf(head) + t) +@JvmName("nel") public inline fun A.nel(): NonEmptyList = - nonEmptyListOf(this) + NonEmptyList(listOf(this)) public operator fun > NonEmptyList.compareTo(other: NonEmptyList): Int = all.compareTo(other.all) @@ -399,15 +376,10 @@ public fun NonEmptyList>.unzip(): Pair, NonEmp this.unzip(::identity) public fun NonEmptyList.unzip(f: (C) -> Pair): Pair, NonEmptyList> = - this.map(f).let { nel -> - nel.tail.unzip().let { - NonEmptyList(nel.head.first, it.first) to - NonEmptyList(nel.head.second, it.second) - } - } + all.unzip(f).let { (a, b) -> NonEmptyList(a) to NonEmptyList(b) } public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = - firstOrNull()?.let { NonEmptyList(it, drop(1)) } + NonEmptyList.ofOrNull(this) public fun Iterable.toNonEmptyListOrNone(): Option> = toNonEmptyListOrNull().toOption() 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 c424bd291cc..51a3eabacc2 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 @@ -21,6 +21,7 @@ import io.kotest.property.arbitrary.of import io.kotest.property.arbitrary.orNull import io.kotest.property.arbitrary.string import kotlinx.coroutines.Dispatchers +import kotlin.math.max import kotlin.Result.Companion.failure import kotlin.Result.Companion.success import kotlin.coroutines.Continuation @@ -32,7 +33,7 @@ import kotlin.coroutines.startCoroutine // copied from kotest-extensions-arrow fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.bind(arb, Arb.list(arb, range), ::NonEmptyList) + Arb.list(arb, max(range.first, 1) .. range.last).map { NonEmptyList(it) } fun Arb.Companion.sequence(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, range).map { it.asSequence() } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java index af0382a41c9..69a6ffd959f 100644 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java +++ b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java @@ -1,23 +1,22 @@ package arrow.core; import java.util.Arrays; - -import static arrow.core.NonEmptyListKt.*; +import java.util.List; public class NonEmptyListUsage { public void testUsage() { - NonEmptyList integers = nonEmptyListOf(1, 2, 3, 4, 5); - int i = compareTo( - nonEmptyListOf(1, 2, 3, 4, 5), - nonEmptyListOf(1, 2, 3, 4, 5) + // from the Java side, we just have List + List integers = NonEmptyList.of(1, 2, 3, 4, 5); + int i = IterableKt.compareTo( + NonEmptyList.of(1, 2, 3, 4, 5), + NonEmptyList.of(1, 2, 3, 4, 5) ); - NonEmptyList flatten = flatten(nonEmptyListOf( - nonEmptyListOf(1, 2), - nonEmptyListOf(3, 4) - )); + // List flatten = flatten(nonEmptyListOf( + // nonEmptyListOf(1, 2), + // nonEmptyListOf(3, 4) + // )); Option> nonEmptyListOption = NonEmptyList.fromList(Arrays.asList(1, 2, 3)); - NonEmptyList integers1 = NonEmptyList.fromListUnsafe(Arrays.asList(1, 2, 3)); - NonEmptyList integers2 = NonEmptyListKt.toNonEmptyListOrNull(Arrays.asList(1, 2, 3)); + List integers2 = NonEmptyList.ofOrNull(Arrays.asList(1, 2, 3)); } } From 1f8ed01427069f6b44938ee10f8632c94ae0d8c2 Mon Sep 17 00:00:00 2001 From: serras Date: Mon, 30 Jan 2023 15:45:49 +0000 Subject: [PATCH 2/5] Update API files --- arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api b/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api index 42f2a8fbdb0..0532df7e698 100644 --- a/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api +++ b/arrow-libs/fx/arrow-fx-coroutines/api/arrow-fx-coroutines.api @@ -235,12 +235,12 @@ public final class arrow/fx/coroutines/ParZipKt { public final class arrow/fx/coroutines/Platform { public static final field INSTANCE Larrow/fx/coroutines/Platform; - public final fun composeErrors (Larrow/core/NonEmptyList;)Ljava/lang/Throwable; public final fun composeErrors (Ljava/lang/Throwable;Ljava/lang/Object;)Ljava/lang/Throwable; public final fun composeErrors (Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable; public final fun composeErrors (Ljava/lang/Throwable;Ljava/util/List;)Ljava/lang/Throwable; public final fun composeErrors (Ljava/lang/Throwable;[Ljava/lang/Throwable;)Ljava/lang/Throwable; public final fun composeErrors (Ljava/util/List;)Ljava/lang/Throwable; + public final fun composeErrors-GZgkXh4 (Ljava/util/List;)Ljava/lang/Throwable; public final fun composeErrorsNullable (Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable; } From ece9c1bd8acc38ad92b49af843bb80c2ca9c31c7 Mon Sep 17 00:00:00 2001 From: Alejandro Serrano Date: Mon, 30 Jan 2023 21:01:17 +0100 Subject: [PATCH 3/5] Fix generator for NonEmptyList in optics --- .../src/commonTest/kotlin/arrow/optics/test/Generators.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt index 1f66bd4a5cb..0d3ddd5ed4e 100644 --- a/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt +++ b/arrow-libs/optics/arrow-optics/src/commonTest/kotlin/arrow/optics/test/Generators.kt @@ -9,6 +9,7 @@ import arrow.core.Tuple6 import arrow.core.Tuple7 import arrow.core.Tuple8 import arrow.core.Tuple9 +import arrow.core.toNonEmptyListOrNull import arrow.core.toOption import io.kotest.property.Arb import io.kotest.property.arbitrary.bind @@ -16,9 +17,10 @@ import io.kotest.property.arbitrary.choice import io.kotest.property.arbitrary.list import io.kotest.property.arbitrary.map import io.kotest.property.arbitrary.orNull +import kotlin.math.max fun Arb.Companion.nonEmptyList(arb: Arb, range: IntRange = 0 .. 100): Arb> = - Arb.bind(arb, Arb.list(arb, range), ::NonEmptyList) + Arb.list(arb, max(range.first, 1) .. range.last).map { it.toNonEmptyListOrNull()!! } fun Arb.Companion.sequence(arb: Arb, range: IntRange = 0 .. 100): Arb> = Arb.list(arb, range).map { it.asSequence() } From 96b7f9377ec2a402df2ae5e0b09e8d030d6fd288 Mon Sep 17 00:00:00 2001 From: Alejandro Serrano Date: Thu, 2 Feb 2023 21:15:54 +0100 Subject: [PATCH 4/5] Apply suggestions --- .../kotlin/arrow/core/NonEmptyList.kt | 36 ++----------------- .../arrow/core/continuations/EffectSpec.kt | 3 +- .../java/arrow/core/NonEmptyListUsage.java | 22 ------------ 3 files changed, 5 insertions(+), 56 deletions(-) delete mode 100644 arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java 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 1a51bc9da0a..41d53dad7d3 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 @@ -215,38 +215,6 @@ public value class NonEmptyList @PublishedApi internal constructor( NonEmptyList(all.padZip(other)) public companion object { - - @JvmStatic @JvmName("of") - public fun of(first: A, vararg tail: A): NonEmptyList = - NonEmptyList(listOf(first) + tail) - - @JvmStatic @JvmName("ofOrNull") - public fun ofOrNull(list: Iterable): NonEmptyList? = - list.firstOrNull()?.let { NonEmptyList(list.toList()) } - - @Deprecated( - "Use toNonEmptyListOrNull instead", - ReplaceWith( - "l.toNonEmptyListOrNull().toOption()", - "import arrow.core.toNonEmptyListOrNull", - "import arrow.core.toOption" - ) - ) - @JvmStatic @JvmName("fromList") - public fun fromList(l: List): Option> = - if (l.isEmpty()) None else Some(NonEmptyList(l)) - - @Deprecated( - "Use toNonEmptyListOrNull instead", - ReplaceWith( - "l.toNonEmptyListOrNull() ?: throw IndexOutOfBoundsException(\"Empty list doesn't contain element at index 0.\")", - "import arrow.core.toNonEmptyListOrNull" - ) - ) - @JvmStatic @JvmName("fromListUnsafe") - public inline fun fromListUnsafe(l: List): NonEmptyList = - NonEmptyList(l) - @PublishedApi internal val unit: NonEmptyList = nonEmptyListOf(Unit) @@ -378,8 +346,10 @@ public fun NonEmptyList>.unzip(): Pair, NonEmp public fun NonEmptyList.unzip(f: (C) -> Pair): Pair, NonEmptyList> = all.unzip(f).let { (a, b) -> NonEmptyList(a) to NonEmptyList(b) } +@JvmName("toNonEmptyListOrNull") public fun Iterable.toNonEmptyListOrNull(): NonEmptyList? = - NonEmptyList.ofOrNull(this) + toList().let { if (it.isEmpty()) null else NonEmptyList(it) } +@JvmName("toNonEmptyListOrNone") public fun Iterable.toNonEmptyListOrNone(): Option> = toNonEmptyListOrNull().toOption() diff --git a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt index 1473e0617d7..becaaaa0f48 100644 --- a/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt +++ b/arrow-libs/core/arrow-core/src/commonTest/kotlin/arrow/core/continuations/EffectSpec.kt @@ -5,6 +5,7 @@ import arrow.core.NonEmptyList import arrow.core.identity import arrow.core.left import arrow.core.right +import arrow.core.toNonEmptyListOrNull import io.kotest.assertions.fail import io.kotest.assertions.throwables.shouldThrow import io.kotest.core.spec.style.StringSpec @@ -378,7 +379,7 @@ class EffectSpec : checkAll(Arb.list(Arb.int(), range = 2 .. 100)) { errors -> either, List> { mapOrAccumulate(errors) { raise(it) } - } shouldBe NonEmptyList.fromListUnsafe(errors).left() + } shouldBe errors.toNonEmptyListOrNull()!!.left() } } diff --git a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java b/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java deleted file mode 100644 index 69a6ffd959f..00000000000 --- a/arrow-libs/core/arrow-core/src/jvmTest/java/arrow/core/NonEmptyListUsage.java +++ /dev/null @@ -1,22 +0,0 @@ -package arrow.core; - -import java.util.Arrays; -import java.util.List; - -public class NonEmptyListUsage { - - public void testUsage() { - // from the Java side, we just have List - List integers = NonEmptyList.of(1, 2, 3, 4, 5); - int i = IterableKt.compareTo( - NonEmptyList.of(1, 2, 3, 4, 5), - NonEmptyList.of(1, 2, 3, 4, 5) - ); - // List flatten = flatten(nonEmptyListOf( - // nonEmptyListOf(1, 2), - // nonEmptyListOf(3, 4) - // )); - Option> nonEmptyListOption = NonEmptyList.fromList(Arrays.asList(1, 2, 3)); - List integers2 = NonEmptyList.ofOrNull(Arrays.asList(1, 2, 3)); - } -} From a196e0871a0c5da625c2bdd59d57622740ed8235 Mon Sep 17 00:00:00 2001 From: serras Date: Thu, 2 Feb 2023 20:21:05 +0000 Subject: [PATCH 5/5] Update API files --- arrow-libs/core/arrow-core/api/arrow-core.api | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index fd21600fda9..39b3944e9fa 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -537,8 +537,6 @@ public final class arrow/core/NonEmptyList : java/util/List, kotlin/jvm/internal public static final fun extract-impl (Ljava/util/List;)Ljava/lang/Object; public static final fun flatMap-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; public static final fun foldLeft-impl (Ljava/util/List;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)Ljava/lang/Object; - public static final fun fromList (Ljava/util/List;)Larrow/core/Option; - public static final fun fromListUnsafe (Ljava/util/List;)Ljava/util/List; public fun get (I)Ljava/lang/Object; public static fun get-impl (Ljava/util/List;I)Ljava/lang/Object; public final fun getAll ()Ljava/util/List; @@ -561,8 +559,6 @@ public final class arrow/core/NonEmptyList : java/util/List, kotlin/jvm/internal public static fun listIterator-impl (Ljava/util/List;)Ljava/util/ListIterator; public static fun listIterator-impl (Ljava/util/List;I)Ljava/util/ListIterator; public static final fun map-0-xjo5U (Ljava/util/List;Lkotlin/jvm/functions/Function1;)Ljava/util/List; - public static final fun of (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; - public static final fun ofOrNull (Ljava/lang/Iterable;)Ljava/util/List; public static final fun padZip-vcjLgH4 (Ljava/util/List;Ljava/util/List;)Ljava/util/List; public static final fun plus-0-xjo5U (Ljava/util/List;Ljava/lang/Object;)Ljava/util/List; public static final fun plus-0-xjo5U (Ljava/util/List;Ljava/util/List;)Ljava/util/List; @@ -597,11 +593,7 @@ public final class arrow/core/NonEmptyList : java/util/List, kotlin/jvm/internal } public final class arrow/core/NonEmptyList$Companion { - public final fun fromList (Ljava/util/List;)Larrow/core/Option; - public final fun fromListUnsafe (Ljava/util/List;)Ljava/util/List; public final fun getUnit-1X0FA-Y ()Ljava/util/List; - public final fun of (Ljava/lang/Object;[Ljava/lang/Object;)Ljava/util/List; - public final fun ofOrNull (Ljava/lang/Iterable;)Ljava/util/List; } public final class arrow/core/NonEmptyListKt {