对象排序如何工作?

时间:2011-05-04 10:37:47

标签: haskell typeclass

起初我应该说我从未见过任何Haskell代码。现在我有一个算法,我必须用另一种语言实现。不幸的是,这个算法依赖于一些Haskell的特性和功能,所以我想请求你帮忙,这是如何才能正确实现它的呢?

有代码:

data Utree = Tree[Utree]

instance Eq Utree where
    Tree(p) == Tree(q) = p == q
instance Ord Utree where
    Tree(p) <= Tree(q) = p <= q

norm(Tree(p)) = Tree(sort(map norm p))


iso p q = (norm p) == (norm q)

sort[] = []
sort(a:x) = ins a (sort x)

ins a [] = [a]
ins a (b:x)
   | a <= b = a:b:x
   | a > b = b:(ins a x)

现在,我如何接受它。 UTree是某种使用list来保存子树的树结构。 (相应应该是)定义的排序是插入排序,这很清楚。

但是使用了排序EqOrd,但我绝对不知道这是如何工作的。 TreeA有一些定义&lt; TreeB和我不知道它是如何比较的。

你可以解释一下吗?

2 个答案:

答案 0 :(得分:7)

您的代码给出了比较两棵树意味着什么的定义。例如,为了平等:

instance Eq Utree where
    Tree(p) == Tree(q) = p == q

它表示两棵树的相等与其子树列表的相等性相同。因此,在此代码中,pq列表。列表中的等式是在Haskell中预定义的,因为如果两个树长度相同且元素成对相等,则它们是相等的。由于pq的元素是,因此会以递归方式调用树上的相等比较。

直观地说,这意味着如果两棵树具有相同的形状,它们是相同的。

类似地,两个树的排序是根据子树列表的顺序定义的。

instance Ord Utree where
    Tree(p) <= Tree(q) = p <= q

Haskell中列表的排序是根据元素的排序预先定义为词典排序,即您比较两个第一个元素。同样,这会以递归方式调用树上的比较。如果它们不同,则使用它作为答案,否则比较接下来的两个元素等。如果在另一个列表之前用完一个列表,则最短列表在排序中排在第一位。

在这种情况下,这意味着这些树的排序大致是我们看到它们不同的最左边的点。此时,“最小”树在排序中排在第一位。

例如,假设我们有两棵树:

*Main> let a = Tree [Tree [], Tree [Tree []]]
*Main> let b = Tree [Tree [Tree []], Tree []] 
*Main> compare a b
LT

此示例中的树看起来像这样:

         *               *
a =     / \        b =  / \
       x   *           x   *
          /           /
         *           *

所以a小于b,因为当我们查看它们不同的最左边点时,xa有一个空子树,而b那里有一个节点。

答案 1 :(得分:1)

通过比较它们的元素列表来比较UT,这可以从实例定义中看出。 通过成对比较它们的元素,以通常的方式比较列表。例如,== for lists的实现如下所示:

[] == [] = True
(a:as) == (b:bs) = a == b && as == bs
_ == _ = False

有关Eq和Ord类的所有信息都可以在相关的Haskell报告中找到,我相信您已经很方便了。

列表的比较函数可能看起来像这样(实际上,它有点不同,但这里不相关):

[] > _ = False     -- the empty list is not greater than any other list
(a:as) > [] = True -- nonempty is greater than empty
(a:as) > (b:bs)
   | a < b = False
   | a > b = True
   | otherwise = as > bs