私は.NET 4.5ベータでF#3.0を使用しており、タイプExpr<'a -> 'b>
のF#見積もりをLINQ Expression<Func<'a, 'b>>
に変換しようとしています。Expr 'b>をExpression <Funcに変換する方法
この問題の解決策がいくつか見つかりましたが、F#3.0または.NET 4.5のいずれかの変更により、これらのテクニックはもう機能していないようです。どちらの場合も
私はどちらかの質問の解決策からのコードを実行すると、以下のアクションが例外をスロー:
mc.Arguments.[0] :?> LambdaExpression
... mc
はMethodCallExpression
です。例外は次のとおりです。
System.InvalidCastExceptionの: 'System.Linq.Expressions.LambdaExpression' を入力するタイプ 'System.Linq.Expressions.MethodCallExpressionN' のオブジェクトをキャストすることができません。
いいえ、MethodCallExpressionN
の末尾に余分な "N"はタイプミスではありません。誰にでも提案はありますか?ありがとう。
UPDATE
はここで完全再現です。このコードは、<@ fun x -> x + 1 @>
のような式で正常に動作します。私の問題は、私の場合、Expr<'a -> 'b>
をExpr<'a -> obj>
に変換する必要があるので、すべてのラムダ式をbox
で捨てる必要はありません。私は元の表現をこれにスプライシングすることでそうしました:<@ %exp >> box @>
。これにより、正しい型のオブジェクトが生成されますが、Expression<Func<'a, obj>>
に変換するコードは機能しなくなりました。
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
おそらく、あなたはポイントフリースタイルの使用のために罰せられているでしょう。代わりに '<@ fun x ->%exp x |> box @>'を使用するとどうなりますか?ポイントフリースタイルを使用する場合、変換する式はラムダではなく、アプリケーションです。 – kvb
@kvb - これは良い考えですが、私がその構造体を使用すると、 '%exp'に下線が引かれ、"この値は関数ではなく、適用できません "と伝えられ、コンパイルが拒否されます。 –
しかし、 '<@ fun x -> x |>%exp |> box @>'はコンパイルされます。残念ながら、変換しようとすると同じエラーが発生します。 –