Alternative

intermediate

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)
}
// 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)
}
// ListK(list=[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
}
// Some(1)

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:

Module Data types

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

Type Class Hierarchy