F# match pattern for Expr<int>

点点圈 提交于 2019-12-11 09:40:08

问题


I try to find the correct pattern to match and run an Expr<int> using the below code:

open System.Linq

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns

let runSelectQuery (q:Expr<IQueryable<'T>>) = 
    match q with
    | Application(Lambda(builder, Call(Some builder2, miRun, [Quote body])), queryObj) ->
        query.Run(Expr.Cast<Microsoft.FSharp.Linq.QuerySource<'T, IQueryable>>(body))
    | _ -> failwith "Cannot run this query %s" (q.ToString())

let runCountQuery (q:Expr<int>) = 
    match q with
    | Application(Lambda(builder, Call(None, miRun, [builder2, Quote body])), queryObj) ->
        query.Run(Expr.Cast<int>(body))
    | _ -> failwith "Cannot run this query %s" (q.ToString())

let countQuery source filter =
    let filter = match filter with | Some filter -> filter | _ -> <@ fun _ -> true @>
    <@ query { for item in source do
               where ((%filter) item)
               count } @>

The runSelectQuery correctly matches the Expr<IQueryable<'T>> pattern. However, I cannot find the correct pattern to match my generic count query Expr<int>

The pattern in the code I derived from the signature of countQuery gives me a:

This expression was expected to have type Expr but here has type 'a * 'b


回答1:


Found it! Stupidly I first tried to match the array pattern using a comma separated pattern (as is the list delimiter in C#), that obviously did not work in F# complaining the it was not a list but a tupple and thus not a Rex.

To match agains an int result or any 'T result:

let runQueryToQueryable (q:Expr<IQueryable<'T>>) = 
    match q with
    | Application(Lambda(builder, Call(Some builder2, miRun, [Quote body])), queryObj) ->
        query.Run(Expr.Cast<Microsoft.FSharp.Linq.QuerySource<'T, IQueryable>>(body))
    | _ -> failwith "Cannot run this query %s" (q.ToString())

let runQueryToType (q:Expr<'T>) = 
    match q with
    | Application(Lambda(builder, Call(None, miRun, [builder2; Quote body])), queryObj) ->
           query.Run(Expr.Cast<'T>(body))
    | _ -> failwith "Cannot run this query %s" (q.ToString())

Works like a charm.



来源:https://stackoverflow.com/questions/16960988/f-match-pattern-for-exprint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!