functional-programmingmonadsoption-typeapplicative

Functional composition of Optionals


I have 2 Optionals (or Maybe objects) that I would like to combine so that I get the following results:

                ||       first operand 
    second      ++-------------+-------------
    operand     ||    empty    | optional(x)
    ============||=============|=============
    empty       ||    empty    | optional(x)
    ------------++-------------+-------------
    optional(y) || optional(y) |optional(x+y)

In other words, a non-empty Optional always replaces/overwrites an empty one, and two non-empty Optionals are combined according to some + function.

Initially, I assumed that the standard monadic flatMap method would do the trick, but (at least in Java) Optional.flatMap always returns an empty optional when the original Optional was already empty (and I'm not sure if any other implementation would comply with the Monad Laws).

Then, as both operands are wrapped in the same monadic type, I figured that this might be a good job for an Applicative Functor. I tried a couple different functional libraries, but I couldn't implement the desired behavior with any of the zip/ap methods that I tried.

What I'm trying to do seems to me a fairly common operation that one might do with Optionals, and I realize that I could just write my own operator with the desired behavior. Still, I am wondering if there is a standard function/method in functional programming to achieve this common operation?

Update: I removed the java tag, as I'm curious how other languages handle this situation


Solution

  • In Haskell you can do this by wrapping any semigroup in a Maybe. Specifically, if you want to add numbers together:

    Prelude> import Data.Semigroup
    Prelude Data.Semigroup> Just (Sum 1) <> Just (Sum 2)
    Just (Sum {getSum = 3})
    Prelude Data.Semigroup> Nothing <> Just (Sum 2)
    Just (Sum {getSum = 2})
    Prelude Data.Semigroup> Just (Sum 1) <> Nothing
    Just (Sum {getSum = 1})
    Prelude Data.Semigroup> Nothing <> Nothing
    Nothing
    

    The above linked article contains more explanations, and also some C# examples.