我想实现一个名为ComplexNumber的自定义数据类型,如下所示:data ComplexNumber a = C (a,a)
现在,我想实现Monoid变量,并定义二进制mappend元素和mappend,如下所示:
instance Num a => Monoid (ComplexNumber a) where
mempty = C (0,0)
mappend = (C (a1, b1)) (C (a2, b2)) = C (a1 + a2, b1 + b2)但这并没有奏效,所以试着找出原因,并遇到了闪族(我仍然不太明白),于是找到了一种解决方案,它至少可以编译,并且似乎与此相配合:
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)有趣的是,当我删除半群的实现时,程序不再编译,并给出以下错误:
* 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
| 为什么我可以将这两个部分编译在一起,但是当我移除半群时会发生错误?特别是这个半群的东西
发布于 2022-07-25 15:18:10
Semigroup只是具有<>操作实现的所有类型的类,在某种程度上它是关联的(也就是说,如果我们忽略了小的浮点偏差,那么a<>(b<>c) ≡ (a<>b)<>c对你的复数来说是正确的)。
Monoid是半群的一类,它另外有一个中性元素mempty,即总是满足mempty <> a ≡ a <> mempty ≡ a的元素(对于带有加法和零的复数也是如此)。
对于一个甚至没有<>操作的类型来说,这是一个荒谬的要求,也就是说,它没有一个Semigroup实例。这是由Semigroup表示的,它是Monoid的超类,因此不可能有一个类型是Monoid的实例,而不是Semigroup的实例。
历史上,Semigroup和Monoid是单独的类,旧的Monoid发布了自己的mappend操作,相当于现代的<>。一些旧的书籍/教程仍然基于这个旧的类层次结构。
但是由于有许多类型只是半群,而不是一元,所以类的层次结构发生了变化。
https://stackoverflow.com/questions/73111476
复制相似问题