//arrow-core/arrow.core/Option

Option

common sealed class Option<out A>

If you have worked with Java at all in the past, it is very likely that you have come across a NullPointerException at some time (other languages will throw similarly named errors in such a case). Usually this happens because some method returns null when you weren’t expecting it and, thus, isn’t dealing with that possibility in your client code. A value of null is often abused to represent an absent optional value. Kotlin tries to solve the problem by getting rid of null values altogether, and providing its own special syntax Null-safety machinery based on ?.

Arrow models the absence of values through the Option datatype similar to how Scala, Haskell, and other FP languages handle optional values.

Option<A> is a container for an optional value of type A. If the value of type A is present, the Option<A> is an instance of Some<A>, containing the present value of type A. If the value is absent, the Option<A> is the object None.

import arrow.core.Option
import arrow.core.Some
import arrow.core.none

//sampleStart
val someValue: Option<String> = Some("I am wrapped in something")
val emptyValue: Option<String> = none()
//sampleEnd
fun main() {
 println("value = $someValue")
 println("emptyValue = $emptyValue")
}

Let’s write a function that may or may not give us a string, thus returning Option<String>:

import arrow.core.None
import arrow.core.Option
import arrow.core.Some

//sampleStart
fun maybeItWillReturnSomething(flag: Boolean): Option<String> =
 if (flag) Some("Found value") else None
//sampleEnd

Using getOrElse, we can provide a default value "No value" when the optional argument None does not exist:

import arrow.core.None
import arrow.core.Option
import arrow.core.Some
import arrow.core.getOrElse

fun maybeItWillReturnSomething(flag: Boolean): Option<String> =
 if (flag) Some("Found value") else None

val value1 =
//sampleStart
 maybeItWillReturnSomething(true)
    .getOrElse { "No value" }
//sampleEnd
fun main() {
 println(value1)
}

import arrow.core.None import arrow.core.Option import arrow.core.Some import arrow.core.getOrElse

fun maybeItWillReturnSomething(flag: Boolean): Option = if (flag) Some("Found value") else None

val value2 = //sampleStart maybeItWillReturnSomething(false) .getOrElse { “No value” } //sampleEnd fun main() { println(value2) }


Checking whether option has value:

{: data-executable='true'}

```kotlin
import arrow.core.None
import arrow.core.Option
import arrow.core.Some

fun maybeItWillReturnSomething(flag: Boolean): Option<String> =
 if (flag) Some("Found value") else None

 //sampleStart
val valueSome = maybeItWillReturnSomething(true) is None
val valueNone = maybeItWillReturnSomething(false) is None
//sampleEnd
fun main() {
 println("valueSome = $valueSome")
 println("valueNone = $valueNone")
}

Creating a Option<T> of a T?. Useful for working with values that can be nullable:

import arrow.core.Option

//sampleStart
val myString: String? = "Nullable string"
val option: Option<String> = Option.fromNullable(myString)
//sampleEnd
fun main () {
 println("option = $option")
}

Option can also be used with when statements:

import arrow.core.None
import arrow.core.Option
import arrow.core.Some

//sampleStart
val someValue: Option<Double> = Some(20.0)
val value = when(someValue) {
 is Some -> someValue.value
 is None -> 0.0
}
//sampleEnd
fun main () {
 println("value = $value")
}

import arrow.core.None import arrow.core.Option import arrow.core.Some

//sampleStart val noValue: Option = None val value = when(noValue) { is Some -> noValue.value is None -> 0.0 } //sampleEnd fun main () { println("value = $value") }


An alternative for pattern matching is folding. This is possible because an option could be looked at as a collection or foldable structure with either one or zero elements.



One of these operations is `map`. This operation allows us to map the inner value to a different type while preserving the option:

{: data-executable='true'}

```kotlin
import arrow.core.None
import arrow.core.Option
import arrow.core.Some

//sampleStart
val number: Option<Int> = Some(3)
val noNumber: Option<Int> = None
val mappedResult1 = number.map { it * 1.5 }
val mappedResult2 = noNumber.map { it * 1.5 }
//sampleEnd
fun main () {
 println("number = $number")
 println("noNumber = $noNumber")
 println("mappedResult1 = $mappedResult1")
 println("mappedResult2 = $mappedResult2")
}

Another operation is fold. This operation will extract the value from the option, or provide a default if the value is None

import arrow.core.Option
import arrow.core.Some

val fold =
//sampleStart
 Some(3).fold({ 1 }, { it * 3 })
//sampleEnd
fun main () {
 println(fold)
}

import arrow.core.Option import arrow.core.none

val fold = //sampleStart none().fold({ 1 }, { it * 3 }) //sampleEnd fun main () { println(fold) }


Arrow also adds syntax to all datatypes so you can easily lift them into the context of `Option` where needed.

{: data-executable='true'}

```kotlin
import arrow.core.some

//sampleStart
 val some = 1.some()
 val none = none<String>()
//sampleEnd
fun main () {
 println("some = $some")
 println("none = $none")
}

import arrow.core.toOption

//sampleStart val nullString: String? = null val valueFromNull = nullString.toOption()

val helloString: String? = “Hello” val valueFromStr = helloString.toOption() //sampleEnd fun main () { println(“valueFromNull = $valueFromNull”) println(“valueFromStr = $valueFromStr”) }


You can easily convert between `A?` and `Option<A>` by using the `toOption()` extension or `Option.fromNullable` constructor.

{: data-executable='true'}

```kotlin
import arrow.core.firstOrNone
import arrow.core.toOption

//sampleStart
val foxMap = mapOf(1 to "The", 2 to "Quick", 3 to "Brown", 4 to "Fox")

val empty = foxMap.entries.firstOrNull { it.key == 5 }?.value.let { it?.toCharArray() }.toOption()
val filled = Option.fromNullable(foxMap.entries.firstOrNull { it.key == 5 }?.value.let { it?.toCharArray() })

//sampleEnd
fun main() {
 println("empty = $empty")
 println("filled = $filled")
}

Transforming the inner contents

import arrow.core.Some

fun main() {
val value =
 //sampleStart
   Some(1).map { it + 1 }
 //sampleEnd
 println(value)
}

Computing over independent values

import arrow.core.Some

 val value =
//sampleStart
 Some(1).zip(Some("Hello"), Some(20.0), ::Triple)
//sampleEnd
fun main() {
 println(value)
}

Computing over dependent values ignoring absence

import arrow.core.computations.option
import arrow.core.Some
import arrow.core.Option

suspend fun value(): Option<Int> =
//sampleStart
 option {
   val a = Some(1).bind()
   val b = Some(1 + a).bind()
   val c = Some(1 + b).bind()
   a + b + c
}
//sampleEnd
suspend fun main() {
 println(value())
}

import arrow.core.computations.option import arrow.core.Some import arrow.core.none import arrow.core.Option

suspend fun value(): Option = //sampleStart option { val x = none().bind() val y = Some(1 + x).bind() val z = Some(1 + y).bind() x + y + z } //sampleEnd suspend fun main() { println(value()) } ```

Credits

Contents partially adapted from Scala Exercises Option Tutorial Originally based on the Scala Koans.

Types

Name Summary
Companion common object Companion

Functions

Name Summary
align common infix fun <B> align(b: Option<B>): Option<Ior<A, B»
Align two options (this on the left and b on the right) as one Option of Ior.
common inline fun <B, C> align(b: Option<B>, f: (Ior<A, B>) -> C): Option<C>
Align two options (this on the left and b on the right) as one Option of Ior, and then, if it’s not None, map it using f.
all common inline fun all(predicate: (A) -> Boolean): Boolean
Returns true if this option is empty ‘'’or’’’ the predicate $predicate returns true when applied to this $option’s value.
and common infix fun <X> and(value: Option<X>): Option<X>
crosswalk common inline fun <B> crosswalk(f: (A) -> Option<B>): Option<Option<B»
crosswalkMap common inline fun <K, V> crosswalkMap(f: (A) -> Map<K, V>): Map<K, Option<V»
crosswalkNull common inline fun <B> crosswalkNull(f: (A) -> B?): Option<B>?
exists common inline fun exists(predicate: (A) -> Boolean): Boolean
Returns true if this option is nonempty ‘'’and’’’ the predicate $p returns true when applied to this $option’s value.
filter common inline fun filter(predicate: (A) -> Boolean): Option<A>
Returns this $option if it is nonempty ‘'’and’’’ applying the predicate $p to this $option’s value returns true.
filterNot common inline fun filterNot(predicate: (A) -> Boolean): Option<A>
Returns this $option if it is nonempty ‘'’and’’’ applying the predicate $p to this $option’s value returns false.
findOrNull common inline fun findOrNull(predicate: (A) -> Boolean): A?
Returns the $option’s value if this option is nonempty ‘'’and’’’ the predicate $p returns true when applied to this $option’s value.
flatMap common inline fun <B> flatMap(f: (A) -> Option<B>): Option<B>
Returns the result of applying $f to this $option’s value if this $option is nonempty.
fold common inline fun <R> fold(ifEmpty: () -> R, ifSome: (A) -> R): R
foldLeft common inline fun <B> foldLeft(initial: B, operation: (B, A) -> B): B
foldMap common inline fun <B> foldMap(MB: Monoid<B>, f: (A) -> B): B
isDefined common fun isDefined(): Boolean
Returns true if the option is an instance of Some, false otherwise.
isEmpty common abstract fun isEmpty(): Boolean
Returns true if the option is None, false otherwise.
isNotEmpty common fun isNotEmpty(): Boolean
map common inline fun <B> map(f: (A) -> B): Option<B>
Returns a Some<$B> containing the result of applying $f to this $option’s value if this $option is nonempty.
mapNotNull common inline fun <B> mapNotNull(f: (A) -> B?): Option<B>
Returns $none if the result of applying $f to this $option’s value is null.
nonEmpty common fun nonEmpty(): Boolean
alias for isDefined
orNull common fun orNull(): A?
padZip common fun <B> padZip(other: Option<B>): Option<Pair<A?, B
inline fun <B, C> padZip(other: Option<B>, f: (A?, B?) -> C): Option<C>
pairLeft common fun <L> pairLeft(left: L): Option<Pair<L, A»
pairRight common fun <R> pairRight(right: R): Option<Pair<A, R»
reduceOrNull common inline fun <B> reduceOrNull(initial: (A) -> B, operation: (B, A) -> B): B?
reduceRightEvalOrNull common inline fun <B> reduceRightEvalOrNull(initial: (A) -> B, operation: (A, acc: Eval<B>) -> Eval<B>): Eval<B?>
replicate common fun replicate(n: Int): Option<List<A»
tap common inline fun tap(f: (A) -> Unit): Option<A>
The given function is applied as a fire and forget effect if this is a some.
tapNone common inline fun tapNone(f: () -> Unit): Option<A>
The given function is applied as a fire and forget effect if this is a None.
toEither common inline fun <L> toEither(ifEmpty: () -> L): Either<L, A>
toList common fun toList(): List<A>
toString common open override fun toString(): String
traverse common inline fun <B> traverse(fa: (A) -> Iterable<B>): List<Option<B»
traverseEither common inline fun <AA, B> traverseEither(fa: (A) -> Either<AA, B>): Either<AA, Option<B»
traverseValidated common inline fun <AA, B> traverseValidated(fa: (A) -> Validated<AA, B>): Validated<AA, Option<B»
void common fun void(): Option<Unit>
zip common fun <B> zip(other: Option<B>): Option<Pair<A, B»
inline fun <B, C> zip(b: Option<B>, map: (A, B) -> C): Option<C>
inline fun <B, C, D> zip(b: Option<B>, c: Option<C>, map: (A, B, C) -> D): Option<D>
inline fun <B, C, D, E> zip(b: Option<B>, c: Option<C>, d: Option<D>, map: (A, B, C, D) -> E): Option<E>
inline fun <B, C, D, E, F> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, map: (A, B, C, D, E) -> F): Option<F>
inline fun <B, C, D, E, F, G> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, f: Option<F>, map: (A, B, C, D, E, F) -> G): Option<G>
inline fun <B, C, D, E, F, G, H> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, f: Option<F>, g: Option<G>, map: (A, B, C, D, E, F, G) -> H): Option<H>
inline fun <B, C, D, E, F, G, H, I> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, f: Option<F>, g: Option<G>, h: Option<H>, map: (A, B, C, D, E, F, G, H) -> I): Option<I>
inline fun <B, C, D, E, F, G, H, I, J> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, f: Option<F>, g: Option<G>, h: Option<H>, i: Option<I>, map: (A, B, C, D, E, F, G, H, I) -> J): Option<J>
inline fun <B, C, D, E, F, G, H, I, J, K> zip(b: Option<B>, c: Option<C>, d: Option<D>, e: Option<E>, f: Option<F>, g: Option<G>, h: Option<H>, i: Option<I>, j: Option<J>, map: (A, B, C, D, E, F, G, H, I, J) -> K): Option<K>

Inheritors

Name
None
Some

Extensions

Name Summary
combine common fun <A> Option<A>.combine(SGA: Semigroup<A>, b: Option<A>): Option<A>
combineAll common fun <A> Option<A>.combineAll(MA: Monoid<A>): A
compareTo common operator fun <A : Comparable<A» Option<A>.compareTo(other: Option<A>): Int
ensure common inline fun <A> Option<A>.ensure(error: () -> Unit, predicate: (A) -> Boolean): Option<A>
filterIsInstance common inline fun <B> Option<*>.filterIsInstance(): Option<B>
Returns an Option containing all elements that are instances of specified type parameter B.
flatten common fun <A> Option<Option<A».flatten(): Option<A>
getOrElse common inline fun <T> Option<T>.getOrElse(default: () -> T): T
Returns the option’s value if the option is nonempty, otherwise return the result of evaluating default.
handleError common inline fun <A> Option<A>.handleError(f: (Unit) -> A): Option<A>
handleErrorWith common inline fun <A> Option<A>.handleErrorWith(f: (Unit) -> Option<A>): Option<A>
or common infix fun <T> Option<T>.or(value: Option<T>): Option<T>
orElse common inline fun <A> Option<A>.orElse(alternative: () -> Option<A>): Option<A>
Returns this option’s if the option is nonempty, otherwise returns another option provided lazily by default.
redeem common inline fun <A, B> Option<A>.redeem(fe: (Unit) -> B, fb: (A) -> B): Option<B>
redeemWith common inline fun <A, B> Option<A>.redeemWith(fe: (Unit) -> Option<B>, fb: (A) -> Option<B>): Option<B>
replicate common fun <A> Option<A>.replicate(n: Int, MA: Monoid<A>): Option<A>
rethrow common fun <A> Option<Either<Unit, A».rethrow(): Option<A>
salign common fun <A> Option<A>.salign(SA: Semigroup<A>, b: Option<A>): Option<A>
separateEither common fun <A, B> Option<Either<A, B».separateEither(): Pair<Option<A>, Option<B»
Separate the inner Either value into the Either.Left and Either.Right.
separateValidated common fun <A, B> Option<Validated<A, B».separateValidated(): Pair<Option<A>, Option<B»
Separate the inner Validated value into the Validated.Invalid and Validated.Valid.
sequence common fun <A> Option<Iterable<A».sequence(): List<Option<A»
sequenceEither common fun <A, B> Option<Either<A, B».sequenceEither(): Either<A, Option<B»
sequenceValidated common fun <A, B> Option<Validated<A, B».sequenceValidated(): Validated<A, Option<B»
toMap common fun <K, V> Option<Pair<K, V».toMap(): Map<K, V>
unalign common fun <A, B> Option<Ior<A, B».unalign(): Pair<Option<A>, Option<B»
inline fun <A, B, C> Option<C>.unalign(f: (C) -> Ior<A, B>): Pair<Option<A>, Option<B»
unite common fun <A> Option<Iterable<A».unite(MA: Monoid<A>): Option<A>
uniteEither common fun <A, B> Option<Either<A, B».uniteEither(): Option<B>
uniteValidated common fun <A, B> Option<Validated<A, B».uniteValidated(): Option<B>
unzip common fun <A, B> Option<Pair<A, B».unzip(): Pair<Option<A>, Option<B»
inline fun <A, B, C> Option<C>.unzip(f: (C) -> Pair<A, B>): Pair<Option<A>, Option<B»
widen common fun <B, A : B> Option<A>.widen(): Option<B>
Given A is a sub type of B, re-type this value from Option to OptionOption -> Optionkotlin:ank:playground import arrow.core.Option import arrow.core.some import arrow.core.widen<br>fun main(args: Array<String>) { val result: Option<CharSequence> = //sampleStart "Hello".some().map({ "$it World" }).widen() //sampleEnd println(result) }

Do you like Arrow?

Arrow Org
<