簡體   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