Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Trick to Use Covariant (out) Type in Contravariant (in) Position in Kotlin
sealed class Option<out A>(open val value: A?) {
fun <B> fold(ifNone: () -> B, ifSome: (A) -> B): B =
when (this) {
is None -> ifNone()
is Some -> ifSome(this.value)
// This doesn't compile because `out` type A is in `in` position
fun getOrElseThatWontWork(default: () -> A): A =
when (this) {
is None -> default()
is Some -> this.value
data class None<A>: Option<A>(null)
data class Some<A>(override val value: A): Option<A>(value)
// But this works even though A is in `in` position here!
// This is an inlined extension function with a reified type A with no variance restrictions on its definition.
// So we are free to use A in `in` position.
inline fun <reified A> Option<A>.getOrElse(crossinline default: () -> A): A = fold({ default() }, { a -> a })
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment