簡體   English   中英

OCaml選項值樹

[英]OCaml option value tree

我有一個任務要編寫一個類型為'a btree -> 'a option list的函數,該函數將給定樹存儲在后綴順序(postorder)中類型為'a option的元素列表中。

內部節點將由None表示,值為x外部節點(葉)將由Some x表示。

到目前為止,葉子很容易實現,但是如何將其放入'a option list呢?

type 'a btree = L of 'a | N of 'a btree * 'a btree ;;

let rec store t =
    match t with
        | L x -> Some x
        | N (a,b) -> None ???   
;;

我知道第二個匹配項不正確,但是如何解決?

如果您看第一個案例,您會發現它還不存在。 它返回'a option ,但是您希望函數返回'a option list

顯然,您將返回一個列表,因此請首先解決該問題:

let rec store = function
  | L x -> [Some x]
  | N (a,b) -> [None] (* ??? *)

現在讓我們解決第二種情況; 我們想將None附加到輸出中,但是在此之前,我們想要子樹的節點:

let rec store = function
  | L x -> [Some x]
  | N (a,b) -> (store a) @ (store b) @ [None]

@具有類型

'a list -> 'a list -> 'a list

即,它將列表連接在一起。 我們要加入從左子樹開始的結果列表,然后是右子節點,最后是該內部節點的結果列表。

如果有人對這種改進感興趣,則可以通過線程附加的累加器參數,在性能方面比Len的解決方案好一些。

這個想法是從功能store : 'a btree -> 'a option list移出的store : 'a btree -> 'a option list采用樹並生成列表store : 'a btree -> 'a option list到功能store' : 'a btree -> 'a option list -> 'a option list將樹的元素添加到作為參數傳遞的現有列表中。

let rec store' t acc = match t with
  | L x -> Some x :: acc
  | N (a, b) ->
    store' a (store' b (None :: acc))

使用此定義,元素僅在最終結果列表中添加一次,而不是首先用於構建臨時store a列表,然后通過(@)運算符第二次添加到最終結果。

參數order很重要,因為在acc之前寫t給出了列表中最終元素順序的直覺: t的元素將在acc已經存在的元素之前 這使N情況很自然地讀出:很容易看到結果將首先具有abNoneacc的元素。

最后,您當然可以根據store'定義store

let store t = store' t []

通常將第一個定義包裝在第二個定義內(如果您不希望向用戶公開此“低級”功能),並為其指定與外部定義相同的名稱(這不會沖突)因為它不是遞歸的,所以不進入內部作用域):

let store t =
  let rec store t acc = match t with
    | L x -> Some x :: acc
    | N (a, b) ->
      store a (store b (None :: acc))
  in store t []

當然,這個定義是否比Len的定義“更好”取決於您的評估標准。 Len的解決方案更短,更易於閱讀,並且可以更緊密地映射原始問題。

(通過使用惰性枚舉而不是嚴格的列表,您可能會兩全其美,但這是另外一回事了。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM