Alternative

We use Option to indicate a computation can fail somehow (that is, it can have either zero results or one result), and we use lists for computations that can have many possible results (ranging from zero to arbitrarily many results). In both of these cases, one useful operation is combining all possible results from multiple computations into a single computation. The Alternative type class captures this combination.

Alternative is for Applicative functors which also have a Monoid structure.

Main Combinators

Kind<F, A>.orElse

Is a binary function which represents a choice between alternatives.

fun <A> Kind<F, A>.orElse(b: Kind<F, A>): Kind<F, A>

import arrow.core.Option
import arrow.core.extensions.option.monadCombine.monadCombine

Option.monadCombine().run {
    val x: Option<Int> = Option.just(1)
    val y: Option<Int> = Option.empty()
    x.orElse(y)
}
// Option.Some(1)
import arrow.core.ListK
import arrow.core.extensions.listk.monadCombine.monadCombine
import arrow.core.k

ListK.monadCombine().run {
    val x = listOf(1, 2).k()
    val y = listOf(3, 4).k()
    x.orElse(y)
}
// [1, 2, 3, 4]

Kind<F, A>.alt

It is just an infix alias over orElse.

import arrow.core.Option
import arrow.core.extensions.option.monadCombine.monadCombine

Option.monadCombine().run {
    val x: Option<Int> = Option.just(1)
    val y: Option<Int> = Option.empty()
    x alt y
}
// Option.Some(1)

Kind<F, A>.some

fun <A> Kind<F, A>.some(): Kind<F, SequenceK<A>>

Repeats the current computation, lazily collecting its results into a sequence, until it fails. It is required that the computation succeeds at least once.

import arrow.core.Option
import arrow.core.extensions.option.monadCombine.monadCombine

Option.monadCombine().run {
  val x = Option.just(1)
  x.some().map { it.take(5).toList() }
}
// Option.Some([1, 1, 1, 1, 1])
import arrow.core.Option
import arrow.core.extensions.option.monadCombine.monadCombine

Option.monadCombine().run {
  val x = Option.empty<Int>()
  x.some().map { it.take(5).toList() }
}
// Option.None

Kind<F, A>.many

fun <A> Kind<F, A>.many(): Kind<F, SequenceK<A>>

Same function as some, but it does not require the computation to succeed.

import arrow.core.Option
import arrow.core.extensions.option.monadCombine.monadCombine

Option.monadCombine().run {
  val x = Option.empty<Int>()
  x.many().map { it.take(5).toList() }
}
// Option.Some([])

Laws

Arrow provides AlternativeLaws in the form of test cases for internal verifications of lawful instances and third party apps creating their own Alternative instances.

Available Instances:

Additionally all the instances of MonadCombine implement the Alternative directly since it is subtype of Alternative.

Do you like Arrow?

Arrow Org
<