Functional programming 使用OCAML中提供的高阶函数检查树是否为BST

Functional programming 使用OCAML中提供的高阶函数检查树是否为BST,functional-programming,ocaml,binary-search-tree,higher-order-functions,Functional Programming,Ocaml,Binary Search Tree,Higher Order Functions,所以,让我先说,这是我过去的作业的一部分,我无法解决,但因为我正在准备一个测试,我想知道如何做到这一点。我有讲师提供的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

所以,让我先说,这是我过去的作业的一部分,我无法解决,但因为我正在准备一个测试,我想知道如何做到这一点。我有讲师提供的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;;
让rec小于tn:bool=
开始比赛
|叶x->true
|节点(x,lt,rt)->(x为真
|节点(x,lt,rt)->(x>=n)&&(大于lt x)&(大于rt x)
结束
让我们检查一下=
折叠树(funx->true)(funx lt rt->((检查lt)和&(检查lt)和&(小于lt x)和&(大于等于rt x))t;;

有什么建议吗?我似乎很难准确理解高阶函数在OCAML中是如何工作的
BST的规范是什么?它是一个二叉树,其中:

  • 左子树(也是一个
    BST
    )中的所有元素都严格小于节点上存储的值
  • 右子树中的所有值(也是一个
    BST
    )都大于或等于节点上存储的值
fold
是一个归纳原则:您必须解释如何处理基本情况(此处为
Leaf
情况)以及如何在步骤情况(此处为
节点
情况)中组合子情况的结果

Leaf
始终是一个
BST
,因此基本情况将非常简单。但是,在
节点
情况下,我们需要确保值位于正确的子树中。为了能够执行此检查,我们需要额外的信息。我们的想法是使用
折叠
计算:

  • 给定的树是否为
    BST
  • 以及它的所有值存在的时间间隔
让我们引入类型同义词来构建我们的思想:

type is_bst      = bool
type 'a interval = 'a * 'a
正如预测的那样,基本情况很简单:

let leaf_bst (a : 'a) : is_bst * 'a interval = (true, (a, a))
节点
的情况下,我们将值
a
存储在节点上,并对左侧(
lih
l
eft
i
nduction
h
ypothesis)和右侧子树递归计算结果。这样构建的树是
BST
当且仅当两个子树是(
b1和&b2
)及其值与前面描述的属性有关。此新树的值存在的时间间隔现在是更大的
(lb1,ub2)


查看
折叠树的
f1
f2
函数的类型。调用最后一个函数的方法(在
检查
中)用
f1
中的
bool
替换类型
'b
,也用
f2
替换类型
'b
,因此
f2
中的两个参数
'b
被推断为
bool
而不是
节点
类似的除外。还可以将
rec
添加到函数
check\bst>中,因为该函数进行递归调用“非叶”的参数折叠的函数是当前节点的值和折叠子树的结果,而不是子树本身。我无法更改提供的函数。是的,我知道这些值是折叠子树的结果,但如何验证子树是否为BST?我可以获得一个bool来指示它,但我不会是able要验证其他较高的树,并将得到类型不匹配的错误。您需要一个中间步骤,将比
bool
更奇特的东西折叠起来,然后从折叠的结果中提取结果。我认为,只有知道子树是否为BST、左子树中的最大值以及sma,才有可能做到这一点L右子树中的最小值。@AndresGalaviz您必须使用
折叠树
?算法非常简单,没有折叠谢谢您提供了详细的解释!
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))
let bst (t : 'a tree) : bool =
  fst (fold_tree leaf_bst node_bst t)