簡體   English   中英

為什么在 Haskell 中更喜歡幺半群而不是半群? 為什么我們需要 mempty?

[英]Why prefer monoids over semigroups in Haskell? Why do we need mempty?

我可以理解 mappend 和關聯性要求的原因。 但是為什么我們需要標識元素呢?它有什么實際用處呢? 或者也許我錯過了一些重要的東西,如果沒有定義它,整個邏輯將無法工作。 謝謝!

某些應用程序肯定需要mempty 例如, foldMap ping空列表的結果應該是什么? 沒有a值可以提供給映射函數來獲得m 因此,需要有一個“默認”。 如果這是關聯操作的標識元素,那就太好了——例如,它允許在不改變結果的情況下任意重新排序/分塊折疊。 當折疊一棵樹時,實際上很多mempty可能會出現在中間,但你總是知道它們會在最終結果中被“擠出”,所以你不依賴於精確的樹布局來獲得可重復的結果。

這就是說,你和你關心的問題: Semigroup會經常是足夠的,它可能會更好,如果該類被用於任何mempty不需要(因為實際上有幾個很漂亮的類型是Semigroup ,但不Monoid )。 然而,標准庫的早期設計顯然沒有考慮到這一點足以保證額外的類,所以很多代碼開始依賴於Monoid而實際上並不需要Monoid

所以 - 與我們過去使用Monad遇到的問題大致相同:許多代碼實際上只需要Applicative甚至只需要Functor ,但由於歷史原因,無論如何在 AMP 之前都被Monad卡住了。 最終的問題是 Haskell 類層次結構在事后無法真正細化,只能向下擴展,而不是向上擴展。

這些天base功能類兩個SemigroupMonoid (和計划正在准備,使后者意味着前者),所以您不必在兩個抽象之間做出選擇-只用適合你的目的最弱的假設。

也就是說, Monoid在日常實踐中似乎確實比Semigroup更有用。 這是為什么? 我可以想到幾行論證:

  1. 在編程中有用的東西,比如集合,往往具有零或多語義; Monoid以一種Semigroup沒有的方式自然地抽象出可組合的事物集合。 (例如, []免費的Monoid ,是集合的經典示例。)
  2. 當您開始組合它們時,屬於Semigroup而不是Monoid的類型往往會失去精度。 給定兩個非空列表xsys ,我們知道xs <> ys至少有兩個元素。 但它的類型只承諾它至少有一個; 有用的信息被丟棄了。
  3. 從社會的角度來看,人們對陰謀集團的地獄已經足夠害怕,以避免為了處理“非空的東西”而引入額外的依賴。 當你想用的單子,sans-工作return和類別,sans- id ,安裝semigroupoids包需要“Kmett平台”的一大塊。

這與所有其他抽象一樣:您可以使用的操作越多,您可以抽象的東西就越復雜。 特別是關於Monoid ,這里有一些最流行的函數, Semigroup只是不夠:

foldMap :: (Foldable t, Monoid m) => (a -> m) -> t a -> m

fold :: (Foldable t, Monoid m) => t m -> m

mconcat :: Monoid a => [a] -> a

暫無
暫無

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

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