[英]What does Data.Semigroup ((<>)) do in this Haskell sort code?
[英]Haskell, implementing Monoids. What is Semigroup and why does it act so weird?
我想实现一个名为 ComplexNumber 的自定义数据类型,如下所示: data ComplexNumber a = C (a,a)
现在我想实现 Monoid 变量并定义二进制 mempty Element 和 mappend ,如下所示:
instance Num a => Monoid (ComplexNumber a) where
mempty = C (0,0)
mappend = (C (a1, b1)) (C (a2, b2)) = C (a1 + a2, b1 + b2)
但这并没有成功,因此试图找出原因并遇到了 Semigroup(我仍然不太了解)并得出了一个至少可以编译并且似乎可以使用的解决方案:
instance Num a => Semigroup (ComplexNumber a) where
(C (a1, b1)) <> (C (a2,b2)) = C (a1 + a2, b1 + b2)
instance Num a => Monoid (ComplexNumber a) where
mempty = C (0,0)
有趣的是,当我删除 Semigroup 的实现时,程序不再编译并给我以下错误:
* Could not deduce (Semigroup (ComplexNumber a))
arising from the superclasses of an instance declaration
from the context: Num a
bound by the instance declaration at Aufgabe_10.hs:9:10-42
* In the instance declaration for `Monoid (ComplexNumber a)'
|
9 | instance Num a => Monoid (ComplexNumber a) where
|
为什么我可以将这两个部分编译在一起,但是当我删除半组时会发生错误? 特别是这个半群的东西
Semigroup
只是具有<>
操作实现的所有类型的 class,以某种方式使其具有关联性(即a<>(b<>c) ≡ (a<>b)<>c
,它确实如果我们忽略小的浮点偏差,则适用于您的复数)。
Monoid
是半群的 class ,它们还具有中性元素mempty
,即始终满足mempty <> a ≡ a <> mempty ≡ a
的元素(对于具有加法和零的复数也是如此)。
对于甚至没有<>
操作的类型,即没有Semigroup
实例,这将是一个荒谬的要求。 这由Semigroup
表示为Monoid
的超类,因此不可能有一个类型是Monoid
的实例而不是Semigroup
的实例。
从历史上看, Semigroup
和Monoid
是独立的类,旧的Monoid
提供自己的mappend
操作,相当于现代的<>
。 一些较旧的书籍/教程仍然基于这个旧的 class 层次结构。
但是因为有一堆类型只是半群而不是幺半群,所以 class 层次结构发生了变化。
一个幺半群[wiki]是一个具有恒等式的半群[wiki] :它有一个恒等元素 e [wiki] ,对于集合中的所有元素x ,关联二元运算⊕将x ⊕ e = e ⊕ x = x 。 因此,每个幺半群都是一个半群,因为半群是一个具有关联二元算子⊕的代数结构,因此除了不需要单位元e之外,它的性质与幺半群中的相同。
从base-4.9.0.0
开始,引入了Semigroup
class ,但随后Semigroup
和Monoid
并没有“生活在一起”。 由于为Semigroup
定义与Monoid
实例不同的二元运算符没有多大意义(因为这可能会引起混淆),因为base-4.11.0.0
, Semigroup
是Monoid
的超类。 事实上, Monoid
被定义为[src] :
class半群 a => Monoid a where # ...
这意味着为了使某物成为Monoid
的实例,它也必须是Semigroup
的实例。 mappend:: Monoid a => a -> a -> a
将自动链接到(<>):: Semigroup a => a -> a -> a
Semigroup a => a -> a -> a 的实现,并且很可能最终会被删除。
因此,您不能再定义Monoid
的实例而不定义Semigroup
的实例。 但是您可以“机械地”从Monoid
的旧实例创建一个实例,因为您只需将mappend
的实现从Monoid
实例移动到Semigroup
的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.