我正在浏览 Learn You a Haskell
并且我在讨论类型类的章节中。有这个片段:
class (Eq a) => Num a where
我将此理解为强加于 Num
类的类约束,迫使它充当可等式类。我的问题是,为什么 Num
没有作为 Eq
的实例实现?像这样:
instance Eq Num where
... stuff
定义一个实例似乎是一种更简洁的方法,但也许我遗漏了一些东西。有人可以向我解释一下区别吗?
最佳答案
让我们用英语读出其中的几个 Haskell 声明;也许这会澄清一些事情。先给出Haskell声明,再给出英文音译。
class Eq a where (==) :: a -> a -> Bool
有一组类型。我们将此集合命名为 Eq
。如果 a
是该集合中的一个类型,那么我们可以使用名为 (==)
的函数比较该类型的两个值是否相等。
data Brillant = T | F | FileNotFound
instance Eq Brillant where
T == T = True
F == F = True
FileNotFound == FileNotFound = True
_ == _ = False
有一个名为 Brillant
的类型。它具有构造函数 T
、F
和 FileNotFound
。 Brillant
类型是 Eq
集合的一个元素。可以通过检查它们是否使用相同的构造函数来比较 Brillant
类型的两个项是否相等。
data Maybe a = Nothing | Just a
instance Eq a => Eq (Maybe a) where
Nothing == Nothing = True
Just v == Just v' = v == v'
只要我们有一个类型a
,就会有另一个类型Maybe a
。如果 a
是 Eq
集合的元素,那么 Maybe a
是 Eq
集合的元素。
class Eq a => Num a where
(+) :: a -> a -> a
有一组类型。我们将此集合命名为 Num
。如果 a
是这个集合中的一个类型,那么 a
也在集合 Eq
中(或者,换句话说,Num
是 Eq
的子集)。如果 a
是 Num
集合中的一个类型,那么我们可以添加这个类型的两个值并使用 (+)
函数得到第三个.
如果以下声明在 Haskell 中有效,那么它的含义如下:
instance Eq Num where -- ...
名为 Num
类型的集合是名为 Eq
类型集合的一个元素。
现在让我们比较最后两个,即 class Eq a => Num a
和 instance Eq Num
。前者表示Num
集合的成员也是Eq
集合的成员,而后者表示Num
集合本身是成员Eq
集合。希望后者能在您的脑海中敲响警钟。因为我们说 Eq
是一组类型,所以该组的所有成员都应该是类型。但是我们也说过 Num
是一组类型,而不是一个类型;所以它不能成为成员。
谈论类型集合的集合是有意义的——也就是说,其实例是其他类的类——但 Eq
和 Num
都没有这样做。因此,声称 Num
是 Eq
的实例是不正确的。
关于haskell - 定义实例与使用类约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30269097/