编写排序实例的有效方法是什么?

时间:2015-07-12 20:10:56

标签: sorting haskell

我正在进行基本的Haskell练习,其设置如下:制作数据定义,其中Zero被声明为NaturalNumber,以及一系列数字(按名称打印,例如,four)最多ten由此构建。

我没有太多麻烦理解Eq实例的声明如何工作(除了没有给出语法的确切解释),但我遇到了麻烦声明Ord所需的所有实例 - 我需要能够在整个数字集上构建一个排序,这样如果我输入"我就会得到True > 9"什么的。

现在,我有这段代码。前两行应该是正确的,因为我从练习本身复制它们(就像我应该的那样)。

instance Ord NaturalNumber where
    compare Zero Zero   = EQ
    compare Zero (S Zero)  = LT
    compare (S Zero) Zero  = GT
    compare x    (S x)  = LT

前四行工作正常,但是他们无法处理类似于"比较四个"以及类似于我输入的内容的任何内容都无法正常工作,即使我键入了类似compare four four = EQ的内容:我得到了一个相互冲突的定义"错误,大概是因为x出现两次。如果我写了类似compare two one = GT的内容,我会得到一个"模式匹配(es)重叠"警告,但它的工作原理。但是,当我将GT输入到实际的Haskell平台时,我也得到结果compare one two,所以显然有些东西不起作用。即使我在该行下面添加compare one two = LT,也会发生这种情况。

很明显,我无法通过编写我可能需要的每个实例来完成对Ord实例的描述,即使我可以,手动写出所有100个实例也是非常低效的

任何人都可以提供一些提示,告诉我如何解决这个问题并完成订购机制的构建?

3 个答案:

答案 0 :(得分:13)

此任务的重点是查找基本案例和递归规则。你得到的前两行是

instance Ord NaturalNumber where
    compare Zero Zero   = EQ

这是第一个基本案例,用文字:

  

零等于零

另外两个基本案例是:

  

零小于任何NaturalNumber

的后继者      

任何NaturalNumber的后继者大于零

请注意,您的第三行和第四行仅表示0 < 11 > 0,但没有任何其他非零数字。

然后,递归规则是,如果你比较两个非零数字,或者它们是后继数字,那就没有区别了:

  

比较1 + x1 + y与比较xy相同。

将其编入Haskell可以为您提供解决此练习的方法。

答案 1 :(得分:8)

您需要以涵盖所有可能模式的方式组织您的实例。为了简化,请记住您的数字是如何定义的:

one = S Zero
two = S one  -- or S (S Zero)

并考虑SZero,而不是onetwo等(它们只是别名)。一旦你这样做,你就会明白你错过了一个案例,如:

compare (S x) (S y) = compare x y

编辑: 像Jakob Runge注意到的那样,还应该改进以下基本条款:

compare Zero (S Zero)  = LT
compare (S Zero) Zero  = GT

在他们编写时,他们只允许在0和1之间进行比较。您应该更改它们以涵盖零和任何正数之间的比较:

compare Zero (S _)  = LT
compare (S _) Zero  = GT

答案 2 :(得分:3)

您的compare函数需要递归。你会希望你的最后一个案例能够捕捉到两个参数都是某个东西的继承者的情况,然后再说明它们是什么的继承者。此外,你的中间两种情况可能不是你想要的,因为它们只会捕获以下情况:

  1. 1 > 0
  2. 0 < 1
  3. 您希望这更加通用,以便您可以处理以下情况:

    1. S x > 0,适用于所有x
    2. 0 < S x,适用于所有x