假设我想为semigroup和monoid定义自己的类型类。所以我写了这段代码:


 class Semigroup g where
 (<>):: g - > g - > g

类半群m => Monoid m where
 mempty :: m



 但是还有另一种方法可以定义这些类型类之间的关系,并带有一些扩展:
&# xA;
 class Semigroup g where
 gappend :: g - > g - > g

类Monoid m其中
 mempty :: m
 mappend :: m - > m - > m

实例Monoid m =>半群m在哪里
 gappend = mappend



 后一种设计有一个优势 - 后来我可以为Monoid添加更多实例。例如,如果我有一个矢量空间的类型类,我以后可以将它作为一个加法组而不必在类声明中指定它。另一方面,我被迫使用灵活的实例和不可判定的实例。


我的问题是 - 这个特定案例的最佳设计是什么?
& #xA;答案 0 :(得分:4)
第一个版本说" monoids是半群,附加属性为mempty
"。
第二个确定说"所有类型都是半群,只要它们也是幺半群"。除非您乐意打开重叠实例,否则您无法添加任何其他实例,因此这等于"当且仅当它是一个幺半群时,类型才是半群&#34 ;;与真实关系完全相反。
我几乎总是喜欢前者。是的,它迫使有人想要添加Monoid
实例来编写Semigroup
实例,但真正的"工作"他们必须做同样的事情:决定mempty
和mappend
的实施。通过使用第二种方法,你唯一能够保存它们的是一个小样板。