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

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

考虑到这些知识,以下代码不应该是可编译或可执行的,因为函数不是 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 类型,也会出现此问题。

最佳答案

EqMaybe 实例最终看起来像这样(也就是说,deriving (Eq) 基本上被改写成这样):

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

如果 aEq 的成员,那么这可以读为 然后 Maybe a 也是。因此,制作 Maybe (Int -> Int) 或您拥有的东西完全没问题,如果它的参数不是,它就不会是 Eq

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

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

关于haskell - 为什么你可以用 "Just (+)"创建一个值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57365468/

10-13 02:19