Как смоделировать подмножество дискриминированного объединения в F #? - PullRequest
5 голосов
/ 24 сентября 2019

Я хочу, чтобы вещь (человек, объект, что угодно) имела способности (прыжок, бег и т. Д.).Я хочу, чтобы у некоторых вещей были только определенные способности.Это мои текущие типы:

type Ability =
  | Jump
  | Stay
  | Run
  | Walk

type Person = {
  abilities : Ability Set // OK, since a person should be able to do all of the above
}

type InanimateObject = {
  abilities : Ability Set // Not OK, it should only be able to "Stay"
}

type ThingWithAbilities =
  | Person of Person
  | InanimateObject of InanimateObject

Я хочу, чтобы вызывающая сторона моего API могла запрашивать ThingWithAbilities с определенной способностью.Пример: Дайте мне все объекты ThingWithAbilities со способностью "Прыжок" .Как я могу смоделировать это хорошим способом?Я хочу сделать невозможным создание InanimateObject со способностью «прыгать» в коде.

Ответы [ 2 ]

7 голосов
/ 24 сентября 2019

Если вы хотите сделать это безопасным для типов способом, вам нужно будет определить разные типы для разных наборов способностей:

type InanimateAbility =
  | Stay

type AnimateAbility = 
  | Jump
  | Run
  | Walk

type Ability = 
  | Inanimate of InanimateAbility
  | Animate of AnimateAbility

type Person = {
  abilities : Ability Set
}

type InanimateObject = {
  abilities : InanimateAbility Set
}

Здесь InanimateAbility - это тип для способностейчто есть только у неодушевленных объектов, а AnimateAbility - это тип способностей, уникальных для одушевленных объектов.Ability сочетает в себе оба из них и представляет любые виды способностей.Person может иметь набор Abilitiy значений, но вы можете ограничить способности InanimateObject набором InanimateAbility значений.

Это прекрасно работает, если у вас не слишком многокомбинации - если у вас было четыре различных типа объектов с различными подмножествами способностей, то это может стать грязным.В этом случае вы, вероятно, просто используете один тип с проверкой во время выполнения, чтобы убедиться, что вы назначаете только разрешенные способности каждому объекту.

3 голосов
/ 24 сентября 2019

вы можете смоделировать их по отдельности, а затем определить типы людей / объектов со ссылкой на атомные способности

type Jump = Jump
type Stay = Stay
type Run = Run
type Walk = Walk

type Person = {
  abilities : Choice<Jump,Stay,Run,Walk> Set
}

type InanimateObject  = {
  abilities : Stay Set // actually haveing this as a set is a bit odd...but whatever
}

type ThingWithAbilities =
    | Person of Person
    | InanimateObject of InanimateObject
...