Recursion 在F中加载一组递归类型的元素#
假设我们在SQL数据库中有一个供应商表,我们希望将其加载到F#: 使用类型提供程序很容易将表转换为F#,但假设我们想将数据转换为供应商序列,其中供应商是如下类型:Recursion 在F中加载一组递归类型的元素#,recursion,f#,Recursion,F#,假设我们在SQL数据库中有一个供应商表,我们希望将其加载到F#: 使用类型提供程序很容易将表转换为F#,但假设我们想将数据转换为供应商序列,其中供应商是如下类型: Vendor = {ID: int; Name: String; Parent: Vendor option} let rec getRecordRecursive recID = let record = getRecord recID { ID = record.ID Name
Vendor = {ID: int; Name: String; Parent: Vendor option}
let rec getRecordRecursive recID =
let record = getRecord recID
{
ID = record.ID
Name = record.Name
Parent =
record.ParentID
|> Option.map (fun pid ->
Lazy.Create <| fun () ->
getRecordRecursive pid)
}
一个人怎么做呢?问题是,在创建供应商序列时,我们无法将每一行映射到特定的供应商,因为我们还没有供应商序列。还可以假设应用程序允许循环(A可以将B作为父级,B可以将A作为父级),尽管对于供应商来说,这并没有什么意义
您可以将供应商类型定义为:
Vendor = {ID: int; Name: String; ParentID: int option}
但这似乎不那么优雅,因为每次你想引用父供应商时,你都必须做一些查找。有没有已知的解决方案?这似乎是一种经常发生的情况(尤其是在处理图形或树时)
似乎解决方案也可能涉及某种惰性计算,但我不清楚惰性这不是一个特别优雅的解决方案,但对父级使用惰性计算的解决方案看起来是这样的:有两种类型,一种与表的模式匹配,另一种是递归的:
type Flat = { ID: int; Name: string; ParentID : int option}
type Recursive = { ID: int; Name: string; Parent: Lazy<Recursive> option}
你可以这样把它放在一起:
Vendor = {ID: int; Name: String; Parent: Vendor option}
let rec getRecordRecursive recID =
let record = getRecord recID
{
ID = record.ID
Name = record.Name
Parent =
record.ParentID
|> Option.map (fun pid ->
Lazy.Create <| fun () ->
getRecordRecursive pid)
}
let rec getRecordRecursive recID=
let record=getRecord recID
{
ID=record.ID
Name=记录。Name
父项=
record.ParentID
|>Option.map(趣味pid->
懒惰。创造
GetRecord(递归pid)
}
因此,在某种意义上,您正在使用lazy类型来延迟递归的下一步,直到您需要它为止。否则,getRecordRecursive 4
将导致堆栈溢出
但也有一些折衷办法——例如,在这样的记录上,你再也得不到很好的表现。从长远来看,我不相信你使用
平面记录不会更好。Drats,我希望有一个更优雅的解决方案。谢谢