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

6 haskell monoids maybe semigroup

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

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

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

luq*_*qui 7

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

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

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

在第三手(!),我们不能有连贯性无处不在,因为库实例与同意MaybeMonadPlus情况下.这与自然数上存在两个幺半群的事实惊人地相似:加法和乘法.对于数字,我们选择不要有任何 monoid实例,因为它不清楚使用哪个.

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

  • 我认为这个问题来自于类型类的核心思想,它是一种双关语,假装类型和代数结构完全对应(例如,类型只有一种方式可以是单子).这通常是,但并非总是如此.但是,制造那些小谎言会使事情变得非常方便,并减少了很多乱七八糟的东西,否则会手动跟踪我们正在谈论的代数结构.但是在这种情况下,我们必须手动选择收藏夹和/或消除歧义,这可能很麻烦. (3认同)
  • ["握紧的手"](http://www.catb.org/jargon/html/O/on-the-gripping-hand.html),也许?:) (2认同)