2010-05-06 58 views
6

为什么...创建委托和Lambda表达式在F#

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) 

不能编译,当:

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

呢?

唯一的区别是在第二个ApplyDelegate将其参数作为元组。

这个函数的参数太多,或者在没有预期的功能

回答

11

我没有看过的规范,以确认上下文中使用,但我猜测的隐式转换从“lambda”到“named委托类型”仅出现在“成员调用”中。

您可以随时进行转换明确:

ListHelper.ApplyDelegate [1..10] (IntDelegate(fun x -> printfn "%d" x)) 

(错误诊断是相当差的,我将文件中的错误。)

编辑:

对于书呆子.. 。

呀,spec

8.13.6成员调用时的类型定向转换如方法应用程序解析(请参阅 第14.4节)中所述,两种类型定向转换 应用于方法调用。

如果一个形式参数是委托 型DelegateType的,和实际 说法是语法功能 值(乐趣...),则该参数 解释为,如果它被写 新DelegateType(乐趣...)。

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

+0

谢谢。 “成员调用”到底是什么以及为什么有元组参数会有所作为? 成员应该总是采用tupled参数吗? – 2010-05-06 18:52:48

+3

“成员”是你用'member'关键字定义的东西,例如,某些类型的静态或实例方法。这些与通过'let f x = ...'或'fun'定义的“函数”形成对比,这些函数相对而言非常严格(例如,您不能重载函数,但可以重载成员)。成员们应该总是采取tupled的论据,是的;与特定于F#的函数相比,成员更多的是.NET-y实体。 – Brian 2010-05-06 18:59:57

+3

'tupled arguments'有所不同,因为当它被元组化时,所有的参数都立刻被传递给成员,所以第二个参数是成员的一个参数。在curried参数的情况下,第一个参数是成员的一个参数,并且导致一个新的(非成员)函数值,然后接受第二个参数。 – Brian 2010-05-06 19:03:40