【问题标题】:Haskell function overloadingHaskell 函数重载
【发布时间】:2016-06-10 09:54:56
【问题描述】:
  1. 我必须重载函数排序。函数的参数是一个数字,它们必须按参数0 的值排序。这是我尝试过的:

    Prelude>instance (Num a, Ord b) => Ord (a -> b) where f > g = f 0 > g 0
    

    但它会产生错误

    Could not deduce (Eq (a -> b))
    arising from the superclasses of an instance declaration
    from the context (Num a, Ord b)
    bound by the instance declaration at <interactive>:117:10-39
    In the instance declaration for `Ord (a -> b)'
    
  2. 我还想为列表实例化 Ord 类。列表排序将通过每个列表的第一个元素之间的比较来给出。例如 [1,2]

    instance Ord a => Ord [a] where
        (h1:_) <= (h2:_) = h1 <= h2
    

    这也会产生下一个错误:

    Ambiguous occurrence `<='
    It could refer to either `Main.<=',
                         defined at C:\Users\user-name\Desktop\test.hs:2:8
                      or `Prelude.<=',
                         imported from `Prelude' at C:\Users\user-name\Desktop\test.hs:1:1
                         (and originally defined in `GHC.Classes')
    

我想我可能不太了解 Haskell 中的函数重载。也许有人可以解释我做错了什么。

【问题讨论】:

  • 您定义自己的&lt;= 吗? Prelude 已经带有&lt;=,所以你应该选择你想要的(这就是第二条错误消息的意思)。第一个错误是说函数之间没有相等的内置定义。此外,Haskell 没有函数重载。
  • 你对列表的排序会很奇怪,因为[1,1] &lt;= [1,2][1,2] &lt;= [1,1] 当然[1,1] /= [1,2] - 你也不能比较空列表......你为什么要这样做?跨度>
  • 练习的目的是理解不做“有道理”的事情的原则。
  • 你的练习需要你解决三件事:定义一个函数&lt;=,它将(尝试)适用于所有类型的参数;定义 Ord 类型类的新类型实例(您的案例 1);并定义一个现有类型的实例(对于[a])(您的2),即使您之前没有定义函数&lt;=,它也不起作用,因为Prelude中已经存在Ord a =&gt; Ord [a]的实例.

标签: haskell


【解决方案1】:
  1. 不要这样做。您在此处定义孤儿实例(既不存在于 data 的模块中也不存在于它们所属的 class 模块中的实例);这样的实例在导入中是“不可见的”,这通常是大型项目维护的痛苦。 (有时你不会绕过孤立实例,特别是在组合来自不相关包的数据和类时;但函数、列表和Ord 都在基础库中。如果没有在那里定义实例,你可以很漂亮肯定有充分的理由!

  2. 如果您确实定义了类实例,请查看类定义! Ord 是这样定义的:

    class (Eq a) => Ord a where
      ...
    

    这意味着,Ord 的任何实例也必须是 Eq 的实例。这也是编译器告诉你的。所以,如果你定义了这个实例,你还需要添加

    instance (Num a, Eq b) => Eq (a -> b) where f==g = f 0 == g 0
    

    这是与您的Ord 兼容的唯一实例。坦率地说,这是错误的,因为大多数被此实例视为相等的函数相等!

  3. Haskell 根本没有重载。如果你在你的模块Main 中定义了一个函数&lt;=,这是一个与标准&lt;= 又名Prelude.&lt;= 完全无关的函数。您可以定义这样一个新功能,但要使用它,您需要消除歧义。以下应该有效:

    instance Ord a => Ord [a] where
      (h1:_) <= (h2:_) = h1 Main.<= h2
    

    同样,这不是一个好主意——您根本不应该首先定义Main.&lt;=,而是将其定义放在Ord 实例中。

【讨论】:

  • Ord [a] 实例不会与Prelude 实例重叠吗?
  • 我现在明白了您在 2 时所说的内容。我还有一个问题。为什么instance (Show b, Num a) =&gt; Show (a -&gt; b) where show f = show (f 0) 可以工作而我不必instance (Show b, Num a) =&gt; Show (a -&gt; b) where show f = Main.show (f 0)
  • 因为与 &lt;= 不同,您显然试图重新定义自己,您从未定义自己的 show 函数。因此很明显show 指的是Prelude.show,而Main.show 根本不存在。
  • Main.show 将不起作用。范围内唯一的showPrelude.show。 Prelude 会自动导入,因此您只需执行show
猜你喜欢
  • 1970-01-01
  • 2013-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多