【问题标题】:How to model a subset of a discriminated union in F#?如何在 F# 中为可区分联合的子集建模?
【发布时间】:2020-01-24 09:52:41
【问题描述】:

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

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


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      您可以单独对它们进行建模,然后参考原子能力定义您的 Person/Object 类型

      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
      

      【讨论】:

      • 有趣的解决方案。这里type Jump = Jump 是一个复杂对象,其中名称Jump 指的是一个DU,也指的是这个DU 的唯一情况。这可以简化为type Jump = class end
      • 我认为 Haskell 的构造很正常
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-19
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      相关资源
      最近更新 更多