How to call C# method taking a parameter of type Expression<T> from F#?
I'm tryng to use the Brahma library from F# and i need to call a method that takes an Exprssion as parameter and I don't know how to do it.
here is the C# code i'd like to translate :
// Create the computation provider
var computationProvider = new ComputationProvider();
// Create a data-parallel array and fill it with data
var data = new DataParallelArray<float>(computationProvider,
new[] { 0f, 1f, 2f, 3f, 4f, 5f, 6f });
// Compile the query
CompiledQuery query = computationProvider.Compile<DataParallelArray<float>>
(
d => from value in d
select value * 2f
);
// Run the query on this data
IQueryable result = computationProvider.Run(query, data);
// Print开发者_StackOverflow out the results
foreach (float value in result)
Console.WriteLine(result[i]);
// Get rid of all the stuff we created
computationProvider.Dispose();
data.Dispose();
result.Dispose();
Source
You need to use F# quotations, but these produce F# expression (Expr) objects, and the translation to CLR expressions is a bit fiddly.
Start by writing your expression as a F# quotation:
let expr = <@ fun (d : DataParallelArray<float>) -> d.ToString() @> // real implementation omitted
Now you need something that will convert this to a CLR (LINQ) expression. I found this little helper method by a chap named Michael (can't find full name to give full credit, sorry):
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.QuotationEvaluation
open System.Linq.Expressions
let ToLinq (exp : Expr<'a -> 'b>) =
let linq = exp.ToLinqExpression()
let call = linq :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
(Note this depends on the F# PowerPack, and the PowerPack ToLinqExpression method is considered experimental, so this may not be acceptable for production code.)
Now you just apply the ToLinq method to the F# expression and pass the result to the desired method:
let clrExpression = expr |> ToLinq
// pass clrExpression to Compile method
(This worked for me with a simplified test; you may need to provide some extra type hints, and I haven't tried to translate the sequence expression from your real code.)
Glancing through the F# source directory[1], I see:
/// Convert F# quotations to LINQ expression trees.
/// A more polished LINQ-Quotation translator will be published
/// concert with later versions of LINQ.
let rec ConvExpr env (inp:Expr) = ...
- .../FSharp-1.9.6.2/source/fsharp/FSharp.PowerPack.Linq/Linq.fs
High level information on F# quotations at [2,3].
- http://msdn.microsoft.com/en-us/library/dd233212(VS.100).aspx
- http://tomasp.net/blog/fsharp-quotation-samples.aspx
精彩评论