首页 > 解决方案 > 如何在 F# 中为可区分联合的子集建模?

问题描述

我希望某物(人、物体等)具有能力(跳跃、奔跑等)。我希望有些东西只有特定的能力。这些是我目前的类型:

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具有“跳转”能力的代码。

标签: f#data-modeling

解决方案


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

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值。

只要您没有太多的组合,这就可以正常工作 - 如果您有四种不同类型的对象具有不同的能力子集,那么它可能会变得混乱。在这种情况下,您可能只使用一种类型进行运行时检查,以确保您只为每个对象分配允许的能力。


推荐阅读