我有一个用例来处理派生类型的构造函数作为委托,我无法弄清楚它是不可能的,或者我只是无法解决它。
type SomeJobEvent(jobId : int, otherThing : string) =
member this.JobId = jobId
member this.OtherThing = otherThing
type SomeJobStarted(jobId : int, otherThing : string) =
inherit SomeJobEvent(jobId, otherThing)
type SomeJobComplete(jobId : int, otherThing : string) =
inherit SomeJobEvent(jobId, otherThing)
type SomeJobError(jobId : int, otherThing : string) =
inherit SomeJobEvent(jobId, otherThing)
让我们想象一下这就是模型,在现实生活中,模型恰好在C#中,我的代码在F#中,但为了简洁起见,在F#中输入更容易。
我想做的是......
let raise eventObject =
// This is just a helper, the raise event takes obj.
eventRaiser.Raise(eventObject)
let raise jobId otherThing eventConstructor =
// Lets treat the 'event' constructor as a function
raise(eventConstructor(jobId, otherThing))
[<EntryPoint>]
let main args =
// Lets curry this function up so I don't have to pass around 1234
let raiseEventForJob1234 = raise 1234 "other thing"
raiseEventForJob1234 SomeJobStarted
raiseEventForJob1234 SomeJobComplete
现在,作为传递给raiseEventForJob1234
的构造函数具有相同的签名并且是同一继承链的一部分,感觉可能。它只是我不确定如何使它工作,甚至不是他们都嘎嘎叫,他们实际上是鸭子!
修改:@tomas这里有一个很好的答案,但也是Piaste in the comments的一个非常有用的扩展,请确保同时查看两者。
答案 0 :(得分:7)
您遇到的问题称为值限制 - 基本上,如果您想将函数用作泛型函数,则必须将其定义为显式函数。
在您的情况下,raiseEventForJob1234
是通用的(它可以创建和触发不同类型的事件),但它被定义为值。添加参数解决了这个问题:
let raiseEventForJob1234 f = raise 1234 "other thing" f
raiseEventForJob1234 SomeJobStarted
raiseEventForJob1234 SomeJobComplete
另请注意,这仅适用于F#4.0(在Visual Studio 2015中)。以前版本的F#不支持将构造函数视为函数。