为什么在Haskell中更喜欢半群而不是半群?为什么我们需要mempty?

时间:2016-11-19 01:36:58

标签: haskell functional-programming category-theory

我可以理解mappend和关联性要求的原因。但为什么我们需要身份元素呢?它的实用性是什么?或者也许我错过了一些重要的事情,如果没有定义它,整个逻辑就不会起作用。谢谢!

3 个答案:

答案 0 :(得分:13)

某些应用程序当然需要mempty。例如,foldMapping对空列表的结果应该是什么?没有a值可以提供映射函数来获取m。所以,需要有一个“默认”。如果这是关联操作的标识元素,那就太好了 - 例如,它允许在不改变结果的情况下任意重新排序/分块。当折叠在树上时,实际上很多mempty可能会出现在中间,但你总是知道它们会在最终结果中被“挤出”,所以你不依赖于确切的树形布局可重复的结果。

那就是说,你的问题是正确的:Semigroup通常是足够的,如果在不需要mempty的地方使用这个类可能会更好(因为有实际上是一些非常漂亮的类型Semigroup但不是Monoid)。然而,标准库的早期设计显然没有考虑到这一点非常重要,以保证额外的类,所以很多代码依赖于Monoid而不需要一个幺半群。

所以 - 与我们之前使用的Monad相同的问题很多:很多代码实际上只需要Applicative甚至只需Functor,但由于历史原因,我们遇到{Monad 1}}无论如何直到AMP。最终问题是Haskell类层次结构实际上不能真正精简,只能向下扩展,而不是向上扩展

答案 1 :(得分:5)

这些天baseSemigroupMonoid提供了类别(并且正在制定计划以使后者暗示前者),因此您无需在两者之间进行选择抽象 - 只使用适合您目的的最弱假设。

尽管如此,Monoid似乎在日常实践中比Semigroup更有用。为什么是这样?我可以想到几行论点:

  1. 在编程中有用的东西,例如集合,往往具有零或多个语义; MonoidSemigroup没有的方式自然地抽象出可组合的事物集合。 (例如,[]免费 Monoid,是集合的典型示例。)
  2. 当您开始撰写时,Semigroup但不是Monoid的类型往往会失去精确度。鉴于两个非空列表xsys,我们知道xs <> ys至少有两个元素。但它的类型只承诺它至少有一个;有用的信息已被丢弃。
  3. 从社交角度来看,人们对Cabal Hell的恐惧已经足够,以避免为了处理“非空洞的事情”而引入额外的依赖关系。当你想使用monads-sans - return和categories-sans - id时,安装semigroupoids包需要一大块“Kmett平台”。

答案 2 :(得分:3)

它与所有其他抽象相同:您拥有的操作越多,您可以抽象的事情就越复杂。关于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