使用类约束定义实例

时间:2015-05-15 21:35:12

标签: haskell

我正在浏览Learn You a Haskell

我正在讨论类型类的章节。有这个片段:

class (Eq a) => Num a where

我将此理解为强加于Num类的类约束,强制它作为一个等同的类。我的问题是,为什么没有Num作为Eq的实例实施?像这样:

instance Eq Num where
... stuff

定义一个实例似乎是一种更干净的方法,但也许我错过了一些东西。有人可以向我解释一下这个区别吗?

1 个答案:

答案 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的类型。它包含构造函数TFFileNotFoundBrillant类型是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。如果aEq集的元素,则Maybe aEq集的元素。

class Eq a => Num a where
    (+) :: a -> a -> a

有一组类型。我们将此集命名为Num。如果a是此集合中的类型,则a也位于集Eq中(换句话说,EqNum的子集)。如果aNum集合中的类型,那么我们可以添加此类型的两个值,并使用(+)函数获得第三个值。

如果以下声明是有效的Haskell,那么它的意思是:

instance Eq Num where -- ...

类型为Num的集合是类型为Eq的集合的元素。

现在让我们比较最后两个,即class Eq a => Num ainstance Eq Num。前者表示Num集的成员也是Eq集的成员,而后者表示Num集本身是Eq集的成员。希望后者在你的头脑中引起某种警钟。由于我们说Eq是一组类型,因此该集合的所有成员都应该是类型。但我们也说Num是一组类型,而不是类型;所以它不能成为会员。

讨论类型集的集合是有意义的 - 也就是说,其实例是其他类的类 - 但EqNum都不这样做。因此,声称NumEq的实例是不正确的。