作为一个函数式编程(OCaml)的新手,我一直被这个问题困扰着。
我得到了如下代码:let rec height tr =
match tr with
| Node(d,[]) -> 1
| Node(d,[t1]) -> 1 + height t1
| Node(d,[t1;t2]) -> 1 + max (height t1) (height t2)
但是OCaml的顶层给出了一个警告:
Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
Node (_, _::_::_::_)
当我运行
let t : int gt =
Node('a',
[Node('b',[]);
Node('c',
[Node('d',
[Node('e',[])]);
Node('f',[]);
Node('g',[])])
]);;
height t;;
top抛出匹配失败异常。
我还实现了这个:
let rec height' tr =
match tr with
| Node(d,[]) -> 1
| Node(d,_::xs) -> 1 + max (List.map height' xs)
返回
Line31 | | Node(d,_::xs) -> 1 + max (List.map height' xs)
^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type int list -> int list
but an expression was expected of type int
此外,我还尝试了另一种方法:
let rec height tr =
match tr with
| Node(d,[]) -> 1
| Node(d,[t1]) -> 1 + height t1
| Node(d, t1::t2) ->
if t2=[]
then 2
else
2 + height t2
则错误为:
Line26 | 2 + height t2
^^
Error: This expression has type 'a gt list
but an expression was expected of type 'a gt
那么,我该如何克服这个问题呢?
你的问题
您的height
函数期望'a gt
类型的值。当调用height t2
时,t2
是列表的尾部,即a gt list
。如果你把它传递给height
,你会得到一个类型不匹配。
如何处理这个问题
给定树的定义:
type 'a gt = Node of 'a * 'a gt list
写一个height
函数很简单,我认为你可能想得太多了,因为你的模式匹配中有很多案例。
对于任何递归,键都是一个基本情况。
let rec height tr =
match
| Node (_, []) -> 1
具有空列表的节点高度为1。树中的实际数据并不重要,因此我们在模式匹配中使用_
。
唯一的其他可能是列表不是为空。所以我们可以匹配非空列表。同样,第一个节点不重要。
let rec height tr =
match
| Node (_, []) -> 1
| Node (_, _::xs) -> 2 + ...
现在我们必须将'a gt list
转换为int类型。height
将把'a gt
的值转换为int。那么我为什么不直接映射xs
呢?
let rec height tr =
match
| Node (_, []) -> 1
| Node (_, _::xs) -> 2 + List.map height xs
啊,但是这把xs
变成了int list
,我们不能把它加到int
上。我们可以使用fold_left
对该列表求和。
let rec height tr =
match
| Node (_, []) -> 1
| Node (_, _::xs) ->
let sum = List.fold_left (+) 0 in
2 + sum (List.map height xs)
还有一点
使用function
关键字,我们可以简化它。
let rec height =
function
| Node (_, []) -> 1
| Node (_, _::xs) ->
let sum = List.fold_left (+) 0 in
2 + sum (List.map height xs)