使用对象上的模式匹配遍历我的树内容

时间:2012-09-12 08:16:10

标签: f# tree pattern-matching tree-traversal

我正在尝试使用以下类型表示F#中的树数据结构:

type Node = 
 val mutable left: Node option
 val mutable right: Node option
 val mutable value: int 

 new (l, r, v) = {left = l; right = r; value = v}

我可以像这样创建一个树:

let root = new Node (Some (new Node (None, None, 2)), Some (new Node (None, None, 3)), 1)

我现在想要使用模式匹配进行遍历。但是,我不知道如何模式匹配对象。我试过这样的事情:

let rec traverse r =
  match r with
  | Node (None, None, v) -> printfn "%d" v

并在那里停止,因为模式匹配是错误的。

编辑: 在Petricek的回答之后,我没有使用他的所有建议,因为我还没有读过有关歧视的工会和其他课程特征。一旦我对这些事情了解得多,我就会实施。但就时间而言,这就是它的外观:

type Node = 
 val left: Node option
 val right: Node option
 val value: int 

 new (l, r, v) = {left = l; right = r; value = v}

let (|Node|) (nd: Node) = (nd.left, nd.right, nd.value)

let root = new Node (Some (new Node (None, None, 2)), Some (new Node (None, None, 3)), 1)

let rec traverseLRtR r =
  match r with
  | Node (None, None, v) -> printfn "%d" v
  | Node (left, right, v) -> traverseLRtR left.Value; traverseLRtR right.Value; printfn "%d" v; 

traverseLRtR root

输出是:

2
3
1

1 个答案:

答案 0 :(得分:3)

您的Node类型需要为会员提供阅读leftright字段的权限。编写此类对象的最惯用的F#方法是使用:

type Node(left:Node option, right:Node option, value : int) =
  member x.Left = left
  member x.Right = right 

我删除了字段上的mutable属性,因为您没有在示例中对其进行变更(但您可以使用get& set属性使其变为可变,如果是#39; s你想要的东西)。我还将代码更改为使用隐式构造函数语法,这更简单。

下一步,您可以编写一个返回节点组件的活动模式:

 let (|Node|) (nd:Node) = (nd.Left, nd.Right)

但是,有什么理由(即C#兼容性)为什么你不使用F#区别联盟?这样,您可以非常轻松地定义树数据结构,并且您可以免费获得模式匹配:

type Node = Node of Node option * Node option * int

然后你可以通过writin Node(None, Some ..., 42)构建节点,并使用你编写的模式对它们进行模式匹配。