繁体   English   中英

为什么Maybe的Semigroup实例偏向于Just而Monoid使用Nothing作为其空元素?

[英]Why is Maybe's Semigroup instance biased towards Just and the Monoid uses Nothing as its empty element?

Maybe表示可能由于错误而不会产生结果的计算。 因此,这种计算必须短路。

现在, Maybe的Semigroup / Monoid实例似乎打破了这种语义,因为前者偏向于Just而后者将错误情况视为Nothing作为其空元素:

Just "foo" <> Nothing -- Just "foo"
Nothing <> Just "bar" -- Just "bar"
Just "foo" <> Just "bar" -- Just "foobar"
Nothing <> Nothing -- Nothing

对于前两种情况,我希望Nothing

这是替代实现(希望它是正确/合法的):

instance Semigroup a => Semigroup (Maybe a) where
    Nothing <> _       = Nothing
    _       <> Nothing = Nothing
    Just a  <> Just b  = Just (a <> b)

instance Monoid a => Monoid (Maybe a) where
  mempty = Just mempty

我不想说这些替代实例更好。 但它们似乎也很有用。 那么为什么首先进行选择而不是将实现留给用户呢?

您的实例实际上是应用函子的更通用实例的特例。

newtype LiftA f a = LiftA { getLiftA :: f a }

instance (Applicative f, Semigroup a) => Semigroup (LiftA f a) where
    LiftA x <> LiftA y = LiftA $ liftA2 (<>) x y

instance (Applicative f, Monoid a) => Monoid (LiftA f a) where
    mempty = LiftA $ pure mempty

我认为它会在某个地方的标准库中(可能在不同的名称下),但我找不到它。 但是这个一般实例的存在可能是选择Maybe的库版本的一个原因,这更像是Maybe的特殊能力。 另一方面,当你的代数结构彼此连贯时,它是相当不错的; 即当一个类型是Applicative时,尽可能使用“ LiftA ”式实例(在所有F代数类上)。

在第三方面(!),我们无法在任何地方保持一致性,因为库实例与MaybeMonadPlus实例一致。 这与自然数上存在两个幺半群的事实惊人地相似:加法和乘法。 对于数字,我们选择不要有任何 monoid实例,因为它不清楚使用哪个。

总之,我不知道。 但也许这些信息很有帮助。

我认为这背后的想法是, Maybe应该具有实际上只有Option正确表达的语义:它需要任何半群并通过添加Nothing作为临时“免费mempty”而使其成为monoid。 即实际上应该是实例

instance Semigroup a => Semigroup (Maybe a) where
  Nothing <> a = a
  a <> Nothing = a
  Just x <> Just y = Just $ x <> y

instance Semigroup a => Monoid (Maybe a) where
  mappend = (<>)
  mempty = Nothing

这类似于[]通过添加mempty<>给出任何类型的自由monoid。

当然,这要求Semigroup类在base ,直到最近才出现。

对此的推论是, mempty变得明显模式匹配,因为通过参数化它不能依赖于包含的类型。

实际上,这个实例可能比你提出的实例更有用,因为正如Luke所说, Applicative实例已经涵盖了这个实例,所以你可以轻松编写liftA2 (<>)pure mempty 当然,标准实例也已经被Alternative实例所覆盖,但是Alternative/MonadPlus一直被认为有点hackish,不如数学上无可挑剔的SemigroupMonoidFunctorApplicative

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM