Reputation: 915
I have a simple type like this:
/// <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>
From this definition I create implementations like so:
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 }
Examples:
let numAttr = numericAttribute [| 1.0; 4.0; 6.0; 20.0; 70.0 |]
let enAttr = enumerationAttribute [| "val1"; "val2"; "val3" |]
Now I can create instances:
let num1 = new AttributeInstance<float>(numAttr, 4.0)
let num2 = new AttributeInstance<float>(numAttr, 6.0)
let en1 = new AttributeInstance<string>(enAttr, "val1")
AttributeInstance is a type that is just a tuple of a specific attribute type and a value compatible with that attribute type.
I want a simple Tree along the lines of this:
type Tree<'a when 'a: comparison> =
| Leaf of 'a
| SubTree of AttributeInstance<'a> * seq<Tree<'a>>
My problem is that at different levels of the tree I want to be able to have different types. At one level I want to have a sub tree where the attribute is en1, and at the next level I want to be able to have num1 (or num2).
Can someone help me generalize or rethink this?
Upvotes: 0
Views: 271
Reputation: 25516
The problem is if you try to write something like
|Subtree of 'a * seq<Tree<'b>>
'b
ends up being a new type which could create something like an infinite chain of types which the compiler doesn't support.
One way to do this can be to wrap the possible types in a Union - Something like
type Element =
|....
and then your tree becomes
type Tree =
| Leaf of Element
| SubTree of AttributeInstance<element> * seq<Tree>
alternatively, you can have a multi generic tree - something like
type Tree<'a,'b,'c,'d> =
| Leaf1 of 'a
| Leaf2 of 'b
...
| SubTree of AttributeInstance<'a> * seq<Tree<'a,'b,'c,'d>>
Upvotes: 3