Search code examples
scalafunctional-programmingscala-catspartialfunction

In functional programming terms, what do you call something with an orElse or other fallback method?


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)?


Solution

  • 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.