2012-04-30 6 views
3

최근 도입 된 F # 3.0 쿼리 이해 구문을 사용하여 Bill of Materials 종류를 정의하려고합니다. 메모리 내 모음에 대해 yield! seq 내포를 사용하여 이러한 종류의 쿼리를 정의 할 수는 있지만 원격 IQueryable 소스를 대상으로하는 쿼리 보급으로 변환하지 않았습니다. 어려운 부분은 제공자가 재귀 패턴에서 공통 테이블 표현식을 인식하도록 "훈련"하는 것입니다.재귀 쿼리 comprehensions (F # 3.0)

아이디어가 있으십니까?

+0

나는 더러워지는 것을 원하지 않지만 다시 게시 할 계획이라면 다음을 참고하십시오. http://stackoverflow.com/faq#signatures 서명이나 태그 라인이 필요 없습니다. 사실 실망 스럽습니다. –

답변

5

F # 3.0의 현재 쿼리 구문 지원이 재귀 쿼리를 처리 할 수 ​​있다고 생각하지 않습니다. 주요한 문제는 F # 3.0이 주로 C# 용으로 설계된 표준 IQueryable 구현에 의존하므로 재귀 구조를 기대하지 않는다는 것입니다.

이 기능을 지원하는 것은 매우 어려울 것이라고 생각합니다. 당신은 어느 쪽이든 당신의 자신의 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이 표준 패턴에 대한 Common Table Expressions을 생성하지 않는다면, 나는 그것을 생성하도록 훈련 할 수 없다고 생각합니다. 내가 아는 한 번역기는 실제로 확장 성이 없습니다.