I am trying to make a function that turns any flat seq<IHierarchy> into a hierarchy. Essentially, anything that has a parentID and a seq of children should be able to be made into a hierarchy. Instead of making Hierarchy a base class with parentID and children properties [we can't as records are sealed classes] I was wondering if it was possible to make it an IHierarchy with two abstract fields that we implement for each class (parentID and children).
I attached the code below including a makeHierarchy function that tries to turn a flat seq<IHierarchy> into a hierarchy structure of IHierarchies. However, when I try using the record copy and update syntax (ie: {node with children = ...}) I am getting an error saying "The type IHierarchy does not contain a field children". I am a bit confused how to get the record {with} syntax to work for this type in the interface. Is it not possible to? Any help would be appreciated as I'm pretty new to 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) )