F# неупорядоченный тип коллекции для представления ресурсов и затрат

чтобы попрактиковаться немного 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>) в идеале без переопределения равенства для типа.

  • легко суммируется с другой коллекцией того же типа (действия могут иметь дополнительные затраты, которые будут складываться в нормальная стоимость) и subtractable (от игрока в пул ресурсов).

что было бы хорошим типом коллекции F# для этого ? Я понял, что не многие из них неупорядочены. Я смотрел на Set<'T> но часть "на основе бинарных деревьев" меня немного смутила, и я не уверен, что она соответствует моим потребностям.

что вы думаете ? Я пропустил что-то очевидное в своем дизайне ?

1 ответов


Если вам нужно представить ресурсы, содержащие некоторое количество золота, дерева и камня, тогда может иметь смысл использовать тип записи, а не коллекцию (например, карту или список) дискриминируемых союзов.

например, если вы определяете свою запись следующим образом:

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> }

Я также добавил Zero member, что упрощает создание записи, если вы хотите установить только один из ресурсов. Например:

let r1 = { Resources.Zero with Gold = 2<gold> }
let r2 = { Resources.Zero with Wood = 4<wood> }
r1 + r2