Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion 在F中加载一组递归类型的元素#_Recursion_F# - Fatal编程技术网

Recursion 在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

假设我们在SQL数据库中有一个供应商表,我们希望将其加载到F#:

使用类型提供程序很容易将表转换为F#,但假设我们想将数据转换为供应商序列,其中供应商是如下类型:

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,我希望有一个更优雅的解决方案。谢谢