我正在浏览Learn You a Haskell
我正在讨论类型类的章节。有这个片段:
class (Eq a) => Num a where
我将此理解为强加于Num
类的类约束,强制它作为一个等同的类。我的问题是,为什么没有Num
作为Eq
的实例实施?像这样:
instance Eq Num where
... stuff
定义一个实例似乎是一种更干净的方法,但也许我错过了一些东西。有人可以向我解释一下这个区别吗?
答案 0 :(得分:7)
让我们用英语发表几个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
中(换句话说,Eq
是Num
的子集)。如果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
的实例是不正确的。