【问题标题】:Understanding Haskell Type Class use in Type Declarations了解 Haskell 类型类在类型声明中的使用
【发布时间】:2018-12-28 08:22:09
【问题描述】:

当我们有一个使用==比较运算符比较两个事物的函数时,我们将Eq a => a...之类的东西添加到类型声明中;但情况似乎并非总是如此。

例如,给定以下函数:

tail' xs = if length xs == 0
          then []
          else drop 1 xs

我们使用==比较运算符,所以我假设正确的类型声明是:

tail':: (Eq a) => [a] -> [a]

但是,运行 :t tail' 告诉我正确的类型声明是:

tail':: [a] -> [a]

为什么会这样?为什么类型声明中不需要Eq

【问题讨论】:

  • 您应该尽可能使用模式匹配(例如这里),而不是使用==。此外,还需要花几分钟时间研究列表是如何定义的,并考虑因此,lengthlast!! 等常见类似数组的操作的时间复杂度必须是多少。
  • 还要注意drop 1 [] 已经是[],尽管我知道这不是你问题的重点:-)

标签: haskell


【解决方案1】:

Eq a => t 表示a 必须是t 类型中Eq 的实例。作为Eq 实例的类型意味着为该类型定义了==。但是在您对tail' 的定义中,您永远不会在a 上使用==,即使是通过代理也不行。 ==的实际使用在length xs == 0length xs(和0)的类型是Int,而Int已经是Eq的一个实例,所以我们已经知道它已经定义了==。由于您从不在 a 上使用 ==,因此您不需要 Eq a 约束。

但是,如果您说xs == [],这似乎是等价的(两者都测试列表是否为空),您将产生Eq a 约束。这是因为[a] 上的== 需要Eq a 约束,因为它在每个列表的条目上使用== 来比较列表。不过,由于您可以使用length xs == 0(或者,甚至更好的是null xs),因此这种添加的约束是虚假的,应该避免使用。

(顺便说一句,drop 1 [] = [],所以你甚至不需要你的if,但这与所提出的问题无关。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多