lambda - 将 F# 函数转换为表达式>
问题描述
我有一个带有以下签名的函数的模块:
module Something =
let someFunc func = // ('TType -> 'TField) -> 'TValue
...
在该函数内部,我从某个外部库调用一个函数,该函数具有以下签名(C#)的方法:
class SomeClass
{
public ReturnType<TType> SomeMethod<TField>(func: Expression<Func<TType, TField>>) { ... }
}
当我尝试在那里传递一个'TType -> 'TField
函数时,我收到一个错误,它不能转换为Expression<Func<'TType, 'TField>>
. 我在 StackOverflow 上发现了以下问题:
但这并不能解决我的问题(第一个答案不起作用,第二个起作用,但我必须更改函数的签名)。
对于第二个答案,我必须将函数的签名更改为以下内容:
module Something =
let someFunc func = // Expression<Func<'TType, 'TField>>) -> 'TValue
...
添加对我的模块的“客户端”可见的附加类,如下所示:
type ExpressionHelper() =
static member AsExpression<'TType, 'TField>(e: Expression<Func<'TType, 'TField>>) = e
所以最终的调用看起来像这样:
let _ = Something.someFunc (fun (o: SomeType) -> o.someField)
看起来像这样:
let _ = Something.someFunc (ExpressionHelper.AsExpression (fun (o: SomeType) -> o.SomeField))
我不想强制user
我的模块将 F# 函数Expression<Func<'TType, 'TField>>
显式转换为。我想在我的模块中这样做,有什么方法可以实现吗?
解决方案
如果你有一个 type 的值,'T1 -> 'T2
你就没有办法把它变成一个 type 的值Expression<Func<'T1, 'T2>>
。这是不可能的,因为前者是一个编译函数(一个引用某个对象及其方法的委托),而后者是原始源代码的表示。
因此,您需要将其Expression<...>
用作参数的类型以使其工作(或者Expr
,如果您要使用引号,则它是 F# 等价物)。
但是,在 F# 中,编译器会自动将使用 lambda 函数语法创建fun x -> ..
的值转换为 type 的值Expression<...>
。它不会对 let-bound 函数的参数执行此操作,但会针对静态方法的参数执行此操作。这意味着您可以使用:
open System
open System.Linq.Expressions
type A =
static member foo (f:Expression<Func<int, int>>) =
f.ToString()
A.foo (fun n -> n + 1)
推荐阅读
- post - 使用 curl 与 python 请求的不同结果
- c# - Xamarin Android:存档-“未安装应用程序。包似乎已损坏”
- reactjs - 如何使用 React 函数组件获取组件的位置
- python - 数据映射/转换
- firebase - 有没有办法检测 Firestore 是否因为客户端位于代理后面而无法工作?
- javascript - 如何找到一个范围内的最小数字,并在谷歌表格中将该数字增加 1?
- java - 如何使用 JNA 处理 Java 内部内存访问
- kubernetes - 如何配置 Keycloak Helm Chart
- arrays - typescript doesn't throw typeerror on an array push of wrong type
- erd - ER Diagram 1:N relationship Convert