树形结构中的F#泛型

时间:2012-08-26 11:14:59

标签: generics f# tree

我有一个这样的简单类型:

/// <summary>
/// An attribute consists of a key and all possible values.
/// </summary>
type IAttribute<'a when 'a: comparison> =
    abstract Key: string
    abstract Values: seq<'a>

根据这个定义,我创建了类似的实现:

let numericAttribute values =
    { new IAttribute<float> with
        member this.Key = "Numeric"
        member this.Values = values }

let enumerationAttribute values =
    { new IAttribute<string> with
        member this.Key = "Enumeration"
        member this.Values = values }

示例:

let numAttr = numericAttribute [| 1.0; 4.0; 6.0; 20.0; 70.0 |]
let enAttr = enumerationAttribute [| "val1"; "val2"; "val3" |]

现在我可以创建实例:

let num1 = new AttributeInstance<float>(numAttr, 4.0)
let num2 = new AttributeInstance<float>(numAttr, 6.0)
let en1 = new AttributeInstance<string>(enAttr, "val1")

AttributeInstance是一种类型,它只是特定属性类型的元组和与该属性类型兼容的值。

我想要一个简单的树:

type Tree<'a when 'a: comparison> =
| Leaf of 'a
| SubTree of AttributeInstance<'a> * seq<Tree<'a>>

我的问题是,在树的不同级别,我希望能够拥有不同的类型。在一个级别我想要一个子树,其中属性是en1,在下一级我希望能够有num1(或num2)。

有人可以帮助我概括或重新考虑吗?

1 个答案:

答案 0 :(得分:3)

问题是如果你尝试编写像

这样的东西
|Subtree of 'a * seq<Tree<'b>>

'b最终成为一种新类型,它可以创建类似于编译器不支持的无限类型链。

执行此操作的一种方法是将可能的类型包装在Union中 - 类似于

type Element = 
    |....

然后你的树变成

type Tree =
| Leaf of Element
| SubTree of AttributeInstance<element> * seq<Tree>

或者,您可以拥有一个多通用树 - 类似于

type Tree<'a,'b,'c,'d> =
| Leaf1 of 'a
| Leaf2 of 'b
...
| SubTree of AttributeInstance<'a> * seq<Tree<'a,'b,'c,'d>>