所以让我首先说这是过去的作业的一部分,我无法解决,但在我准备测试时,我想知道如何做到这一点。我有教师提供的map_tree和fold_tree的这些实现:
let rec map_tree (f:'a -> 'b) (t:'a tree) : 'b tree =
match t with
| Leaf x -> Leaf (f x)
| Node (x,lt,rt) -> Node (f x,(map_tree f lt),(map_tree f rt))
let fold_tree (f1:'a->'b) (f2:'a->'b->'b->'b) (t:'a tree) : 'b =
let rec aux t =
match t with
| Leaf x -> f1 x
| Node (x,lt,rt) -> f2 x (aux lt) (aux rt)
in aux t
我需要使用上述功能实现一个验证树是BST的函数,到目前为止,这是我已经完成的并且我得到了错误:
Error: This expression has type bool but an expression was expected of type
'a tree
这是我的代码:
let rec smaller_than t n : bool =
begin match t with
| Leaf x -> true
| Node(x,lt,rt) -> (x<n) && (smaller_than lt x) && (smaller_than rt x)
end
let rec greater_equal_than t n : bool =
begin match t with
| Leaf x -> true
| Node(x,lt,rt) -> (x>=n) && (greater_equal_than lt x) && (greater_equal_than rt x)
end
let check_bst t =
fold_tree (fun x -> true) (fun x lt rt -> ((check_bst lt) && (check_bst rt)&&(smaller_than lt x)&&(greater_equal_than rt x))) t;;
有什么建议吗?我似乎无法准确理解更高阶函数在OCAML中的工作原理
答案 0 :(得分:6)
BST
的规格是什么?它是二叉树,其中:
BST
)严格小于节点上存储的值BST
)大于或等于节点上存储的值 A fold
是一个归纳原则:您必须解释如何处理基本情况(此处为Leaf
情况)以及如何在步骤情况下组合子结果的结果(这里有Node
个案例。)
Leaf
始终为BST
,因此基本情况非常简单。但是,在Node
情况下,我们需要确保值在正确的子树中。为了能够执行此检查,我们将需要额外的信息。我们的想法是fold
计算:
BST
让我们引入类型同义词来构建我们的想法:
type is_bst = bool
type 'a interval = 'a * 'a
正如预测的那样,基本情况很简单:
let leaf_bst (a : 'a) : is_bst * 'a interval = (true, (a, a))
在Node
案例中,我们在节点处存储了值a
,并且左侧(lih
)递归计算结果,如l
eft {{1 }} nduction i
ypothesis)和右子树。这样构建的树是h
当且仅当两个子树是(BST
)并且它们的值尊重前面描述的属性时。此新树的值所处的时间间隔现在更大b1 && b2
。
(lb1, ub2)
最后,检查树是否为let node_bst (a : 'a) (lih : is_bst * 'a interval) (rih : is_bst * 'a interval) =
let (b1, (lb1, ub1)) = lih in
let (b2, (lb2, ub2)) = rih in
(b1 && b2 && ub1 < a && a <= lb2, (lb1, ub2))
的函数是通过从其上调用BST
的结果中弹出布尔值来定义的。
fold_tree leaf_bst node_bst