Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Value Class Option [Arrow 2] #2950

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1064,30 +1064,7 @@ public sealed class Either<out A, out B> {
}
return getOrElse { null }
}

public fun orNone(): Option<B> = getOrNone()

/**
* Transforms [Either] into [Option],
* where the encapsulated value [B] is wrapped in [Some] when this instance represents [Either.Right],
* or [None] if it is [Either.Left].
*
* ```kotlin
* import arrow.core.Either
* import arrow.core.Some
* import arrow.core.None
* import io.kotest.matchers.shouldBe
*
* fun test() {
* Either.Right(12).getOrNone() shouldBe Some(12)
* Either.Left(12).getOrNone() shouldBe None
* }
* ```
* <!--- KNIT example-either-41.kt -->
* <!--- TEST lines.isEmpty() -->
*/
public fun getOrNone(): Option<B> = fold({ None }, { Some(it) })


@Deprecated(
NicheAPI + "Prefer using the Either DSL, or map",
ReplaceWith("if (n <= 0) Right(emptyList()) else map { b -> List(n) { b } }")
Expand Down Expand Up @@ -1119,7 +1096,7 @@ public sealed class Either<out A, out B> {
* Either.Right("foo").isEmpty() // Result: false
* }
* ```
* <!--- KNIT example-either-42.kt -->
* <!--- KNIT example-either-41.kt -->
*/
@Deprecated(
RedundantAPI + "Use `is Either.Left<*>`, `when`, or `fold` instead",
Expand All @@ -1141,7 +1118,7 @@ public sealed class Either<out A, out B> {
* //sampleEnd
* }
* ```
* <!--- KNIT example-either-43.kt -->
* <!--- KNIT example-either-42.kt -->
*/
@Deprecated(
RedundantAPI + "Use `is Either.Right<*>`, `when`, or `fold` instead",
Expand Down Expand Up @@ -1319,7 +1296,7 @@ public sealed class Either<out A, out B> {
* println(result)
* }
* ```
* <!--- KNIT example-either-44.kt -->
* <!--- KNIT example-either-43.kt -->
*/
@JvmStatic
@Deprecated(
Expand Down Expand Up @@ -1816,6 +1793,30 @@ public sealed class Either<out A, out B> {
map { }
}

public inline fun <A, reified B> Either<A, B>.orNone(): Option<B> = getOrNone()

/**
* Transforms [Either] into [Option],
* where the encapsulated value [B] is wrapped in [Some] when this instance represents [Either.Right],
* or [None] if it is [Either.Left].
*
* ```kotlin
* import arrow.core.Either
* import arrow.core.Some
* import arrow.core.None
* import arrow.core.getOrNone
* import io.kotest.matchers.shouldBe
*
* fun test() {
* Either.Right(12).getOrNone() shouldBe Some(12)
* Either.Left(12).getOrNone<Int, Any>() shouldBe None
* }
* ```
* <!--- KNIT example-either-44.kt -->
* <!--- TEST lines.isEmpty() -->
*/
public inline fun <A, reified B> Either<A, B>.getOrNone(): Option<B> = fold({ None }, { Some(it) })

/**
* Binds the given function across [Right], that is,
* Map, or transform, the right value [B] of this [Either] into a new [Either] with a right value of type [C].
Expand Down Expand Up @@ -2238,7 +2239,7 @@ public fun <A, B> Either<A, Iterable<B>>.sequence(): List<Either<A, B>> =
"arrow.core.right",
)
)
public fun <A, B> Either<A, Option<B>>.sequenceOption(): Option<Either<A, B>> =
public inline fun <A, reified B> Either<A, Option<B>>.sequenceOption(): Option<Either<A, B>> =
sequence()

@Deprecated(
Expand All @@ -2250,7 +2251,7 @@ public fun <A, B> Either<A, Option<B>>.sequenceOption(): Option<Either<A, B>> =
"arrow.core.left"
)
)
public fun <A, B> Either<A, Option<B>>.sequence(): Option<Either<A, B>> =
public inline fun <A, reified B> Either<A, Option<B>>.sequence(): Option<Either<A, B>> =
orNull()?.orNull()?.right().toOption()

@Deprecated(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ public fun <A> Iterable<A>.combineAll(MA: Monoid<A>): A =
/**
* Returns the first element as [Some(element)][Some], or [None] if the iterable is empty.
*/
public fun <T> Iterable<T>.firstOrNone(): Option<T> =
public inline fun <reified T> Iterable<T>.firstOrNone(): Option<T> =
when (this) {
is Collection -> if (!isEmpty()) {
Some(first())
Expand All @@ -733,7 +733,7 @@ public fun <T> Iterable<T>.firstOrNone(): Option<T> =
}
}

private fun <T> Iterator<T>.nextOrNone(): Option<T> =
@PublishedApi internal inline fun <reified T> Iterator<T>.nextOrNone(): Option<T> =
if (hasNext()) {
Some(next())
} else {
Expand All @@ -743,7 +743,7 @@ private fun <T> Iterator<T>.nextOrNone(): Option<T> =
/**
* Returns the first element as [Some(element)][Some] matching the given [predicate], or [None] if element was not found.
*/
public inline fun <T> Iterable<T>.firstOrNone(predicate: (T) -> Boolean): Option<T> {
public inline fun <reified T> Iterable<T>.firstOrNone(predicate: (T) -> Boolean): Option<T> {
for (element in this) {
if (predicate(element)) {
return Some(element)
Expand All @@ -755,7 +755,7 @@ public inline fun <T> Iterable<T>.firstOrNone(predicate: (T) -> Boolean): Option
/**
* Returns single element as [Some(element)][Some], or [None] if the iterable is empty or has more than one element.
*/
public fun <T> Iterable<T>.singleOrNone(): Option<T> =
public inline fun <reified T> Iterable<T>.singleOrNone(): Option<T> =
when (this) {
is Collection -> when (size) {
1 -> firstOrNone()
Expand All @@ -770,7 +770,7 @@ public fun <T> Iterable<T>.singleOrNone(): Option<T> =
/**
* Returns the single element as [Some(element)][Some] matching the given [predicate], or [None] if element was not found or more than one element was found.
*/
public inline fun <T> Iterable<T>.singleOrNone(predicate: (T) -> Boolean): Option<T> {
public inline fun <reified T> Iterable<T>.singleOrNone(predicate: (T) -> Boolean): Option<T> {
val list = mutableListOf<T>()
for (element in this) {
if (predicate(element)) {
Expand All @@ -786,7 +786,7 @@ public inline fun <T> Iterable<T>.singleOrNone(predicate: (T) -> Boolean): Optio
/**
* Returns the last element as [Some(element)][Some], or [None] if the iterable is empty.
*/
public fun <T> Iterable<T>.lastOrNone(): Option<T> =
public inline fun <reified T> Iterable<T>.lastOrNone(): Option<T> =
when (this) {
is Collection -> if (!isEmpty()) {
Some(last())
Expand All @@ -808,7 +808,7 @@ public fun <T> Iterable<T>.lastOrNone(): Option<T> =
/**
* Returns the last element as [Some(element)][Some] matching the given [predicate], or [None] if no such element was found.
*/
public inline fun <T> Iterable<T>.lastOrNone(predicate: (T) -> Boolean): Option<T> {
public inline fun <reified T> Iterable<T>.lastOrNone(predicate: (T) -> Boolean): Option<T> {
var value: Any? = EmptyValue
for (element in this) {
if (predicate(element)) {
Expand All @@ -821,7 +821,7 @@ public inline fun <T> Iterable<T>.lastOrNone(predicate: (T) -> Boolean): Option<
/**
* Returns an element as [Some(element)][Some] at the given [index] or [None] if the [index] is out of bounds of this iterable.
*/
public fun <T> Iterable<T>.elementAtOrNone(index: Int): Option<T> =
public inline fun <reified T> Iterable<T>.elementAtOrNone(index: Int): Option<T> =
when {
index < 0 -> None
this is Collection -> when (index) {
Expand All @@ -832,7 +832,7 @@ public fun <T> Iterable<T>.elementAtOrNone(index: Int): Option<T> =
else -> iterator().skip(index).nextOrNone()
}

private tailrec fun <T> Iterator<T>.skip(count: Int): Iterator<T> =
@PublishedApi internal tailrec fun <T> Iterator<T>.skip(count: Int): Iterator<T> =
when {
count > 0 && hasNext() -> {
next()
Expand Down Expand Up @@ -1048,7 +1048,7 @@ public operator fun <A : Comparable<A>> Iterable<A>.compareTo(other: Iterable<A>
public infix fun <T> T.prependTo(list: Iterable<T>): List<T> =
listOf(this) + list

public fun <T> Iterable<Option<T>>.filterOption(): List<T> =
flatMap { it.fold(::emptyList, ::listOf) }
public inline fun <reified T> Iterable<Option<T>>.filterOption(): List<T> =
flatMap { it.fold(::emptyList) { listOf(it) } }

public fun <T> Iterable<Option<T>>.flattenOption(): List<T> = filterOption()
public inline fun <reified T> Iterable<Option<T>>.flattenOption(): List<T> = filterOption()
Loading