我正在尝试使用以下类型表示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
答案 0 :(得分:3)
您的Node
类型需要为会员提供阅读left
和right
字段的权限。编写此类对象的最惯用的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)
构建节点,并使用你编写的模式对它们进行模式匹配。