Haskell 错误中的 Semigroup/Monoid/Group 类型类层次结构
我正在尝试创建代数类型类的“层次结构”,如下所示:
class Semigroup a where
(.*) :: a -> a -> a
foldr1 (.*) = foldl1 (.*) -- GHCi error: "`foldr1' is not a (visible) method of class `Semigroup'"
class (Semigroup a) => Monoid a where
identity :: a
(.*) identity = id :: a -> a -- GHCi error: "`.*' is not a (visible) method of class `Monoid'"
class (Monoid a) => Group a where
inverse :: a -> a
因此,群是幺半群,而幺半群是半群。但是,我收到错误,这些类无法看到其父类的函数。
这些错误让我烦恼,因为我假设通过编写(例如) class (Semigroup a) => Monoid a
类 Monoid a
将能够看到函数 (.*)
。此外,Prelude 中的 foldr1
类型没有任何限制,因此我假设 foldr1
在这种情况下可以工作。
I'm trying to create a "hierarchy" of algebraic type classes, as follows:
class Semigroup a where
(.*) :: a -> a -> a
foldr1 (.*) = foldl1 (.*) -- GHCi error: "`foldr1' is not a (visible) method of class `Semigroup'"
class (Semigroup a) => Monoid a where
identity :: a
(.*) identity = id :: a -> a -- GHCi error: "`.*' is not a (visible) method of class `Monoid'"
class (Monoid a) => Group a where
inverse :: a -> a
Thus, groups are monoids and monoids are semigroups. However, I get errors that the classes can't see the functions of their parent class.
These errors bug me because I assumed that by writing (for example) class (Semigroup a) => Monoid a
the class Monoid a
would be able to see the function (.*)
. And furthermore, the type of foldr1
in the Prelude has no constraints, so I assumed that foldr1
would work in this context.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Haskell 不允许您根据项声明(或强制执行)方程(就像您想要做的那样)。这是出于一个非常实际的原因:在像 Haskell 这样丰富的编程语言中证明任意项之间的相等性是不可判定的。检查人工构建的证明通常是可判定的,但在编程时必须编写和跟踪这些证明也有点烦人。
不过,如果这是您想要定期做的事情,有一些语言可以使这成为可能;要搜索的术语是“依赖类型”。例如,Coq 和 Agda 可能是目前两种最流行的依赖类型语言,每种语言都可以使编写仅由良好的、守法的半群(或幺半群)所占据的类型变得非常简单。
Haskell does not allow you to declare (or enforce) equations on terms (like it seems like you want to do). This is for a very practical reason: proving equalities between arbitrary terms in a programming language as rich as Haskell is undecidable. Checking a human-constructed proof is often decidable, but it is also somewhat annoying to have to write and track these proofs while programming.
Still, if this is the kind of thing you want to do on a regular basis, there are languages that make this possible; the term to search for is "dependent types". For example, Coq and Agda are perhaps the two most popular dependently typed languages at the moment, and each would make it dead-simple to write a type inhabited only by good, law-abiding semigroups (or monoids).
我不确定你想做什么。
如果您尝试为
Semigroup
中的foldr1
提供默认值,并为Monoid 中的
,那么你就不能。(.*)
提供默认值foldr1
在 Prelude 中定义为非类型类函数,因此您不能在Semigroup
中给它局部定义(.*)
是Semigroup
类的一部分。您可以在Semigroup
实例中给出其值,并且可以在Semigroup
类中为其给出默认值,但不能在Monoid
类(或Monoid
实例)如果您尝试为
Semigroup
中的(.*)
提供默认值,以及identity
的默认值Monoid
,那么您使用了错误的语法。相反,尝试类似
或
I'm not sure what you're trying to do.
If you're trying to provide a default value for
foldr1
inSemigroup
, and a default value for(.*)
inMonoid
, then you can't.foldr1
is defined in the Prelude as a non-typeclass function, so you can't give it a local definition inSemigroup
(.*)
is part of theSemigroup
class. You can give its values inSemigroup
instances, and you can give a default value for it in theSemigroup
class, but you can't give its value in theMonoid
class (orMonoid
instances)If you're trying to to provide a default value for
(.*)
inSemigroup
, and a default value foridentity
inMonoid
, then you're using the wrong syntax.Instead try something like
or