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 theAlternative
typeclass.In Haskell, an
Applicative
is aFunctor
(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'sandThen
, in that it takes two "successful" computations and sequences them. Under this analogy, anAlternative
is anApplicative
that provides a way to "recover" from failure, so<|>
is more or less Scala'sorElse
.Since you mentioned monads,
Applicative
is a weakening ofMonad
, in the sense that everyMonad
is anApplicative
but not everyApplicative
is necessarilyMonad
. For example, multidimensional arrays can easily be made intoApplicative
but cannot be madeMonad
.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.