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

Ale*_*tko 7 haskell functional-programming category-theory

我可以理解mappend和关联性要求的原因.但为什么我们需要身份元素呢?它的实用性是什么?或许我错过了一些重要的东西,如果没有定义它,整个逻辑将无法正常工作.谢谢!

lef*_*out 13

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

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

所以 - 和我们以前一样的问题Monad很多:很多代码真的只需要Applicative甚至只是Functor,但由于历史原因,Monad直到AMP都被困住了.最终问题是Haskell类层次结构在事后不能真正得到改进,只能向下扩展,而不是向上扩展.


Ben*_*son 5

这些天base都有两个类SemigroupMonoid(并且计划正在进行以使后者暗示前者),因此您不必在两个抽象之间进行选择 - 只使用适合您目的的最弱假设.

也就是说,Monoid在日常实践中似乎确实比在某些方面更有用Semigroup.为什么是这样?我可以想到几行论点:

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