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标签,因为我很好奇其他语言如何处理这种情况
在函数式语言中,您可以通过模式匹配来完成此操作,例如(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)
还有其他方法可以编写它,但基本上是对案例进行模式匹配。请注意,这仍然涉及“解包”选项,但由于它内置于语言中,因此不太明显。
在 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# 示例。