起初我应该说我从未见过任何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来保存子树的树结构。 (相应应该是)定义的排序是插入排序,这很清楚。
但是使用了排序Eq
和Ord
,但我绝对不知道这是如何工作的。 TreeA有一些定义&lt; TreeB和我不知道它是如何比较的。
答案 0 :(得分:7)
您的代码给出了比较两棵树意味着什么的定义。例如,为了平等:
instance Eq Utree where
Tree(p) == Tree(q) = p == q
它表示两棵树的相等与其子树列表的相等性相同。因此,在此代码中,p
和q
是列表。列表中的等式是在Haskell中预定义的,因为如果两个树长度相同且元素成对相等,则它们是相等的。由于p
和q
的元素是树,因此会以递归方式调用树上的相等比较。
直观地说,这意味着如果两棵树具有相同的形状,它们是相同的。
类似地,两个树的排序是根据子树列表的顺序定义的。
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
,因为当我们查看它们不同的最左边点时,x
,a
有一个空子树,而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