【问题标题】:Why can you create a value with "Just (+)"?为什么可以用“Just (+)”创造价值?
【发布时间】:2019-08-05 20:10:02
【问题描述】:

目前我正在学习 Haskell,并且被类型实例化为类型类所困。我其实不明白,为什么可以用Just (+) 创建Maybe a 类型的值。

这对我来说很奇怪的问题是,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 类型,也会出现此问题。

【问题讨论】:

  • 为什么你认为let a = Just (+) 应该是一个错误?这是一个Maybe (Integer -&gt; Integer -&gt; Integer) 类型的值——这有什么问题?你不能比较a==b,当然,但你也不能比较(+)==(-),但我认为你可以接受(+)的存在。如果(+)存在,为什么要禁止Just (+)

标签: haskell type-parameter deriving


【解决方案1】:

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

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

这可以读作如果 aEq 的成员,那么 Maybe a 也是。所以创建一个Maybe (Int -&gt; Int) 或者你有什么是完全可以的,如果它的论点不是,它就不会是Eq

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

a == b

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

【讨论】:

    猜你喜欢
    • 2015-11-15
    • 2018-08-17
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 2021-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多