F# 使用构造函数作为函数

F# use constructors as functions

我有一个将派生类型的构造函数视为委托的用例,但我不知道这是不可能的还是我无法解决。

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, but also a really useful extension from 的一个很好的答案,请务必检查两者。

您遇到的问题称为值限制 - 基本上,如果您想将函数用作泛型,则必须将其定义为显式函数。

在你的例子中 raiseEventForJob1234 是通用的(它可以创建和触发不同类型的事件),但它被定义为一个值。添加一个参数可以解决这个问题:

let raiseEventForJob1234 f = raise 1234 "other thing" f

raiseEventForJob1234 SomeJobStarted
raiseEventForJob1234 SomeJobComplete

另请注意,这仅适用于 F# 4.0(Visual Studio 2015)。以前版本的 F# 不支持将构造函数视为函数。