Reputation: 3266
I'm trying to pass a function to a function that accepts an Expression but it only works in the function is a generics one.
This one is what I want but it does not work:
open System
open System.Linq.Expressions
open MongoDB.Driver
type MyObject = { Name:string}
type MyClass () =
// I want to use this
let createFilter (field:Expression<Func<MyObject, string>>, value:string):FilterDefinition<MyObject> =
FilterDefinitionBuilder<MyObject>().Eq(field, value)
member this.CreateFilter<'T> (field:Expression<Func<'T, string>>, value:string):FilterDefinition<'T> =
FilterDefinitionBuilder<'T>().Eq(field, value)
member this.DoSomething(name:string) =
// 1. this does NOT work
let filter = createFilter( (fun x -> x.Name) , name)
// 2. this one works fine
let filter = this.CreateFilter( (fun x -> x.Name) , name)
Why the example 1. does not work?
Upvotes: 2
Views: 95
Reputation: 17153
The difference isn't due to generics. It happens because one example is a function call and the other is a method call. So even if you make the function generic, it still won't work:
let createFilter (field:Expression<Func<'T, string>>, value:string):FilterDefinition<'T> =
FilterDefinitionBuilder<'T>().Eq(field, value)
let filter = createFilter( (fun x -> x.Name) , name) // ERROR
Per the F# spec, implicit conversion to LINQ expressions is part of F#'s method application resolution (section 14.4), which is a more complex process than simple function application resolution (section 14.3). Conversion to LINQ expressions is specifically described in section 8.13.7.4, which says:
... type-directed conversion enables an F# expression to be implicitly converted to a LINQ expression at a method call. Conversion is driven by an argument of type System.Linq.Expressions.Expression.
(Emphasis added.)
Upvotes: 2