フラットseq<IHierarchy>
を階層に変換する関数を作成しようとしています。基本的には、parentIDとseqの子を持つものはすべて階層化することができます。 HierarchyをparentIDとchildrenプロパティを持つ基本クラスにする代わりに、各クラス(parentIDとchildren)に対して実装する2つの抽象フィールドを持つIHierarchyにすることが可能かどうか疑問に思っていました。 。F#:インターフェイスを介してレコードをコピーして更新しようとするとエラーが発生する
フラットseq<IHierarchy>
をIHierarchiesの階層構造に変換しようとするmakeHierarchy関数を含む以下のコードを添付しました。しかし、レコードのコピーを使用して構文を更新しようとすると(つまり{node with children = ...})、 "IHierarchy型にフィールドchildrenが含まれていません"というエラーが表示されます。私は、インターフェイスでこのタイプのために動作するための構文{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とchildrenフィールドを持つ基本クラスを使用し、この基本クラスから直接継承します。 2.クローン関数の一部として作成する私のインターフェイスは、子供のフィールドを変更可能にする、私の関数では、レコードをクローンし、手動で子フィールドを変更します。これらの両方がIHierarchyインターフェイスの一部であるため、これは問題ではありませんが、醜いようです。 – gnicholas
私はエレガントな選択肢を見ることができません。 –