Let's say I have a significant class hierarchy:
Tag
ControlFlowTag
IfTag
ForTag
JumpTag
HTMLTag
DivTag
and I want to make a list interspersed with these and strings.
let MyList = [tagA, tagB, "some text", tagC]
and I thought I could discriminated union it
type Node =
| Tag of Tag
| String of String
let MyList: list<Node> = [tagA, tagB, "some text", tagC]
but alas, it doesn't work without
let MyList: list<Node> = [Tag tagA, Tag tagB, String "some text", Tag tagC]
Obviously the Tag and String described in Node are orthogonal and separate from the existing Tag/String classes. Mousing over gives me the types as Node.Tag
and Node.String
, which isn't what I want.
What I have now is a function t
which creates a StringTag
which inherits from Tag
, giving me
let MyList : list<Tag> = [tagA, tagB, t"some text", tagC]
which is pretty nice, but the extra t
adds to the visual noise. What I actually want is a strongly typed "list of two different types" which I could work with using match
statements. I thought that was the point of Discriminated Unions, but their inability to use existing type hierarchies is a problem, since the existing hierarchy (in this case Tag
) is complex enough I think a full OO-inheritence approach to that subset of types is clearer than a pure Discriminated Union approach
One option is to just make it a list of obj
and cast everything before/during the match
, but that's not really very nice. Are there any other approaches?