F# 什么时候应该使用FSharpFunc.Adapt?

F# 什么时候应该使用FSharpFunc.Adapt?,f#,F#,查看FSharp.Core和PowerPack中的源代码,我发现许多接受具有两个或多个参数的函数的高阶函数都会使用。例如: let mapi f (arr: ResizeArray<_>) = let f = FSharpFunc<_,_,_>.Adapt(f) let len = length arr let res = new ResizeArray<_>(len) for i = 0 to len - 1 do re

查看FSharp.Core和PowerPack中的源代码,我发现许多接受具有两个或多个参数的函数的高阶函数都会使用。例如:

let mapi f (arr: ResizeArray<_>) =
   let f = FSharpFunc<_,_,_>.Adapt(f)
   let len = length arr
   let res = new ResizeArray<_>(len)
   for i = 0 to len - 1 do
       res.Add(f.Invoke(i, arr.[i]))
   res
让mapi f(arr:ResizeArray)=
设f=FSharpFunc.Adapt(f)
设len=长度arr
let res=新的调整大小数组(len)
对于i=0到len-1 do
res.Add(f.Invoke(i,arr.[i]))
物件
FSharpFunc.Adapt
上的文档相当少。这是一个一般的最佳实践吗?我们应该在任何时候使用具有类似签名的高阶函数吗?仅当传入函数被多次调用时?它的优化程度如何?我们应该随时随地使用
Adapt
,还是很少使用


谢谢你的时间。

那很有趣!我没有任何官方信息(我也没有在任何地方看到文档),但这里有一些关于
Adapt
函数如何工作的想法

类似于
mapi
的函数采用函数的货币形式,这意味着参数的类型被编译为类似于
FSharpFunc
的类型。但是,许多函数实际上直接编译为两个参数的函数,因此实际值通常是继承自
FSharpFunc
FSharpFunc

如果调用此函数(例如
f1“a”
),f#编译器将生成如下内容:

FSharpFunc<int, string>.InvokeFast<a>(f, 1, "a");
FSharpFunc.InvokeFast(f,1,“a”);
如果使用Reflector查看
InvokeFast
函数,您将看到它测试函数是否编译为优化版本(
f:?FSharpFunc
)。如果是,则直接调用
Invoke(1,“a”)
,如果不是,则需要进行两次调用
Invoke(1)。Invoke(“a”)

每次调用作为参数传递的函数时都会执行此检查(执行检查然后使用优化的调用可能会更快,因为这更常见)

Adapt
函数的作用是将任何函数转换为
FSharpFunc
(如果函数未优化,它会为其创建一个包装器,但大多数情况下并非如此)。对adapted函数的调用将更快,因为它们不需要每次都执行动态检查(在
Adapt
中只执行一次检查)

因此,总结一下,
Adapt
可以提高性能,如果您调用一个作为参数传递的函数,该函数需要多次使用一个以上的参数。与任何优化一样,我不会盲目地使用它,但在调整性能时要注意它是一件有趣的事情

(顺便说一句:谢谢你提出一个非常有趣的问题,我不知道编译器会这样做:-)