【问题标题】:Why has Haskell troubles resolving "overloaded" operators?为什么 Haskell 难以解决“重载”运算符?
【发布时间】:2015-10-16 18:13:47
【问题描述】:

This post!! 的情况提出了问题。接受的答案告诉我们,您实际上在做的是创建一个新函数!!,然后您应该避免导入标准函数。

但是,如果新功能要应用于与标准功能不同的类型,为什么要这样做呢?编译器不是可以根据其参数选择正确的吗? 是否有任何编译器标志允许这样做?

例如,如果* 没有为[Float] * Float 定义

为什么编译器会哭

> 模棱两可的出现 * > 它可以引用在 Vec.hs:4:1 中定义的任何一个 `Main.*' > 或 `Prelude.*',

对于此代码:

(*) :: [Float] -> Float -> [Float]
(*) as k = map (\a -> a*k) as  -- here: clearly Float*Float


r = [1.0, 2.0, 3.0] :: [Float]

s = r * 2.0 -- here: clearly [Float] * Float

main = do
     print r
     print s

【问题讨论】:

  • 你可以用s = r * 2.0 where (*) = (Main.*)(*) as k = map (\a -> a*k) as where (*) = (Prelude.*)提示编译器

标签: haskell operator-overloading


【解决方案1】:

允许编译器根据函数的类型选择正确的函数实现是类型类的目的。没有他们是不可能的。

为了证明这种方法的合理性,您可以阅读介绍它们的论文:How to make ad-hoc polymorphism less ad hoc [PDF]。

【讨论】:

  • 奇怪的是,在其他地方没有问题,却在 Haskell。谢谢你的回答。
  • 这句话似乎反过来也是正确的。其他地方出现的许多问题在 haskell 中都没有。
  • 是的,但这不是在 Haskell 中不允许临时多态性的理由。
  • @cibercitizen1 你读过我链接的论文吗?它讨论了特殊多态性的一些限制,尤其是在 Hindley-Milner 系统中。
  • @cibercitizen1 这是一个设计决策,我认为考虑到选项,这是一个合理的决策。虽然您的问题和 cmets 似乎表明 Haskell 只是选择不实现 ad hoc 多态本身,但 ad hoc 多态并不是免费的:它与其他语言设计目标存在冲突。其他语言在这里做出了不同的选择(或者,在某些情况下,没有选择,因为他们无法实现他们放弃的功能)。例如,我每次都更喜欢类型推断而不是临时多态性。我无法想象没有它来编写 Haskell。
【解决方案2】:

真的,原因是这样的:在 Haskell 中,不一定有明确的关联“变量x 具有类型T

Haskell 几乎与动态语言一样灵活,因为任何类型都可以是类型变量,即可以具有多态类型。但是在动态语言(以及例如 OO 多态性或 C++ 模板)中,此类类型变量的类型基本上只是附加到代码中的值变量的额外信息(因此重载运算符可以看到:参数是 @987654323 @->do this, is a String->do that),在 Haskell 中,类型变量在类型语言中存在于完全独立的范围内。这给了你很多好处,例如,如果没有这样的系统,高级多态性几乎是不可能的。然而,这也意味着更难推断应该如何解决重载函数。如果 Haskell 允许您只编写重载并假设编译器会尽最大努力解决歧义,那么您通常会在意想不到的地方收到奇怪的错误消息。 (实际上,即使您有 no Hindley-Milner 类型系统,重载也很容易发生这种情况。C++ 因它而臭名昭著。)

相反,Haskell 选择强制重载显式。在重载方法之前必须先定义一个类型类,虽然这不能完全排除令人困惑的编译错误,但它使它们更容易避免。此外,它还允许您表达具有传统重载无法表达的类型解析的多态方法,特别是 多态结果(这对于编写非常容易重用的代码非常有用)。

【讨论】:

    【解决方案3】:

    这是一个设计决定,而不是一个理论问题,不要将其包含在 Haskell 中。正如您所说,许多其他语言使用类型来以特别的方式消除术语之间的歧义。但是类型类具有类似的功能,并且还允许对重载的事物进行抽象。没有类型导向的名称解析。

    尽管如此,已经为 Haskell 讨论了类型导向的名称解析形式(例如在解析记录字段选择器的上下文中),并且被一些类似于 Haskell 的语言支持,例如 Agda(用于数据构造函数)或 Idris(更多一般来说)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-13
      相关资源
      最近更新 更多