使用F#中的Lambda表达式创建代理

Mat*_*w H 7 .net f# delegates functional-programming

为什么...

type IntDelegate = delegate of int -> unit

type ListHelper =
    static member ApplyDelegate (l : int list) (d : IntDelegate) =
        l |> List.iter (fun x -> d.Invoke x)

ListHelper.ApplyDelegate [1..10] (fun x -> printfn "%d" x)
Run Code Online (Sandbox Code Playgroud)

不编译,时间:

type IntDelegate = delegate of int -> unit

type ListHelper =
    static member ApplyDelegate (l : int list, d : IntDelegate) =
        l |> List.iter (fun x -> d.Invoke x)

ListHelper.ApplyDelegate ([1..10], (fun x -> printfn "%d" x))
Run Code Online (Sandbox Code Playgroud)

呢?

唯一的区别在于,在第二个中,ApplyDelegate将其参数作为元组.

此函数需要太多参数,或者在不期望函数的上下文中使用

Bri*_*ian 11

我没有看过要确认的规范,但我猜测从"lambda"到"named delegate type"的隐式转换只发生在"成员调用"中.

您始终可以明确转换:

ListHelper.ApplyDelegate [1..10] (IntDelegate(fun x -> printfn "%d" x))
Run Code Online (Sandbox Code Playgroud)

(错误诊断很差;我会提交错误.)

编辑:

对于谁...

是的,规范

8.13.6成员调用中的类型导向转换如方法应用程序解析(参见§14.4)中所述,在方法调用中应用了两个类型导向的转换.

如果形式参数是委托类型DelegateType,并且实际参数在语法上是函数值(fun ...),那么该参数被解释为好像它已经写成新的DelegateType(fun ...).

lambda会自动转换为仅在"成员调用"中委托类型.在curried成员的情况下,传递的第一个参数是成员调用,但是然后返回一个函数值来应用第二个参数,而函数调用没有这个隐式转换规则.

  • "成员"是您使用`member`关键字定义的内容,例如某些类型的静态或实例方法.这些与"函数"形成对比,"函数"通过`let fx = ...`或`fun`定义,并且相对非常​​严格(例如,您不能重载函数,但可以重载成员).成员应该总是采取有争议的论点,是的; 与F#特定的函数相比,成员是更多的.NET-y实体. (3认同)
  • 'tupled arguments'有所不同,因为当它被tupled时,所有参数都会"立即"传递给成员,所以第二个参数是成员的参数.在curried参数的情况下,第一个参数是成员的参数,并且导致新的(非成员)函数值,然后获取第二个参数. (3认同)