2016-12-03 61 views
1

的問題是記錄字段,我不能寫n.key> = n.left.key & & n.key < n.right.key在compare_children功能;訪問OCaml中

我想將它寫像OOP node.left.right.left ...

我真的想了解更多關於鏡頭,但我還沒有發現在網絡上的任何材料。

type avl_tree = 
    Node of avl_tree_node 
    | Leaf 
and avl_tree_node = { 
    key : int; 
    balance : int; 
    left : avl_tree; 
    right : avl_tree; 
} 

type subtree_lens = { 
    get : avl_tree_node -> avl_tree; 
    set : avl_tree_node -> avl_tree -> avl_tree_node 
} 

let lens_right = { 
    get = (fun node -> node.right); 
    set = fun node t -> {node with right = t} 
} 

let lens_left = { 
    get = (fun node -> node.left); 
    set = fun node t -> {node with left = t} 
} 

let compare_children nd = 
    match nd with 
    | Leaf -> true 
    | Node n -> n.key >= n.left.key && n.key < n.right.key 

回答

2

一看這種方式是,你可以不寫n.left.key因爲n.left可能是一個Leaf

如果你想讓你的類型定義,你必須處理LeafNode作爲單獨的情況:

let compare_children nd = 
    match nd with 
    | Leaf -> true 
    | Node { left = Leaf } -> (* Leaf case, fill in... *) false 
    | Node { right = Leaf } -> (* Other leaf case, fill in... *) false 
    | Node { left = Node ln; right = Node rn; key = k } -> 
     k >= ln.key && k < rn.key 

更新

的OCaml的表達式可以是這樣的:{ x with f = v }。表達式x的類型必須是包含名爲f的字段的記錄類型。表達式的計算結果爲一個記錄,其字段與x的字段相同,但f字段的值爲v。實際上,您可以在with之後擁有任意數量的字段。

nd接入領域可以使圖案更加明確:

let compare_children nd = 
    match nd with 
    | Leaf -> true 
    | Node { left = Leaf; right = Leaf } -> true 
    | Node { left = Leaf; right = Node rn; key = k } -> k < rn.key 
    | Node { left = Node ln; right = Leaf; key = k } -> k >= ln.key 
    | Node { left = Node ln; right = Node rn; key = k } -> 
     k >= ln.key && k < rn.key 

請注意,我只是在什麼功能應該返回猜測。這只是您可能想要使用哪種模式的示例。

+0

由於@Jeffrey斯科菲爾德 一個問題雖然 這條線的從lens_right功能的代碼: 組=樂趣節點噸 - > {右= T節點} 它需要一個節點作爲參數,然後創建品牌新屬性被設置爲t的新節點? – Oleg

+0

該行:| Node {left = Leaf}告訴我,如果nd已將其左子類型的avl_tree鍵入爲Leaf,但我無法在此處訪問nd,那麼我必須執行其他模式匹配嗎? – Oleg

+0

我更新了我的答案,希望它有幫助。 –