F # unordered collection type to represent resources and costs

To do a bit of F # work, I make myself a simple game. The game involves resources that players can spend. There are 3 types of resources. Elements and actions in the game are associated with cost , which can combine the amounts of any amount of these resources (or none, for free actions). I started to implement this basically like this: Creating a list with several units of measure for floats in F #

 [<Measure>] type gold [<Measure>] type wood [<Measure>] type stone type Resource = | Gold of int<gold> | Wood of int<wood> | Stone of int<stone> 

Now I need a collection data type to represent cost . I want to:

  • Contains resources . Ideally, this would be limited to no more than one resource of each type, but with the security that I could do.

  • To be disordered. (1<gold>, 2<wood>) should ideally be (2<wood>, 1<gold>) ideally without overriding equality for the type.

  • It can be easily summed up with another collection of the same type (actions can have additional costs that will correspond to the normal cost) and deductible (from the pool of players' resources).

What would be a good F # collection type to do this? I realized that many of them are disordered. I looked at Set<'T> , but the binary-based part was a bit embarrassing to me, and I'm not sure if it fits my needs.

What do you think? Did I miss something obvious in my design?

+6
source share
1 answer

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 
+9
source

All Articles