[英]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
功能類兩個Semigroup
和Monoid
(和計划正在准備,使后者意味着前者),所以您不必在兩個抽象之間做出選擇-只用適合你的目的最弱的假設。
也就是說, Monoid
在日常實踐中似乎確實比Semigroup
更有用。 這是為什么? 我可以想到幾行論證:
Monoid
以一種Semigroup
沒有的方式自然地抽象出可組合的事物集合。 (例如, []
,免費的Monoid
,是集合的經典示例。)Semigroup
而不是Monoid
的類型往往會失去精度。 給定兩個非空列表xs
和ys
,我們知道xs <> ys
至少有兩個元素。 但它的類型只承諾它至少有一個; 有用的信息被丟棄了。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.