If you need to imagine resources containing a certain amount of gold, wood, and stone, then it might make sense to use the type of record rather than the collection (for example, a map or list) of discriminatory unions.
For example, if you define your entry as follows:
type Resources = { Gold : int<gold> Wood : int<wood> Stone : int<stone> }
Then the value of Resources meets all your criteria - it contains no more than one file for each type of resource (it contains exactly one field of each type, 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 the + operator for 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 a Zero member, which makes creating a record easier if you only want to install one of the resources. For instance:
let r1 = { Resources.Zero with Gold = 2<gold> } let r2 = { Resources.Zero with Wood = 4<wood> } r1 + r2
source share