How to Convert Expr<'a -> 'b> to Expression<Func<'a, obj>>
f#, linq
Solution
Can you post a more complete sample and also include the F# expression that you're trying to convert?
I tried to test the behaviour on .NET 4.5 using a minimal sample and it worked for me. Here is what I did:
I created new F# 3.0 project and copied `Linq.fs` and `Linq.fsi` from the 2.0 version of F# PowerPack. (Or is there a 3.0 version of the `ToLinqExpression` method available somewhere in F# 3.0?)
I used the code from Daniel's earlier answer and called the function as follows:
let r = toLinq <@ fun x -> x + 1 @>
printfn "%A" r
This did not throw any exception and it printed `x => (x + 1)`, which looks correct to me.
EDIT: To answer the updated question - both of the code samples that you referred to (mine and Daniel's) assume that the body of the quotation is an explicitly constructed function, so they only work on quotations of a specific structure: `<@ fun x -> ... @>`.
You can fix the problem by using splicing in an explicitly constructed function. The following works for me:
let exp = <@ fun x -> x + 1 @>
let r = toLinq <@ fun a -> box ((%exp) a) @>
printfn "%A" r
This contains application of an F# function, so the generated `Expression` contains a call to `ToFSharpFunc` (which converts a delegate to an F# function) and then invocation of this. This may be an issue if you want `Expression` that standard .NET tools can understand (in which case, you'd have to post-process the C# expression tree and remove these constructs).
Problem
I'm using F# 3.0 with .NET 4.5 beta, and I'm trying to convert an F# quotation of type `Expr<'a -> 'b>` to a LINQ `Expression<Func<'a, 'b>>`. I've found several questions that have solutions to this problem, but those techniques don't seem to work any longer, presumably due to changes in either F# 3.0 or .NET 4.5. - Converting F# Quotations into LINQ Expressions - `Expression<Func<T, bool>>` from a F# func In both cases, when I run the code from the solutions of either question, the following action throws an exception: ``` mc.Arguments.[0] :?> LambdaExpression ``` ...where `mc` is a `MethodCallExpression`. The exception is: System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpressionN' to type 'System.Linq.Expressions.LambdaExpression'. No, the extra "N" at the end of `MethodCallExpressionN` is not a typo. Does anyone have a suggestion? Thanks. UPDATE Here's a complete reproduction. It turns out this code works fine on an expression like `<@ fun x -> x + 1 @>`. My problem is that in my case I need to convert an `Expr<'a -> 'b>` into `Expr<'a -> obj>` so that I don't have to litter all my lambda expressions with `box`. I did so by splicing the original expression into this one: `<@ %exp >> box @>`. This produces an object with the correct type, but the code to convert to `Expression<Func<'a, obj>>` no longer works. ``` module Expr = open System open System.Linq.Expressions open Microsoft.FSharp.Quotations open Microsoft.FSharp.Linq.QuotationEvaluation let rec private translateExpr (linq:Expression) = match linq with | :? MethodCallExpression as mc -> let le = mc.Arguments.[0] :?> LambdaExpression let args, body = translateExpr le.Body le.Parameters.[0] :: args, body | _ -> [], linq let ToFuncExpression (expr:Expr<'a -> 'b>) = let args, body = expr.ToLinqExpression() |> translateExpr Expression.Lambda<Func<'a, 'b>>(body, Array.ofList args) let exp = <@ fun x -> x + 1 @> let r = Expr.ToFuncExpression <@ %exp >> box @> printfn "%A" r ```