Search code examples
f#type-constraints

Type mismatching in parameters of function values


The following code generates a compile-time error at myFunctions.Add fn:

type IInterface = interface end

let myFunctions = ResizeArray<IInterface -> unit> ()

let add<'T when 'T :> IInterface> (fn: 'T -> unit) = myFunctions.Add fn

The error is "FS0001: Type mismatch. Excpeting a 'IInterface -> unit' but given a ''T -> unit' The type 'IInterface' does not match the type ''T'"

This is puzzling to me for the obvious reason that I constrain 'T to IInterface.

There are no compile-time errors with the following code:

type IInterface = interface end

let myStuff = ResizeArray<IInterface> ()

let add<'T when 'T :> IInterface> (item: 'T) = myStuff.Add item

... so there is some property of function parameters that is incompatible with this approach.

What is that property, and is there a way to make my approach work?


Solution

  • F# has no implicit upcasting for object types. So, the following compiles:

    let add<'T when 'T :> IInterface> (fn: IInterface -> unit) = myFunctions.Add fn
    

    (Note that your case is not covered by the language guide's statement "Upcasting is applied automatically when you pass arguments to methods on an object type". 'T -> unit :> IInterface -> unit is not an upcast. You would need upcasting earlier in the type checking process here, and that is not done in F#.)