从事一项基本上需要一棵树的作业,该树的声明是:
datatype a BinTree =
Leaf of a
| Node of a BinTree * a BinTree;
并返回一个树的int高度的元组和存储在树的最深部分的值列表。
fun deepest tree =
case tree of
Leaf(n) => [n]
| Node(l, r) => if #1(deepest l) > #1(deepest r) then ((#1(deepest l) + 1), #2(deepest l)) else
if #1(deepest l) < #1(deepest r) then ((#1(deepest r) + 1), #2(deepest r)) else
(1, #2(deepest l) @ #2(deepest r));
尝试测试此代码,我出现以下错误消息:
stdIn:43.1-47.35 Error: types of rules don't agree [tycon mismatch]
earlier rule(s): 'Z BinTree -> 'Z list
this rule: 'Z BinTree -> [+ ty] * 'Y list
in rule:
Node (l,r) =>
if (fn <rule>) (deepest <exp>) > (fn <rule>) (deepest <exp>)
then (<exp> <exp> + 1,(fn <rule>) (deepest <exp>))
else if <exp> <exp> < <exp> <exp>
then (<exp> + <exp>,<exp> <exp>)
else (1,<exp> @ <exp>)
stdIn:21.2-47.35 Error: right-hand-side of clause doesn't agree with
function result type [type mismatch]
expression: 'Z list
result type: {1:[+ ty], 2:'X list; 'Y}
in declaration:
deepest =
(fn tree =>
(case tree
of <pat> => <exp>
| <pat> => <exp>))
stdIn:1.2-47.35 Error: unresolved flex record (need to know the names of ALL
the fields
in this context)
type: {1:[+ ty], 2:'Y list; 'Z}
虽然我确实知道它是类型冲突,但是我找不到冲突,也找不到解决方法。任何帮助将不胜感激。
答案 0 :(得分:0)
此
earlier rule(s): 'Z BinTree -> 'Z list
来自叶子的大小写([n]
),使其从树到列表都具有功能。
这:
this rule: 'Z BinTree -> [+ ty] * 'Y list
来自节点的情况,使其具有从树到成对的“一种支持加法的类型”和列表的功能。
其余错误是由于SML在存在冲突时无法推断#1
和#2
的含义而引起的。
您的基本情况是错误的-应该是一对,而不是列表。
该对中的深度应为1,如果两个子树的深度相同,则深度不应为1。
在最坏的情况下,您还要为每个子树计算最深的值三次,在最坏的情况下要计算两次。 每个子树最好只递归一次。
类似这样的东西:
fun deepest (Leaf n) = (1, [n])
| deepest (Node (l, r)) =
case deepest l of (dl, ll) =>
case deepest r of (dr, lr) =>
if dl > dr then (dl + 1, ll)
else if dr > dl then (dr + 1, lr)
else (dl + 1, ll @ lr)
答案 1 :(得分:0)
尽管我也更喜欢像molbdnilo这样的 case-of 来编写此功能,但这里有一个使用 let-in-end 演示它们都可以使用的示例当结果是乘积(元组)时。由于if-then-else中的三种情况具有三个不同的结果(dl > dr
,dr > dl
和dl = dr
),因此最好使用Int-compare
:
fun deepest (Leaf n) = (1, [n])
| deepest (Node (l, r)) =
let val (lcount, ls) = deepest l
val (rcount, rs) = deepest r
in case Int.compare (lcount, rcount) of
GT => (lcount + 1, ls)
| LT => (rcount + 1, rs)
| EQ => (lcount + 1, ls @ rs)
end