F#:n-ary树提取单个元素并保存计算

时间:2017-12-11 21:20:46

标签: f# tree

给出树的类型:

type id = int;;
type tree = T of id * tree list;;
let ex = T(12,[T(3,[T(4,[T(38,[])])]);T(23,[T(22,[])]);T(1,[])]);;

鉴于所有id都是唯一的,我想从给定的id中获取一棵树,如下所示:

get 23 ex = t(23, [t(22,[])]);

到目前为止,我只能制作这样的函数:

  let rec child c n = 
    match c with
    | [] -> []
    | e::es -> (get n e) @ (child es n)
   and get id t = 
    match t with 
    | T(id1,c) when id=id1-> [t]
    | T(_,c) -> child c id;;

哪个好,但该函数完全贯穿树中的所有节点。是否有可能使函数在找到正确的节点时终止,从而跳过一些计算?

1 个答案:

答案 0 :(得分:3)

您需要使递归调用返回一个值,该值以某种方式包含有关是否找到该节点的响应。如果确实如此 - 只需返回它,如果它没有 - 保持(递归地)搜索树的其余部分。

为此,F#有一个方便的内置类型 - Option。它是一个定义为type Option<'t> = Some of 't | None的和类型。所以我会让get函数返回Option<tree>而不是tree list,然后child函数可以决定是否要继续:

 let rec child c n = 
    match c with
    | [] -> None
    | e::es -> match get n e with
               | Some x -> Some x   // node found - just return it
               | None -> child es n // not found - keep searching
   and get id t = 
    match t with 
    | T(id1,c) when id=id1-> Some t
    | T(_,c) -> child c id;;

另请注意,您的child功能实际上在标准库中以List.tryPick的名称提供:

let rec child c n = List.tryPick (get n) c

这使得整个事情陷入了这个:

let rec get id t = 
    match t with 
    | T(id1,_) when id=id1 -> Some t
    | T(_,c) -> List.tryPick (get id) c