Functional companion to Kotlin's Standard Library providing core data types and error handling
—
Safe handling of optional values without null pointer exceptions. Option provides a type-safe alternative to nullable types with comprehensive functional operations and guaranteed null safety.
Create Option instances representing presence or absence of values.
/**
* Option containing a value
*/
data class Some<out A>(val value: A) : Option<A>
/**
* Option representing absence of value
*/
object None : Option<Nothing>
/**
* Create Option from potentially null value
*/
fun <A> Option.Companion.fromNullable(value: A?): Option<A>Convenience functions for creating Option instances.
/**
* Wrap any value in Some
*/
fun <A> A.some(): Some<A>
/**
* Create None instance with specific type
*/
fun <A> none(): Option<A>Usage Examples:
// Direct construction
val present: Option<String> = Some("hello")
val absent: Option<String> = None
// From nullable values
val maybeUser = Option.fromNullable(findUserById(123))
// Using extension functions
val greeting = "Hello".some()
val empty: Option<String> = none()Check the state of Option instances with type-safe guards.
/**
* Check if Option contains a value
* @return true if Some, false if None
*/
fun <A> Option<A>.isSome(): Boolean
/**
* Check if Option is empty
* @return true if None, false if Some
*/
fun <A> Option<A>.isNone(): BooleanSafely extract values or perform operations based on Option state.
/**
* Pattern match on Option, providing handlers for both cases
*/
fun <A, B> Option<A>.fold(
ifEmpty: () -> B,
ifSome: (A) -> B
): B
/**
* Extract the value or compute a default
*/
fun <A> Option<A>.getOrElse(default: () -> A): A
/**
* Extract the value or return null
*/
fun <A> Option<A>.getOrNull(): A?
/**
* Extract the value or return null (alias for getOrNull)
*/
fun <A> Option<A>.orNull(): A?Usage Examples:
val maybeAge: Option<Int> = Some(25)
// Pattern matching
val description = maybeAge.fold(
ifEmpty = { "Age not provided" },
ifSome = { age -> "Age is $age" }
)
// Extract with default
val age = maybeAge.getOrElse { 0 }
// Extract as nullable
val nullableAge: Int? = maybeAge.getOrNull()Transform Option values while preserving the container structure.
/**
* Transform the contained value if present
*/
fun <A, B> Option<A>.map(f: (A) -> B): Option<B>
/**
* Monadic bind - chain operations that may return None
*/
fun <A, B> Option<A>.flatMap(f: (A) -> Option<B>): Option<B>
/**
* Keep value only if it satisfies the predicate
*/
fun <A> Option<A>.filter(predicate: (A) -> Boolean): Option<A>
/**
* Keep value only if it does NOT satisfy the predicate
*/
fun <A> Option<A>.filterNot(predicate: (A) -> Boolean): Option<A>Usage Examples:
val maybeNumber: Option<String> = Some("42")
// Transform value
val doubled = maybeNumber
.map { it.toInt() }
.map { it * 2 }
// Result: Some(84)
// Chain operations
val result = maybeNumber
.flatMap { str ->
if (str.all { it.isDigit() }) Some(str.toInt()) else None
}
.filter { it > 10 }
// Result: Some(42)Filter Option values based on predicates.
/**
* Keep value only if it satisfies the predicate
*/
fun <A> Option<A>.filter(predicate: (A) -> Boolean): Option<A>
/**
* Keep value only if it does NOT satisfy the predicate
*/
fun <A> Option<A>.filterNot(predicate: (A) -> Boolean): Option<A>Convert Option to other types and collections.
/**
* Convert Option to List (empty list for None, single-item list for Some)
*/
fun <A> Option<A>.toList(): List<A>
/**
* Convert Option to Either, providing error for None case
*/
fun <A, E> Option<A>.toEither(ifEmpty: () -> E): Either<E, A>Usage Examples:
val maybeValue: Option<String> = Some("hello")
// Convert to List
val list = maybeValue.toList() // ["hello"]
// Convert to Either
val either = maybeValue.toEither { "Value was not provided" }
// Result: Either.Right("hello")
val emptyOption: Option<String> = None
val emptyList = emptyOption.toList() // []
val leftEither = emptyOption.toEither { "Missing value" }
// Result: Either.Left("Missing value")Combine multiple Option values.
/**
* Combine two Options using a transformation function
* Returns Some only if both Options are Some
*/
fun <A, B, C> Option<A>.zip(other: Option<B>, transform: (A, B) -> C): Option<C>
/**
* Combine two Options into a Pair
* Returns Some only if both Options are Some
*/
fun <A, B> Option<A>.zip(other: Option<B>): Option<Pair<A, B>>Usage Examples:
val firstName: Option<String> = Some("John")
val lastName: Option<String> = Some("Doe")
// Combine with transformation
val fullName = firstName.zip(lastName) { first, last -> "$first $last" }
// Result: Some("John Doe")
// Combine into Pair
val namePair = firstName.zip(lastName)
// Result: Some(Pair("John", "Doe"))Additional utility functions for working with Option.
/**
* Return this Option if it's Some, otherwise return the alternative
*/
fun <A> Option<A>.orElse(alternative: () -> Option<A>): Option<A>
/**
* Apply a side effect if Option is Some, return original Option
*/
fun <A> Option<A>.onSome(action: (A) -> Unit): Option<A>
/**
* Apply a side effect if Option is None, return original Option
*/
fun <A> Option<A>.onNone(action: () -> Unit): Option<A>Usage Examples:
val primary: Option<String> = None
val backup: Option<String> = Some("backup value")
// Use alternative if primary is None
val result = primary.orElse { backup }
// Result: Some("backup value")
// Side effects
val logged = Some("important data")
.onSome { value -> println("Processing: $value") }
.onNone { println("No data to process") }Extensions for working with collections of Option values.
/**
* Sequence a collection of Options into an Option of collection
* Returns Some(list) only if all Options are Some
*/
fun <A> Iterable<Option<A>>.sequence(): Option<List<A>>
/**
* Transform collection to Options and sequence the results
*/
fun <A, B> Iterable<A>.traverse(f: (A) -> Option<B>): Option<List<B>>
/**
* Keep only Some values from collection of Options
*/
fun <A> Iterable<Option<A>>.catOptions(): List<A>Usage Examples:
val options = listOf(Some(1), Some(2), Some(3))
val sequenced = options.sequence() // Some([1, 2, 3])
val mixed = listOf(Some(1), None, Some(3))
val mixedSequenced = mixed.sequence() // None
val values = mixed.catOptions() // [1, 3]Install with Tessl CLI
npx tessl i tessl/maven-io-arrow-kt--arrow-core