diff --git a/arrow-libs/core/arrow-core/api/arrow-core.api b/arrow-libs/core/arrow-core/api/arrow-core.api index 20eb0450c2a..61f73eee264 100644 --- a/arrow-libs/core/arrow-core/api/arrow-core.api +++ b/arrow-libs/core/arrow-core/api/arrow-core.api @@ -187,6 +187,8 @@ public abstract class arrow/core/Either { public final fun swap ()Larrow/core/Either; public final fun tap (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public final fun tapLeft (Lkotlin/jvm/functions/Function1;)Larrow/core/Either; + public final fun toEither ()Larrow/core/Either; + public final fun toIor ()Larrow/core/Ior; public fun toString ()Ljava/lang/String; public final fun toValidated ()Larrow/core/Validated; public final fun toValidatedNel ()Larrow/core/Validated; @@ -297,6 +299,7 @@ public final class arrow/core/EitherKt { public static final fun handleErrorWith (Larrow/core/Either;Lkotlin/jvm/functions/Function1;)Larrow/core/Either; public static final fun left (Ljava/lang/Object;)Larrow/core/Either; public static final fun leftIfNull (Larrow/core/Either;Lkotlin/jvm/functions/Function0;)Larrow/core/Either; + public static final fun leftNel (Ljava/lang/Object;)Larrow/core/Either; public static final fun leftWiden (Larrow/core/Either;)Larrow/core/Either; public static final fun merge (Larrow/core/Either;)Ljava/lang/Object; public static final fun orNull (Larrow/core/Either;)Ljava/lang/Object; @@ -315,7 +318,6 @@ public final class arrow/core/EitherKt { public static final fun sequenceOption (Larrow/core/Either;)Larrow/core/Option; public static final fun sequenceValidated (Larrow/core/Either;)Larrow/core/Validated; public static final fun toEitherNel (Larrow/core/Either;)Larrow/core/Either; - public static final fun toEitherNel (Ljava/lang/Object;)Larrow/core/Either; public static final fun widen (Larrow/core/Either;)Larrow/core/Either; public static final fun zip (Larrow/core/Either;Larrow/core/Either;)Larrow/core/Either; public static final fun zip (Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Larrow/core/Either;Lkotlin/jvm/functions/Function10;)Larrow/core/Either; diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt index ec972404117..da7330c28d3 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Either.kt @@ -921,10 +921,10 @@ public sealed class Either { @Deprecated( NicheAPI + "Prefer when or fold instead", - ReplaceWith("MN.run { fold({ MN.empty().combine(f(it)) }, { MN.empty().combine(g(it)) }) }") + ReplaceWith("MN.run { fold({ empty().combine(f(it)) }, { empty().combine(g(it)) }) }") ) public inline fun bifoldMap(MN: Monoid, f: (A) -> C, g: (B) -> C): C = - MN.run { fold({ MN.empty().combine(f(it)) }, { MN.empty().combine(g(it)) }) } + MN.run { fold({ empty().combine(f(it)) }, { empty().combine(g(it)) }) } /** * Swap the generic parameters [A] and [B] of this [Either]. @@ -1138,6 +1138,10 @@ public sealed class Either { return getOrElse { null } } + @Deprecated( + "orNone is being renamed to getOrNone to be more consistent with the Kotlin Standard Library naming", + ReplaceWith("getOrNone()") + ) public fun orNone(): Option = getOrNone() /** @@ -1197,14 +1201,14 @@ public sealed class Either { public inline fun traverseNullable(fa: (B) -> C?): Either? = orNull()?.let(fa)?.right() - // TODO will be renamed to mapAccumulating in 2.x.x. Backport, and deprecate in 1.x.x + @Deprecated( + NicheAPI + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith("fold({ it.left().valid() }, { fa(it).map(::Right) })") + ) @OptIn(ExperimentalTypeInference::class) @OverloadResolutionByLambdaReturnType public inline fun traverse(fa: (B) -> Validated): Validated> = - when (this) { - is Right -> fa(this.value).map(::Right) - is Left -> this.valid() - } + fold({ it.left().valid() }, { fa(it).map(::Right) }) @Deprecated("traverseValidated is being renamed to traverse to simplify the Arrow API", ReplaceWith("traverse(fa)")) public inline fun traverseValidated(fa: (B) -> Validated): Validated> = @@ -1333,6 +1337,9 @@ public sealed class Either { public fun toValidated(): Validated = fold({ it.invalid() }, { it.valid() }) + public fun toIor(): Ior = + fold({ Ior.Left(it) }, { Ior.Right(it) }) + public companion object { @Deprecated( @@ -1944,6 +1951,13 @@ public sealed class Either { ) public fun void(): Either = map { } + + @Deprecated( + "Facilitates the migration from Validated to Either, you can simply remove this method call.", + ReplaceWith("this") + ) + public inline fun toEither(): Either = + this } /** @@ -2596,7 +2610,7 @@ public const val RedundantAPI: String = public fun Either.toEitherNel(): EitherNel = mapLeft { nonEmptyListOf(it) } -public fun E.toEitherNel(): EitherNel = +public fun E.leftNel(): EitherNel = nonEmptyListOf(this).left() /** diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt index cf668335f19..10560efc2c0 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/Validated.kt @@ -8,23 +8,47 @@ import kotlin.experimental.ExperimentalTypeInference import kotlin.jvm.JvmName import kotlin.jvm.JvmStatic +@Deprecated( + DeprMsg + "ValidatedNel is being replaced by EitherNel", + ReplaceWith("EitherNel", "arrow.core.EitherNel") +) public typealias ValidatedNel = Validated, A> + +@Deprecated( + DeprMsg + "Use Right to construct Either values instead", + ReplaceWith("Either.Right(value)", "arrow.core.Either") +) public typealias Valid = Validated.Valid + +@Deprecated( + DeprMsg + "Use Left to construct Either values instead", + ReplaceWith("Either.Left(value)", "arrow.core.Either") +) public typealias Invalid = Validated.Invalid +@Deprecated(DeprMsg + "You can find more details about how to migrate on the Github release page, or the 1.2.0 release post.") public sealed class Validated { public companion object { + @Deprecated( + DeprMsg + "Use leftNel instead to construct the equivalent Either value", + ReplaceWith("e.leftNel()", "arrow.core.leftNel") + ) @JvmStatic public fun invalidNel(e: E): ValidatedNel = Invalid(nonEmptyListOf(e)) + @Deprecated( + DeprMsg + "Use right instead to construct the equivalent Either value", + ReplaceWith("a.right()", "arrow.core.right") + ) @JvmStatic public fun validNel(a: A): ValidatedNel = Valid(a) /** * Converts an `Either` to a `Validated`. */ + @Deprecated(DeprMsg) @JvmStatic public fun fromEither(e: Either): Validated = e.fold({ Invalid(it) }, { Valid(it) }) @@ -32,6 +56,10 @@ public sealed class Validated { * Converts an `Option` to a `Validated`, where the provided `ifNone` output value is returned as [Invalid] * when the specified `Option` is `None`. */ + @Deprecated( + DeprAndNicheMsg + "Prefer using toEither on Option instead", + ReplaceWith("o.toEither(ifNone).toValidated()") + ) @JvmStatic public inline fun fromOption(o: Option, ifNone: () -> E): Validated = o.fold( @@ -43,10 +71,18 @@ public sealed class Validated { * Converts a nullable `A?` to a `Validated`, where the provided `ifNull` output value is returned as [Invalid] * when the specified value is null. */ + @Deprecated( + DeprAndNicheMsg + "Prefer Kotlin nullable syntax, or ensureNotNull inside Either DSL", + ReplaceWith("value?.valid() ?: ifNull().invalid()") + ) @JvmStatic public inline fun fromNullable(value: A?, ifNull: () -> E): Validated = value?.let(::Valid) ?: Invalid(ifNull()) + @Deprecated( + DeprMsg + "Use Either.catch instead", + ReplaceWith("Either.catch(f).toValidated()") + ) @JvmStatic @JvmName("tryCatch") public inline fun catch(f: () -> A): Validated = @@ -56,11 +92,19 @@ public sealed class Validated { e.nonFatalOrThrow().invalid() } + @Deprecated( + DeprAndNicheMsg + "Use Either.catch and mapLeft instead", + ReplaceWith("Either.catch(f).mapLeft(recover).toValidated()") + ) @JvmStatic @JvmName("tryCatch") public inline fun catch(recover: (Throwable) -> E, f: () -> A): Validated = catch(f).mapLeft(recover) + @Deprecated( + DeprAndNicheMsg + "Use Either.catch and toEitherNel instead", + ReplaceWith("Either.catch(f).toEitherNel().toValidated()") + ) @JvmStatic public inline fun catchNel(f: () -> A): ValidatedNel = try { @@ -69,6 +113,10 @@ public sealed class Validated { e.nonFatalOrThrow().invalidNel() } + @Deprecated( + DeprAndNicheMsg + "Prefer creating explicit lambdas instead", + ReplaceWith("{ it.map(f) }") + ) @JvmStatic public inline fun lift(crossinline f: (A) -> B): (Validated) -> Validated = { fa -> fa.map(f) } @@ -91,6 +139,10 @@ public sealed class Validated { * ``` * */ + @Deprecated( + DeprAndNicheMsg + "Prefer creating explicit lambdas instead", + ReplaceWith("{ it.bimap(fl, fr) }") + ) @JvmStatic public inline fun lift( crossinline fl: (A) -> C, @@ -116,14 +168,32 @@ public sealed class Validated { * ``` * */ + @Deprecated( + DeprAndNicheMsg + "Use map on Either after refactoring instead", + ReplaceWith("toEither().map { }.toValidated()") + ) public fun void(): Validated = map { Unit } + @Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ emptyList() }, { fa(it).map(::Valid) })", + "arrow.core.Valid" + ) + ) @OptIn(ExperimentalTypeInference::class) @OverloadResolutionByLambdaReturnType public inline fun traverse(fa: (A) -> Iterable): List> = fold({ emptyList() }, { a -> fa(a).map { Valid(it) } }) + @Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ it.invalid().right() }, { fa(it).map(::Valid) })", + "arrow.core.invalid", "arrow.core.right", "arrow.core.Valid" + ) + ) @OptIn(ExperimentalTypeInference::class) @OverloadResolutionByLambdaReturnType public inline fun traverse(fa: (A) -> Either): Either> = @@ -136,6 +206,13 @@ public sealed class Validated { public inline fun traverseEither(fa: (A) -> Either): Either> = traverse(fa) + @Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ None }, { fa(it).map(::Valid) })", + "arrow.core.None", "arrow.core.Valid" + ) + ) @OptIn(ExperimentalTypeInference::class) @OverloadResolutionByLambdaReturnType public inline fun traverse(fa: (A) -> Option): Option> = @@ -148,12 +225,20 @@ public sealed class Validated { public inline fun traverseOption(fa: (A) -> Option): Option> = traverse(fa) + @Deprecated( + DeprAndNicheMsg + "Use orNull() and Kotlin nullable types", + ReplaceWith("orNull()?.let(fa)?.valid()", "arrow.core.valid") + ) public inline fun traverseNullable(fa: (A) -> B?): Validated? = when (this) { is Valid -> fa(this.value)?.let { Valid(it) } is Invalid -> null } + @Deprecated( + DeprAndNicheMsg + "Prefer when or fold instead", + ReplaceWith("fold({ fe(c, it) }, { fa(c, it) })") + ) public inline fun bifoldLeft( c: B, fe: (B, E) -> B, @@ -161,31 +246,67 @@ public sealed class Validated { ): B = fold({ fe(c, it) }, { fa(c, it) }) - public inline fun bifoldMap(MN: Monoid, g: (E) -> B, f: (A) -> B): B = MN.run { + @Deprecated( + DeprAndNicheMsg + "Prefer when or fold instead", + ReplaceWith("MN.run { fold({ empty().combine(g(it)) }, { empty().combine(f(it)) }) }") + ) + public inline fun bifoldMap(MN: Monoid, g: (E) -> B, f: (A) -> B): B = MN.run { bifoldLeft(MN.empty(), { c, b -> c.combine(g(b)) }) { c, a -> c.combine(f(a)) } } + @Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } })", + "arrow.core.Valid", "arrow.core.Invalid" + ) + ) public inline fun bitraverse(fe: (E) -> Iterable, fa: (A) -> Iterable): List> = fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } }) + @Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } })", + "arrow.core.Valid", "arrow.core.Invalid" + ) + ) public inline fun bitraverseEither( fe: (E) -> Either, fa: (A) -> Either ): Either> = fold({ fe(it).map { Invalid(it) } }, { fa(it).map { Valid(it) } }) + @Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ fe(it).map(::Invalid) }, { fa(it).map(::Valid) })", + "arrow.core.Valid", "arrow.core.Invalid" + ) + ) public inline fun bitraverseOption( fe: (E) -> Option, fa: (A) -> Option ): Option> = fold({ fe(it).map(::Invalid) }, { fa(it).map(::Valid) }) + @Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ fe(it)?.let(::Invalid) }, { fa(it)?.let(::Valid) })", + "arrow.core.Valid", "arrow.core.Invalid" + ) + ) public inline fun bitraverseNullable( fe: (E) -> B?, fa: (A) -> C? ): Validated? = fold({ fe(it)?.let(::Invalid) }, { fa(it)?.let(::Valid) }) + @Deprecated( + DeprMsg + "Use fold on Either after refactoring instead", + ReplaceWith("toEither().fold({ MB.empty() }, f)") + ) public inline fun foldMap(MB: Monoid, f: (A) -> B): B = fold({ MB.empty() }, f) @@ -194,6 +315,10 @@ public sealed class Validated { { "Validated.Valid($it)" } ) + @Deprecated( + DeprMsg + "Use Right to construct Either values instead", + ReplaceWith("Either.Right(value)", "arrow.core.Either") + ) public data class Valid(val value: A) : Validated() { override fun toString(): String = "Validated.Valid($value)" @@ -204,38 +329,75 @@ public sealed class Validated { } } + @Deprecated( + DeprMsg + "Use Left to construct Either values instead", + ReplaceWith("Either.Left(value)", "arrow.core.Either") + ) public data class Invalid(val value: E) : Validated() { override fun toString(): String = "Validated.Invalid($value)" } + @Deprecated( + DeprMsg + "Use fold on Either after refactoring", + ReplaceWith("toEither().fold(fe, fa)") + ) public inline fun fold(fe: (E) -> B, fa: (A) -> B): B = when (this) { is Valid -> fa(value) is Invalid -> (fe(value)) } + @Deprecated( + DeprMsg + "Use isRight on Either after refactoring", + ReplaceWith("toEither().isRight()") + ) public val isValid: Boolean = fold({ false }, { true }) + + @Deprecated( + DeprMsg + "Use isLeft on Either after refactoring", + ReplaceWith("toEither().isLeft()") + ) public val isInvalid: Boolean = fold({ true }, { false }) /** * Is this Valid and matching the given predicate */ + @Deprecated( + DeprMsg + "Use isRight on Either after refactoring", + ReplaceWith("toEither().isRight(predicate)") + ) public inline fun exist(predicate: (A) -> Boolean): Boolean = fold({ false }, predicate) + @Deprecated( + DeprAndNicheMsg + "Use getOrNull and takeIf on Either after refactoring", + ReplaceWith("toEither().getOrNull()?.takeIf(predicate)") + ) public inline fun findOrNull(predicate: (A) -> Boolean): A? = when (this) { is Valid -> if (predicate(this.value)) this.value else null is Invalid -> null } + @Deprecated( + DeprAndNicheMsg + "Use fold on Either after refactoring", + ReplaceWith("toEither().fold({ true }, predicate)") + ) public inline fun all(predicate: (A) -> Boolean): Boolean = fold({ true }, predicate) + @Deprecated( + DeprMsg + "Use isRight on Either after refactoring", + ReplaceWith("toEither().isLeft()") + ) public fun isEmpty(): Boolean = isInvalid + @Deprecated( + DeprMsg + "Use isRight on Either after refactoring", + ReplaceWith("toEither().isRight()") + ) public fun isNotEmpty(): Boolean = isValid /** @@ -247,6 +409,10 @@ public sealed class Validated { /** * Returns Valid values wrapped in Some, and None for Invalid values */ + @Deprecated( + DeprMsg + "Use getOrNone on Either after refactoring", + ReplaceWith("toEither().getOrNone()") + ) public fun toOption(): Option = fold({ None }, ::Some) @@ -254,10 +420,18 @@ public sealed class Validated { * Convert this value to a single element List if it is Valid, * otherwise return an empty List */ + @Deprecated( + DeprAndNicheMsg + "Use fold instead", + ReplaceWith("fold({ emptyList() }, ::listOf)") + ) public fun toList(): List = fold({ listOf() }, ::listOf) /** Lift the Invalid value into a NonEmptyList. */ + @Deprecated( + DeprMsg + "Use toEitherNel directly instead", + ReplaceWith("toEither().toEitherNel().toValidated()") + ) public fun toValidatedNel(): ValidatedNel = fold({ invalidNel(it) }, ::Valid) @@ -265,6 +439,10 @@ public sealed class Validated { * Convert to an Either, apply a function, convert back. This is handy * when you want to use the Monadic properties of the Either type. */ + @Deprecated( + DeprMsg + "Use Either directly instead", + ReplaceWith("toEither().let(f).toValidated()") + ) public inline fun withEither(f: (Either) -> Either): Validated = fromEither(f(toEither())) @@ -279,6 +457,10 @@ public sealed class Validated { /** * Apply a function to a Valid value, returning a new Valid value */ + @Deprecated( + DeprMsg + "Use map on Either after refactoring", + ReplaceWith("toEither().map(f).toValidated()") + ) public inline fun map(f: (A) -> B): Validated = bimap(::identity, f) @@ -286,6 +468,10 @@ public sealed class Validated { * Apply a function to an Invalid value, returning a new Invalid value. * Or, if the original valid was Valid, return it. */ + @Deprecated( + DeprMsg + "Use mapLeft on Either after refactoring", + ReplaceWith("toEither().mapLeft(f).toValidated()") + ) public inline fun mapLeft(f: (E) -> EE): Validated = bimap(f, ::identity) @@ -306,6 +492,10 @@ public sealed class Validated { * ``` * */ + @Deprecated( + DeprMsg + "Use onLeft on Either after refactoring", + ReplaceWith("toEither().onLeft(f).toValidated()") + ) public inline fun tapInvalid(f: (E) -> Unit): Validated = when (this) { is Invalid -> { @@ -332,6 +522,10 @@ public sealed class Validated { * ``` * */ + @Deprecated( + DeprMsg + "Use onRight on Either after refactoring", + ReplaceWith("toEither().onRight(f).toValidated()") + ) public inline fun tap(f: (A) -> Unit): Validated = when (this) { is Invalid -> this @@ -345,16 +539,38 @@ public sealed class Validated { * apply the given function to the value with the given B when * valid, otherwise return the given B */ + @Deprecated( + DeprMsg + "Use fold on Either after refactoring", + ReplaceWith("toEither().fold({ b }) { f(b, it) }") + ) public inline fun foldLeft(b: B, f: (B, A) -> B): B = fold({ b }, { f(b, it) }) + @Deprecated( + DeprMsg + "Use swap on Either after refactoring", + ReplaceWith("toEither().swap()") + ) public fun swap(): Validated = fold(::Valid, ::Invalid) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), fb.toEither(), ::Pair).toValidated()", + "arrow.core.Either" + ) +) public fun Validated.zip(SE: Semigroup, fb: Validated): Validated> = zip(SE, fb, ::Pair) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -375,6 +591,13 @@ public inline fun Validated.zip( f(a, b) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -396,6 +619,13 @@ public inline fun Validated.zip( f(a, b, c) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -418,6 +648,13 @@ public inline fun Validated.zip( f(a, b, c, d) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -441,6 +678,13 @@ public inline fun Validated.zip( f(a, b, c, d, e) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -465,6 +709,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -479,6 +730,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -494,6 +752,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g, h) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -510,6 +775,13 @@ public inline fun Validated.zip( f(a, b, c, d, e, ff, g, h, i) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate({ a, b -> SE.run, E> { a.combine(b) } }, toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), j.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun Validated.zip( SE: Semigroup, b: Validated, @@ -551,12 +823,26 @@ public inline fun Validated.zip( Validated.Invalid(accumulatedError as E) } +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, f: (A, B) -> Z ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -564,6 +850,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -572,6 +865,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -581,6 +881,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, e, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -591,6 +898,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, e, ff, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -602,6 +916,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -614,6 +935,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, h, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -627,6 +955,13 @@ public inline fun ValidatedNel.zip( ): ValidatedNel = zip(Semigroup.nonEmptyList(), b, c, d, e, ff, g, h, i, f) +@Deprecated( + DeprMsg + "zipOrAccumulate for Either now exposes this same functionality", + ReplaceWith( + "Either.zipOrAccumulate(toEither(), b.toEither(), c.toEither(), d.toEither(), e.toEither(), ff.toEither(), g.toEither(), h.toEither(), i.toEither(), j.toEither(), f).toValidated()", + "arrow.core.Either" + ) +) public inline fun ValidatedNel.zip( b: ValidatedNel, c: ValidatedNel, @@ -658,32 +993,77 @@ public inline fun ValidatedNel.zip( * ``` * */ +@Deprecated( + DeprMsg + "Use widen on Either after refactoring", + ReplaceWith("toEither().widen()") +) public fun Validated.widen(): Validated = this +@Deprecated( + DeprMsg + "Use leftWiden on Either after refactoring", + ReplaceWith("toEither().leftWiden()") +) public fun Validated.leftWiden(): Validated = this +@Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or map", + ReplaceWith("(0 until (n.coerceAtLeast(0))).mapOrAccumulate({ a, b -> SE.run { a.combine(b) } }) { bind() }.toValidated()") +) public fun Validated.replicate(SE: Semigroup, n: Int): Validated> = if (n <= 0) emptyList().valid() else this.zip(SE, replicate(SE, n - 1)) { a, xs -> listOf(a) + xs } +@Deprecated(DeprAndNicheMsg) public fun Validated.replicate(SE: Semigroup, n: Int, MA: Monoid): Validated = if (n <= 0) MA.empty().valid() else this@replicate.zip(SE, replicate(SE, n - 1, MA)) { a, xs -> MA.run { a + xs } } +@Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ it.map { Invalid(it) } }, { it.map { Valid(it) } })", + "arrow.core.Valid", "arrow.core.Invalid" + ) +) public fun Validated, Iterable>.bisequence(): List> = bitraverse(::identity, ::identity) +@Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ it.map { Invalid(it) } }, { it.map { Valid(it) } })", + "arrow.core.Valid", "arrow.core.Invalid" + ) +) public fun Validated, Either>.bisequenceEither(): Either> = bitraverseEither(::identity, ::identity) +@Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ it.map(::Invalid) }, { it.map(::Valid) })", + "arrow.core.Valid", "arrow.core.Invalid" + ) +) public fun Validated, Option>.bisequenceOption(): Option> = bitraverseOption(::identity, ::identity) +@Deprecated( + DeprAndNicheMsg + "Prefer explicit fold instead", + ReplaceWith( + "fold({ it?.let(::Invalid) }, { it?.let(::Valid) })", + "arrow.core.Valid", "arrow.core.Invalid" + ) +) public fun Validated.bisequenceNullable(): Validated? = bitraverseNullable(::identity, ::identity) +@Deprecated( + DeprAndNicheMsg + "Use fold on Either after refactoring", + ReplaceWith("MA.run { fold({ empty() }) { empty().combine(it) } }") +) public fun Validated.fold(MA: Monoid): A = MA.run { foldLeft(empty()) { acc, a -> acc.combine(a) } } @@ -692,30 +1072,68 @@ public fun Validated.fold(MA: Monoid): A = MA.run { public fun Validated.combineAll(MA: Monoid): A = fold(MA) +@Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ emptyList() }, { it.map(::Valid) })", + "arrow.core.Valid" + ) +) public fun Validated>.sequence(): List> = traverse(::identity) -@Deprecated("sequenceEither is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence()", "arrow.core.sequence")) +@Deprecated( + "sequenceEither is being renamed to sequence to simplify the Arrow API", + ReplaceWith("sequence()", "arrow.core.sequence") +) public fun Validated>.sequenceEither(): Either> = sequence() +@Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ it.invalid().right() }, { it.map(::Valid) })", + "arrow.core.invalid", "arrow.core.right", "arrow.core.Valid" + ) +) public fun Validated>.sequence(): Either> = traverse(::identity) -@Deprecated("sequenceOption is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence()", "arrow.core.sequence")) +@Deprecated( + "sequenceOption is being renamed to sequence to simplify the Arrow API", + ReplaceWith("sequence()", "arrow.core.sequence") +) public fun Validated>.sequenceOption(): Option> = sequence() +@Deprecated( + DeprAndNicheMsg + "Prefer using the Either DSL, or explicit fold or when", + ReplaceWith( + "fold({ None }, { it.map(::Valid) })", + "arrow.core.None", "arrow.core.Valid" + ) +) public fun Validated>.sequence(): Option> = traverse(::identity) -@Deprecated("sequenceNullable is being renamed to sequence to simplify the Arrow API", ReplaceWith("sequence()", "arrow.core.sequence")) +@Deprecated( + "sequenceNullable is being renamed to sequence to simplify the Arrow API", + ReplaceWith("sequence()", "arrow.core.sequence") +) public fun Validated.sequenceNullable(): Validated? = sequence() +@Deprecated( + DeprAndNicheMsg + "Use orNull() and Kotlin nullable types", + ReplaceWith("orNull()?.valid()", "arrow.core.valid") +) public fun Validated.sequence(): Validated? = traverseNullable(::identity) +@Deprecated( + DeprMsg + "Use compareTo on Either after refactoring", + ReplaceWith("toEither(). compareTo(other.toEither())") +) public operator fun , A : Comparable> Validated.compareTo(other: Validated): Int = fold( { l1 -> other.fold({ l2 -> l1.compareTo(l2) }, { -1 }) }, @@ -725,21 +1143,37 @@ public operator fun , A : Comparable> Validated.compa /** * Return the Valid value, or the default if Invalid */ +@Deprecated( + DeprMsg + "Use getOrElse on Either after refactoring", + ReplaceWith("toEither().getOrElse { default() }") +) public inline fun Validated.getOrElse(default: () -> A): A = fold({ default() }, ::identity) /** * Return the Valid value, or null if Invalid */ +@Deprecated( + DeprMsg + "Use getOrNull on Either after refactoring", + ReplaceWith("toEither().getOrNull()") +) public fun Validated.orNull(): A? = getOrElse { null } +@Deprecated( + DeprMsg + "Use getOrNone on Either after refactoring", + ReplaceWith("toEither().getOrNone()") +) public fun Validated.orNone(): Option = fold({ None }, { Some(it) }) /** * Return the Valid value, or the result of f if Invalid */ +@Deprecated( + DeprMsg + "Use getOrElse on Either after refactoring", + ReplaceWith("toEither().getOrElse(f)") +) public inline fun Validated.valueOr(f: (E) -> A): A = fold({ f(it) }, ::identity) @@ -747,6 +1181,13 @@ public inline fun Validated.valueOr(f: (E) -> A): A = * If `this` is valid return `this`, otherwise if `that` is valid return `that`, otherwise combine the failures. * This is similar to [orElse] except that here failures are accumulated. */ +@Deprecated( + DeprAndNicheMsg + "Use recover on Either after refactoring", + ReplaceWith( + "toEither().recover { e -> that().mapLeft { ee -> SE.run { e.combine(ee) } }.bind() }.toValidated()", + "arrow.core.recover" + ) +) public inline fun Validated.findValid(SE: Semigroup, that: () -> Validated): Validated = fold( { e -> @@ -774,6 +1215,10 @@ public inline fun Validated.findValid(SE: Semigroup, that: () -> * ``` * */ +@Deprecated( + DeprMsg + "Use Either DSL or flatMap instead after refactoring.", + ReplaceWith("toEither().flatMap { f(it).toEither() }.toValidated()") +) public inline fun Validated.andThen(f: (A) -> Validated): Validated = when (this) { is Validated.Valid -> f(value) @@ -785,36 +1230,64 @@ public inline fun Validated.andThen(f: (A) -> Validated): * The functionality is similar to that of [findValid] except for failure accumulation, * where here only the error on the right is preserved and the error on the left is ignored. */ +@Deprecated( + DeprMsg + "Use recover on Either instead after refactoring.", + ReplaceWith("toEither().recover { default().bind() }.toValidated()") +) public inline fun Validated.orElse(default: () -> Validated): Validated = fold( { default() }, { Valid(it) } ) +@Deprecated( + DeprMsg + "Use recover on Either instead after refactoring.", + ReplaceWith("toEither().recover { e -> f(e).bind() }.toValidated()") +) public inline fun Validated.handleErrorWith(f: (E) -> Validated): Validated = when (this) { is Validated.Valid -> this is Validated.Invalid -> f(this.value) } +@Deprecated( + DeprMsg + "Use recover on Either instead after refactoring.", + ReplaceWith("toEither().recover { e -> f(e) }.toValidated()") +) public inline fun Validated.handleError(f: (E) -> A): Validated = when (this) { is Validated.Valid -> this is Validated.Invalid -> Valid(f(this.value)) } +@Deprecated( + DeprMsg + "Use fold on Either instead after refactoring.", + ReplaceWith("fold(fe, fa).valid()") +) public inline fun Validated.redeem(fe: (E) -> B, fa: (A) -> B): Validated = when (this) { is Validated.Valid -> map(fa) is Validated.Invalid -> Valid(fe(this.value)) } +@Deprecated( + DeprMsg + "Validated is deprecated in favor of Either", + ReplaceWith("toEither().valid()") +) public fun Validated.attempt(): Validated> = map { Right(it) }.handleError { Left(it) } +@Deprecated( + DeprMsg + "Use merge() on Either instead after refactoring.", + ReplaceWith("toEither().merge()") +) public inline fun Validated.merge(): A = fold(::identity, ::identity) +@Deprecated( + DeprMsg + "Use Either.zipOrAccumulate instead", + ReplaceWith("Either.zipOrAccumulate({ a, b -> SE.run { a.combine(b) } }, toEither(), y.toEither(), { a, b -> SA.run { a.combine(b) } }).toValidated()") +) public fun Validated.combine( SE: Semigroup, SA: Semigroup, @@ -827,6 +1300,13 @@ public fun Validated.combine( else -> y } +@Deprecated( + DeprAndNicheMsg, + ReplaceWith( + "toEither().recover { e -> y.toEither().recover { ee -> raise(SE.run { e.combine(ee) })) }.bind() }.toValidated()", + "arrow.core.recover" + ) +) public fun Validated.combineK(SE: Semigroup, y: Validated): Validated { return when (this) { is Valid -> this @@ -840,17 +1320,42 @@ public fun Validated.combineK(SE: Semigroup, y: Validated) /** * Converts the value to an Ior */ +@Deprecated( + DeprMsg + "Use toIor on Either after refactoring Validated to Either", + ReplaceWith("toEither().toIor()") +) public fun Validated.toIor(): Ior = fold({ Ior.Left(it) }, { Ior.Right(it) }) +@Deprecated( + DeprMsg + "Use right instead to construct the equivalent Either value", + ReplaceWith("this.right()", "arrow.core.right") +) public inline fun A.valid(): Validated = Valid(this) +@Deprecated( + DeprMsg + "Use left instead to construct the equivalent Either value", + ReplaceWith("this.left()", "arrow.core.left") +) public inline fun E.invalid(): Validated = Invalid(this) +@Deprecated( + DeprMsg + "Use right instead to construct the equivalent Either value", + ReplaceWith("this.right()", "arrow.core.right") +) public inline fun A.validNel(): ValidatedNel = Validated.validNel(this) +@Deprecated( + DeprMsg + "Use leftNel instead to construct the equivalent Either value", + ReplaceWith("this.leftNel()", "arrow.core.leftNel") +) public inline fun E.invalidNel(): ValidatedNel = Validated.invalidNel(this) + +private const val DeprMsg = "Validated functionally is being merged into Either.\n" + +private const val DeprAndNicheMsg = + "Validated functionaliy is being merged into Either, but this API is niche and will be removed in the future. If this method is crucial for you, please let us know on the Arrow Github. Thanks!\n https://github.com/arrow-kt/arrow/issues\n" diff --git a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt index 969145e994d..7bc24ac97ee 100644 --- a/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt +++ b/arrow-libs/core/arrow-core/src/commonMain/kotlin/arrow/core/raise/Raise.kt @@ -199,7 +199,11 @@ public interface Raise { is Either.Right -> value } - /* Will be removed in subsequent PRs for Arrow 2.x.x */ + + @Deprecated( + "Validated is deprecated in favor of Either.", + ReplaceWith("toEither().bind()") + ) @RaiseDSL public fun Validated.bind(): A = when (this) { is Validated.Invalid -> raise(value)