haskell - 定义实例与使用类约束

标签 haskell

我正在浏览 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 的类型。它具有构造函数 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 中(或者,换句话说,NumEq 的子集)。如果 aNum 集合中的一个类型,那么我们可以添加这个类型的两个值并使用 (+) 函数得到第三个.

如果以下声明在 Haskell 中有效,那么它的含义如下:

instance Eq Num where -- ...

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

现在让我们比较最后两个,即 class Eq a => Num ainstance Eq Num。前者表示Num集合的成员也是Eq集合的成员,而后者表示Num集合本身是成员Eq 集合。希望后者能在您的脑海中敲响警钟。因为我们说 Eq 是一组类型,所以该组的所有成员都应该是类型。但是我们也说过 Num 是一组类型,而不是一个类型;所以它不能成为成员。

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

关于haskell - 定义实例与使用类约束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30269097/

相关文章:

haskell - 无法将种类 '*' 与 'Nat' 匹配

Haskell-foldl $ lambda Set.empty

haskell - 构造函数/cases/guards/if-then-else 的顺序对性能有影响吗?

haskell - F# 类型声明可能是 Haskell 吗?

haskell - Haskell 函数中的非详尽模式

performance - haskell /GHC : Unsafely deconstruct a constructor?

haskell - 如何编写调用 `run` 或 `runStateT` 的函数 `runReaderT`?

arrays - Haskell map/sortBy/findIndex 等用于数组而不是列表

haskell - Haskell 中通过多态性的递归代数数据类型

haskell - 在 monad 转换器中,为什么已知的 monad 是内部的?