Using scala for reference, we see a fallback behavior (orElse
) in several places such as PartialFunction
, Option
, and cats EitherOps
.
This feels similar to but not the same as the flattening behavior of a monad. Is there a functional programming term for things that exhibit this behavior?
Edit: Some good answers so far, digging around more in cats, I've found
Semigroup[Option[String]].combine(None, Some("b"))
res0: Option[String] = Some(b)
Semigroup[Option[String]].combine(Some("a"), Some("b"))
res1: Option[String] = Some(ab)
SemigroupK[Option].combineK(None, Some("b"))
res2: Option[String] = Some(b)
SemigroupK[Option].combineK(Some("a"), Some("b"))
res3: Option[String] = Some(a)
SemigroupK[List].combineK(List("a"), List("b"))
res4: List[String] = List(a, b)
Alternative[List].unite(List(None, Some("a"), Some("b")))
res4: List[String] = List(a, b)
So I see now that the scalaz Alt
and haskell Alternative
are not quite the same as the cats Alternative
. The more interesting thing is the SemigroupK
(called Plus
in scalaz according to the cats documentation).
So could we say this behavior is exhibited by a type for which you cannot define a semigroup without also having a semigroup for its inner type (because then we might say the scalaz Alt
and haskell Alternative
are semigroups for such kinds)?
A decent chunk of Scala is inspired by similar concepts in Haskell. In this particular case, orElse
is pretty close to the "alternative" operator <|>
in the Alternative
typeclass.
In Haskell, an Applicative
is a Functor
(read: it contains things and has some way of interacting with those things) which has some meaningful monoidal way of "combining" those things: <*>
. We can think of <*>
as being somewhat similar (although not identical) to Scala's andThen
, in that it takes two "successful" computations and sequences them. Under this analogy, an Alternative
is an Applicative
that provides a way to "recover" from failure, so <|>
is more or less Scala's orElse
.
Since you mentioned monads, Applicative
is a weakening of Monad
, in the sense that every Monad
is an Applicative
but not every Applicative
is necessarily Monad
. For example, multidimensional arrays can easily be made into Applicative
but cannot be made Monad
.
So, to summarize, I believe the term you're looking for is "applicative functor with alternative capabilities", codified in Haskell by the Alternative
typeclass. If you want to sound terribly arrogant, we can call it by its mathematically rigorous name: a strong lax monoidal functor backed by an additional monoidal structure. But that's just if we're showing off.