I have a use case for treating a constructor for a derived type as a delegate and I can't figure out if it's impossible or I'm just incapable of working it out.
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)
Lets imagine that this is the model, in real life the model happens to be in C# and my code is in F#, but for brevity it's much easier to type out in F#.
And what I want to do is...
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
Now as the constructors passed into the raiseEventForJob1234
have the same signature and are part of the same inheritance chain, it feels possible. It's just I am not sure how to make it work, it's not even that they all quack, they are actually ducks!
Edit: There is a great answer here from @tomas, but also a really useful extension from Piaste in the comments make sure you check out both.
The problem you are getting here is called value restriction - basically, if you want to use function as generic, it has to be defined as an explicit function.
In your case raiseEventForJob1234
is generic (it can create and trigger different types of events), but it is defined as a value. Adding an argument solves this:
let raiseEventForJob1234 f = raise 1234 "other thing" f
raiseEventForJob1234 SomeJobStarted
raiseEventForJob1234 SomeJobComplete
Also note that this only works in F# 4.0 (in Visual Studio 2015). Previous version of F# did not support treating constructors as functions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With