【发布时间】:2016-03-21 04:32:32
【问题描述】:
我正在尝试创建一个将任何平面 seq<IHierarchy> 转换为层次结构的函数。本质上,任何具有 parentID 和一系列子项的东西都应该能够构成层次结构。而不是让 Hierarchy 成为具有 parentID 和 children 属性的基类 [我们不能因为记录是密封类] 我想知道是否有可能将其作为具有我们为每个类(parentID 和孩子)实现的两个抽象字段的 IHierarchy .
我附上了下面的代码,其中包括一个 makeHierarchy 函数,该函数试图将平面 seq<IHierarchy> 转换为 IHierarchies 的层次结构。但是,当我尝试使用记录复制和更新语法(即:{node with children = ...})时,我收到一条错误消息,提示“IHierarchy 类型不包含子字段”。我有点困惑如何让记录 {with} 语法在界面中适用于这种类型。不可能吗?任何帮助将不胜感激,因为我对 F# 还很陌生。
module Hierarchy =
type IHierarchy =
abstract member parentID: Option<int>
abstract member children: seq<IHierarchy>
module SalesComponents =
open Hierarchy
type SalesComponentJson = JsonProvider<""" [{ "ID":1, "parentID":0, "name":"All Media" }, { "ID":1, "parentID":null, "name":"All Media" }] """, SampleIsList=true>
type SalesComponent = {
ID: int;
parentID: Option<int>;
children: seq<SalesComponent>;
name: string
}
interface IHierarchy with
member x.parentID = x.parentID
member x.children = x.children |> Seq.map (fun c -> c :> IHierarchy)
open Hierarchy
open SalesComponents
let main argv =
let makeHierarchy hierarchyRecords:seq<IHierarchy> =
let root = hierarchyRecords |> Seq.tryFind (fun sc -> sc.parentID.IsNone)
let rec getHierarchy (node: IHierarchy, scs: seq<IHierarchy>) =
{node with children = scs |> Seq.filter (fun sc -> sc.parentID.IsSome && sc.parentID.Value = node.ID )
|> Seq.map (fun sc -> getHierarchy(sc,scs))}
root |> Option.map (fun r -> getHierarchy(r,hierarchyRecords) )
【问题讨论】:
-
IHeirachy 不是记录,所以不能使用记录语法。
-
我就是这么想的。关于 F# 中的设计模式以解决此问题的任何建议?我想到的选项似乎都很糟糕: 1. 不要使用记录类型,使用具有 parentID 和子字段的基类,并直接从该基类继承 2. 将克隆函数作为我接口的一部分,使子字段可变,在我的函数中克隆记录,然后手动改变子字段。由于这两个都是 IHierarchy 接口的一部分,所以这应该不是问题,但看起来很难看。
-
我看不到一个优雅的选择。
标签: generics interface f# record