F# 表达式仅在泛型中自动从函数转换?

F# Expression is automatically converted from function only within generics?

我正在尝试将一个函数传递给一个接受表达式的函数,但它只适用于泛型函数。

这个是我想要的,但它不起作用:

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)

为什么示例 1. 不起作用?

差异不是由泛型引起的。发生这种情况是因为一个示例是函数调用,另一个示例是方法调用。因此,即使您将函数设为泛型,它仍然无法正常工作:

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

根据 F# spec,到 LINQ 表达式的隐式转换是 F# 方法应用程序解析(第 14.4 节)的一部分,这是一个比简单函数应用程序解析(第 14.3 节)更复杂的过程。转换为 LINQ 表达式在 8.13.7.4 节中有具体描述,其中说:

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

(强调已添加。)