首页 > 解决方案 > F# 表达式仅在泛型内自动从函数转换?

问题描述

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

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

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. 不起作用?

标签: lambdaf#

解决方案


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

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# 规范,隐式转换为 LINQ 表达式是 F# 的方法应用程序解析(第 14.4 节)的一部分,这是一个比简单函数应用程序解析(第 14.3 节)更复杂的过程。转换为 LINQ 表达式在第 8.13.7.4 节中有具体描述,其中说:

...类型导向的转换使 F# 表达式能够在方法调用时隐式转换为 LINQ 表达式。转换由 System.Linq.Expressions.Expression 类型的参数驱动。

(强调补充。)


推荐阅读