gui*_*e31 6 collections f# types units-of-measurement
为了练习一点F#,我正在建立一个简单的游戏.游戏涉及resources玩家可以花费.有3种资源.游戏中的项目和动作具有关联cost,可以组合任意数量的这些资源的数量(或者没有,用于自由行动).我开始实现这一点很多:在F#中创建一个包含多个浮点数测量单位的列表
[<Measure>] type gold
[<Measure>] type wood
[<Measure>] type stone
type Resource =
    | Gold of int<gold> 
    | Wood of int<wood>
    | Stone of int<stone>
现在我需要一个集合数据类型来表示一个cost.我希望它:
包含Resources.理想情况下,它将被限制为每种类型不超过1个资源,但我可以不用安全.
无序.理想情况下(1<gold>, 2<wood>)需要平等(2<wood>, 1<gold>)而不重新定义类型的相等性.
可以轻松地与另一个相同类型的集合(动作可能有可选成本,这将加上正常成本)和可减少(从玩家的资源池).
什么是一个很好的F#集合类型呢?我意识到没有多少是无序的.我在看,Set<'T>但"基于二叉树"部分让我有点困惑,我不确定它是否适合我的需要.
你怎么看 ?我错过了设计中明显的东西吗?
如果您需要代表包含一定数量的黄金,木材和石材的资源,那么使用记录类型而不是区分联合的集合(例如地图或列表)可能更有意义.
例如,如果您像这样定义记录:
type Resources =
  { Gold : int<gold> 
    Wood : int<wood>
    Stone : int<stone> }
然后,一个值Resources满足您的所有标准 - 它最多包含一种针对每种资源的字段(它只包含每种类型的一个字段,但该值可以为零).这些字段是有序的,但顺序无关紧要(创建值时),您也可以+在类型上轻松定义运算符:
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> }
我还添加了Zeromember,如果你只想设置其中一个资源,它可以更容易地创建记录.例如:
let r1 = { Resources.Zero with Gold = 2<gold> }
let r2 = { Resources.Zero with Wood = 4<wood> }
r1 + r2