4

目前我正在学习 Haskell,并且坚持将类型实例化为类型类。我实际上不明白,为什么可以Maybe a使用Just (+).

这对我来说表现得很奇怪的问题是,Maybe 类型被定义为类型类的实例Eq(请参阅Haskell 源代码),并且如果您派生一个类型的实例,则该类型的值/数据构造函数的所有字段必须也是类型类的一个实例Eq这里)。

考虑到这些知识,以下代码不应是可编译或可执行的,因为函数不是类型类的一部分Eq

let a = Just (+)
let b = Just (-)

但 GHCi 实际上执行代码时不会抛出错误消息。如果您然后尝试比较这两个值(这也不应该是可能的),解释器会出现以下错误消息:

a == b

<interactive>:24:1: error:
    * No instance for (Eq (Integer -> Integer -> Integer))
        arising from a use of `=='
        (maybe you haven't applied a function to enough arguments?)
    * In the expression: a == b
      In an equation for `it': it = a == b

如果您创建自己的Maybe a类型,也会出现此问题。

4

1 回答 1

12

Eqfor的实例Maybe最终看起来像这样(也就是说,deriving (Eq)基本上被重写为这个):

instance (Eq a) => Eq (Maybe a) where
    ...

这可以读成好像 a是 的成员Eq那么也是Maybe a。因此,制作 a或拥有你的东西是完全可以的,如果它的论点不是Maybe (Int -> Int),它就不会是。Eq

从编译器的角度来看,这是一种对操作更有帮助的思考方式:解决Eq (Maybe a)约束,解决约束就足够了Eq a。所以当我们说

a == b

编译器试图解决Eq (Maybe (Integer -> Integer -> Integer)). 它使用Maybe实例将问题简化为Eq (Integer -> Integer -> Integer),然后在它无能为力时放弃。这就是为什么您会看到错误消息抱怨 no instance forEq (Integer -> Integer -> Integer)而不是提及Maybe.

于 2019-08-05T20:16:36.660 回答