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<gold>, 2<wood>)
должен равняться(2<wood>, 1<gold>)
в идеале без переопределения равенства для типа.Быть легко суммируемым с другой коллекцией того же типа (действия могут иметь дополнительные затраты, которые будут составлять обычную стоимость) и вычитаться (из пула ресурсов игрока).
Каким будет хороший тип коллекции 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
член, который облегчает создание записи, если вы хотите установить только один из ресурсов. Например:
let r1 = { Resources.Zero with Gold = 2<gold> }
let r2 = { Resources.Zero with Wood = 4<wood> }
r1 + r2