在 Haskell 中,是否有 <?> 运算符的抽象?

In Haskell, is there an abstraction for the <?>-operator?

我刚刚发现自己正在编写这段代码:

import Control.Applicative ((<|>))

x = mA <|> mB <?> c

(<?>) :: Maybe a -> a -> a
Just x  <?> _ = x
Nothing <?> y = y

其中 mA :: Maybe amB :: Maybe ac :: ax :: a。基本上,代码说:选择第一个不是 empty 的备选方案,并默认为 c。您可以将其称为 "reverse Maybe monad",其中与 <?> 的类比是 pure.

等价地,我可以写

Just x = mA <|> mB <|> pure c,

但我对无可辩驳的模式感到不舒服。或者,当然,

x = fromMaybe c (mA <|> mB)

因为fromMaybe === flip <?>.

<?> 运算符的灵感来自秒差距。当我发现自己定义了这样的实用函数时,我总是很怀疑,但我在任何地方都找不到这种默认行为。

显然AlternativeApplicative不够强大。

我是不是错过了一个类型-class?

我能想到的 "emptyness" 仅有的两个抽象是:

首先,MonadErrorMaybe 可能有 instance MonadError () Maybe。但是请参阅 https://github.com/ekmett/mtl/issues/27

其次,lens_Empty, 这是默认比较 (Eq) 与 mempty (of Monoid)。然而 MonoidAlternative 不同意 Maybe.

但我不记得有任何操作员直接在上面的任何一个上工作。

我认为将事情留在 (<?>) = flip fromMaybe 是个好主意。

如果您想概括一下,Foldable 似乎是最简单的 class,带有空虚的概念:

(<?>) :: Foldable t => t a -> a -> a
ta <?> a = foldr const a ta 

如果 ta 为空或 ta 的第一个元素,则此 returns a。示例:

Just 0 <?> 10 == 0
Nothing <?> 0 == 0
[] <?> 10 == 10

实际上,我不喜欢 <?> 运算符名称作为您要查找的内容。 如果您在 Stackage or Hayoo 上搜索 Maybe a -> a -> a 类型,您可以从 errors 包中找到 ?: 运算符。

这个运算符就是所谓的 elvis-运算符。它以那种形式用在 Groovy 中。 Kotlin 也有。此运算符有助于处理命令式语言中的空值。但是,如果您认为 Maybe a 是某种可空类型,那么 ?: 运算符对您来说也很有意义。您可以观察到 ?: 运算符背后有一些历史。

此外,<?> 已经在一些包中使用,例如 megaparsec, attoparsec, optparse-generic 和其他包。而你的项目可能会使用其中一个很有可能。因此,您可能会在使用 elvis-operator.

版本时遇到一些冲突