递归查询综合(F# 3.0)

3
我正在尝试使用最近引入的F# 3.0查询语法来定义BOM(物料清单)类型的查询。虽然可以使用yield! seq comprehensions为内存集合定义这些查询,但我在将其转换为针对可远程查询的IQueryable源的查询推导时遇到了困难。我猜难点在于“训练”提供程序识别递归模式中的公共表达式。有什么想法吗?

我不想说得太难听,但如果你打算再次在这里发帖,你可能需要看一下这个链接:http://stackoverflow.com/faq#signatures。你不需要签名或标语,事实上这是有点不被鼓励的。 - Onorio Catenacci
1个回答

5

很遗憾,我认为当前F# 3.0中支持查询语法的能力不足以处理递归查询。主要问题在于F# 3.0依赖于标准IQueryable实现,这些实现主要是为C#设计的,因此它们不支持递归结构。

我认为支持递归查询会非常困难。你可以自己实现F#引用到SQL翻译器(这很难),或者你可以实现某种预处理器,将包含递归的F#引用(查询)转换为LINQ to SQL翻译器可以处理的东西(但这也可能很难)。

总的来说,方法就是定义自己的查询构建器:

open System.IO
open Microsoft.FSharp.Quotations

type MyQueryBuilder() =
  member x.For(a, body) = Seq.collect body a
  member x.Quote(e) = e
  member x.YieldFrom(s) = s
  member x.Run(e:Expr<'T>) : 'T = failwithf "%A" e

// Example using the custom query builder
// (fails, printing the quoted query)
let mquery = MyQueryBuilder()    
let n = [1 .. 10]

let rec nums a : seq<int> =
  mquery { for b in n do
           yield! nums b }

Run方法中,您将获取表示查询的报价。您可以预处理并将所有调用MyQueryBuilder替换为调用标准的query操作,并使用其他方法替换递归。然后,您可以调用query.Run (以运行标准的IQueryable实现)。
虽然我已经说过,这可能会很难实现,但也许,如果您有一些特定类型的递归可以轻松处理,那么这可能是一个选项。但是,如果LINQ to SQL没有为任何标准模式生成公共表达式,则我认为您无法训练它生成它们-据我所知,翻译器实际上并不具有可扩展性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接