If you need to represent resources containing some amount of gold, wood and stone, then it might make more sense to use a record type rather than a collection (e.g. a map or list) of discriminated unions.
For example, if you define your record like this:
type Resources =
{ Gold : int<gold>
Wood : int<wood>
Stone : int<stone> }
Then a value of Resources
satisfies all your criteria - it contains at most one filed for each kind of resource (it contains exactly one field of each kind, but the value can be zero). The fields are ordered, but the order does not matter (when creating the value) and you can also easily define +
operator on the type:
type Resources =
{ Gold : int<gold>
Wood : int<wood>
Stone : int<stone> }
static member (+) (r1:Resources, r2:Resources) =
{ Gold = r1.Gold + r2.Gold
Wood = r1.Wood + r2.Wood
Stone = r1.Stone + r2.Stone }
static member Zero =
{ Gold = 0<gold>; Stone = 0<stone>; Wood = 0<wood> }
I also added Zero
member, which makes it easier to create the record if you only want to set one of the resources. For example:
let r1 = { Resources.Zero with Gold = 2<gold> }
let r2 = { Resources.Zero with Wood = 4<wood> }
r1 + r2