tags:

views:

269

answers:

2

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 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

+2  A: 

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) = ...
  1. .../FSharp-1.9.6.2/source/fsharp/FSharp.PowerPack.Linq/Linq.fs

High level information on F# quotations at [2,3].

  1. http://msdn.microsoft.com/en-us/library/dd233212(VS.100).aspx
  2. http://tomasp.net/blog/fsharp-quotation-samples.aspx
nullptr
One thing to watch out for is that ConvExpr is not part of the interface of the QuotationEvaluation module (at least in v1.9.7.8 of the Power Pack). (I get a compiler error when I try to use ConvExpr.) The module interface surfaces it via the `Expr.ToLinqExpression` extension method.
itowlson
+3  A: 

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.)

itowlson
I suppose the full name of the blogger is Michael Giagnocavo.
Novox