选项的功能组成

use*_*890 10 monads functional-programming applicative option-type

我有 2 个可选对象(或 Maybe 对象),我想将它们组合起来,以便得到以下结果:

                ||       first operand 
    second      ++-------------+-------------
    operand     ||    empty    | optional(x)
    ============||=============|=============
    empty       ||    empty    | optional(x)
    ------------++-------------+-------------
    optional(y) || optional(y) |optional(x+y)
Run Code Online (Sandbox Code Playgroud)

换句话说,一个非空Optional总是替换/覆盖一个空Optional,并且两个非空Optional根据某种+功能组合在一起。

最初,我认为标准的 MonadicflatMap方法可以解决这个问题,但是(至少在 Java 中)Optional.flatMap当原始Optional已经为空时总是返回一个空的Optional(并且我不确定是否有其他实现符合Monad Laws) )。

然后,由于两个操作数都包装在相同的一元类型中,我认为这对于应用函子来说可能是一个很好的工作。我尝试了几个不同的函数库,但无法使用我尝试过的任何zip/ap方法实现所需的行为。

在我看来,我正在尝试做的事情似乎是一种相当常见的操作,人们可能会使用Options执行此操作,并且我意识到我可以编写自己的具有所需行为的运算符。不过,我想知道函数式编程中是否有标准函数/方法来实现这种常见操作?

更新:我删除了java标签,因为我很好奇其他语言如何处理这种情况

Bri*_*etz 6

在函数式语言中,您可以通过模式匹配来完成此操作,例如(Haskell):

combine :: Maybe t -> Maybe t -> (t -> t -> t) -> Maybe t
combine (Some x) (Some y) f = Some (f x y)
combine (Some x) _ _ = (Some x)
combine _ (Some y) _ = (Some y)
combine None None _ = None
Run Code Online (Sandbox Code Playgroud)

还有其他方法可以编写它,但基本上是对案例进行模式匹配。请注意,这仍然涉及“解包”选项,但由于它内置于语言中,因此不太明显。


Mar*_*ann 4

在 Haskell 中,你可以通过将任何半群包装在 Maybe 中来做到这一点。具体来说,如果您想将数字相加:

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
Run Code Online (Sandbox Code Playgroud)

上面链接的文章包含更多解释,以及一些 C# 示例。