gpt4 book ai didi

f# - 如何使用单根对简单层次结构进行建模

转载 作者:行者123 更新时间:2023-12-03 01:43:01 25 4
gpt4 key购买 nike

我想在 F# 中对层次结构进行建模,其中每个节点必须有一个父节点,但显然根节点是异常(exception),它没有父节点。我的天真的解决方案

type Node = {
Id: int // meta data for node
Parent: Node option
}
let root = { Id = 1; Parent = None}
let child1 = { Id = 2; Parent = Some(root)}
let child2 = { Id = 3; Parent = Some(child1)}

但是我是通过 @swlaschin 进入 F# 的,他创建描述性域的方式让我大吃一惊。所以我觉得 Parent 是一个选项,而 99% 的情况下它是必需的。我尽最大努力:

type Node = 
| Node of NodeMeta * Node
| Root of NodeMeta
and NodeMeta = {
Id: int
}
let root = Root({Id = 1})
let child1 = Node({Id = 2}, root)
let child2 = Node({Id = 3}, child1)

有更惯用的方法吗?

最佳答案

如果我在领域驱动设计中为自己的模型构建此模型,我可能会按如下方式定义节点:

[<Struct>] type NodeId = private NodeId of int

module NodeId =
let create id =
// Replace with the proper validation rules for a Node Id
if id < 0
then Error "NodeId must be non-negative" // I would actually use a DU with each error case
else Ok <| NodeId id

let value (NodeId id) = id

type [<Struct>] RootNode = {Id: NodeId}
type [<Struct>] ChildNode = {Parent: Node; Id: NodeId}

and Node =
| Root of RootNode
| Node of ChildNode
member node.Id =
match node with
| Root r -> r.Id
| Node n -> n.Id
member node.Parent =
match node with
| Root _ -> None
| Node n -> Some n.Parent
member node.IsRootNode =
match node with
| Root _ -> true
| Node _ -> false
member node.IsChildNode =
not node.IsRootNode

这为我们提供了以下信息:

  • NodeId 的类型,它包装了 int 以及一个随附的模块,该模块封装了围绕构成有效标识符的任何业务规则
  • RootNodeChildNode 的特定类型,允许它们仅具有该类型节点的必需字段
  • 单个 Node 类型,允许我们将 RootNodeChildNode 表示为相同类型,而不要求它们具有相同的字段,但是仍然提供对底层字段的直接访问,并允许我们轻松区分 RootNodeChildNode

然后,我将有一个用于创建 Node 的模块,例如:

module Node = 
let createRoot =
NodeId.create >> Result.bind((fun id -> Root {Id = id}) >> Ok)

let createChild parent =
NodeId.create >> Result.bind((fun id -> Node {Id = id; Parent = parent}) >> Ok)

关于f# - 如何使用单根对简单层次结构进行建模,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50839160/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com