簡體   English   中英

幺半群和戒指之間差異的含義是什么?

[英]What are the implications of the differences between a monoid and a ring?

這是Haskell中monoid的一個例子:

> import Data.Monoid
> Sum 5 <> Sum 6 <> Sum 10
Sum {getSum = 21}
> mconcat [Sum 5, Sum 6, Sum 10]
Sum {getSum = 21}
> getSum $ mconcat $ map Sum [5, 6, 10]
21
> getProduct $ mconcat $ map Product [5, 6, 10]
300

這是Clojure中monoid的一個例子:

(defn plus-monoid
    ([]
        0)
    ([a b]
        (+ a b)))

(plus-monoid) 

(plus-monoid 3 4)

(reduce plus-monoid [2 3 4]) 

這是Haskell中一個環的一個例子:

module Rings where

newtype Matrix r = M [[r]] deriving (Eq,Show)

instance Num r => Num (Matrix r) where
   M [[a,b],[c,d]] + M [[a',b'],[c',d']] = M [[a+a',b+b'],[c+c',d+d']]
   negate (M [[a,b],[c,d]]) = M [[-a,-b],[-c,-d]]
   M [[a,b],[c,d]] * M [[e,f],[g,h]] = M [[a*e+b*g, a*f+b*h] ,[c*e+d*g, c*f+d*h]]
   fromInteger n = M [[fromInteger n, 0],[0, fromInteger n]]

> M [[1,2],[3,4]] - M [[1,0],[0,1]]
M [[0,2],[3,3]]
> M [[2,0],[0,3]] * M [[1,2],[3,4]]
M [[2,4],[9,12]]

這是Clojure中基於此的一個環的示例:

(defprotocol ring
  (plus [x y])
  (mult [x y])
  (neg [x])
  (zero [])
  (one []) )

它似乎是 - (借用Java的說法), 環和幺半群之間區別在於環具有“實現接口的附加方法”。 (也許我錯了)。 現在對我來說,這會對相關性產生影響 - 但我並沒有全神貫注於這一點。

我的問題是: 幺半群和戒指之間的差異有什么影響?

其他方法是必要的但不足以制作戒指。 環結構由管理方法行為及其相互作用的規則產生。

例如,您可以實例Monad並實現bind並返回,公然無視Monad定律,只要您獲得正確的類型,Haskell的類型檢查器就會很高興。 稱這是一個單子並不能使它像一個單子應該不過。

戒指也是如此。

特別是,如果你調用一個環的合約方法+ plus- neg* mul0 zero ,那么1 one

  • +, 0*, 1應該遵守幺半群定律。
  • -應該在+下提供反轉,即-a + a = 0
  • +應該通勤,即a + b = b + a
  • *應該分配+ ,即
    a * (b + c) = (a * b) + (a * c) (b + c) * a = (b * a) + (c * a)

如果你還要求*通勤並且有反向,那么你就有了一個字段。

我可以更容易地回答這個問題,比較幺半群與半環(即環狀,但沒有否定)。

理解半環的最簡單方法是,當類型具有兩個以特定方式相互交互的有效Monoid實例時,它們最常出現。 而不是定義兩個獨立的newtypes(每個Monoid實例),它更容易使用的半環操作來區分哪些Monoid情況下,我們的意思。

一個例子是Haskell中的Bool類型,它有兩個有效的Monoid實例,我們使用AnyAll newtypes進行區分:

newtype Any = Any { getAny :: Bool }
newtype All = All { getAll :: Bool }

instance Monoid Any where
    mempty = Any False
    (Any b1) `mappend` (Any b2) = Any (b1 || b2)

instance Monoid Any where
    mempty = And True
    (And b1) `mappend` (And b2) = And (b1 && b2)

使用Any / All newtypes消除這兩個實例的歧義是一種痛苦,但是如果我們使用半環,那么我們可以通過使用0 / (+)來對應Monoid實例中的一個來完全避免newtypes(在這種情況下) Any )和1 / (*)對應另一個Monoid實例(在本例中為And ):

instance Num Bool where
    fromIntegral 0 = False
    fromIntegral 1 = True

    (+) = (||)
    (*) = (&&)

兩個競爭的Monoid實例的另一個例子是SumProduct的數字:

newtype Sum     a = Sum     { getSum     :: a }
newtype Product a = Product { getProduct :: a }

instance Num a => Monoid (Sum a) where
    mempty = Sum 0
    (Sum x) `mappend` (Sum y) = Sum (x + y)

instance Num a => Product (Product a) where
    mempty = Product 1
    (Product x) `mappend` (Product y) = Product (x * y)

通常,直接使用(+) / (*)來消除我們Monoid的兩個Monoid的哪一個更容易消除歧義。

請注意,在兩種情況下(bool和數字),有問題的兩個Monoid實例以下列方式相互交互:

x * (y + z) = (x * y) + (x * z)

x * 0 = 0

這實際上是偽裝的仿函數法的一個例子。 如果你定義:

fmap = (x *)

(.) = (+)

id = 0

那就是說:

fmap (y . z) = fmap y . fmap z

fmap id = id

因此,您不一定要使用半環來實現兩個單獨的Monoid實例。 您還需要驗證這兩個Monoid實例是否也遵守分配/零定律(即函子定律)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM