如何在F#中为已区分联合的子集建模?

L42*_*L42 5 f# data-modeling

我希望事物(人,物体等)具有能力(跳跃,奔跑等)。我希望某些东西仅具有某些能力。这些是我当前的类型:

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
Run Code Online (Sandbox Code Playgroud)

我希望我的API的调用者能够要求ThingWithAbilities具有特定功能。示例:给我所有ThingWithAbilities具有“跳转”能力的对象。我怎样才能很好地建模呢?我想使不可能InanimateObject在代码中创建具有“跳转”功能的。

Tom*_*cek 7

如果要以类型安全的方式执行此操作,则需要为不同的功能集定义不同的类型:

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
}
Run Code Online (Sandbox Code Playgroud)

Here, InanimateAbility is a type for abilities that only inanimate objects have and AnimateAbility is a type for abilities that are unique to animate objects. Ability combines both of these and represents any kind of ability. Person can then have a set of Abilitiy values, but you can restrict abilities of InanimateObject to a set of InanimateAbility values.

This works fine as long as you do not have too many combinations - if you had four different kinds of objects with various subsets of abilities, then it might get messy. In that case, you would probably just use one type with a runtime check to make sure that you only assign allowed abilities to each object.