How do I get warning FS1125 (The instantiation of the generic type 'xxx' is missing and can't be inferred from...) to go away?

Viewed 53

The advice from Don Syme doesn't seem to apply in this case.

type WrappedFunction<'a,'b> = 
    private {
        Function:'a -> 'b
    }
    static member Make (f:'a -> int) = {Function = f}
    static member Make (f:'a -> string) = {Function = f}

when used as in

let a = WrappedFunction.Make (fun (a:DateTime) -> a.ToString())

results in the warning.

1 Answers

The missing bit of insight here is this: there is no rule to say that the Make static methods have to return the same type on which they are defined.

Check this out:

let w : WrappedFunction<int,int> = WrappedFunction<int,bool>.Make (fun i -> string i)

This works, even though I call the Make function on WrappedFunction<int,bool>, but the result has type WrappedFunction<int,int>.

The second type parameter 'b is not mentioned anywhere in the signature of Make, so it doesn't have to match anything. But it still has to be known somehow, so it needs to be specified explicitly. And if you don't specify it explicitly, you get the warning.

With the first type parameter 'a it's a different story: since it's mentioned in the signature of Make, it has to match the surrounding type. So, for example, this doesn't work:

let w = WrappedFunction<string, bool>.Make (fun i -> i + 42)
                                                     ^^^^^^
                                                        |
                       "The type 'int' does not match the type 'string'"

If you want the Make methods to "just work" without specifying the type parameters, the usual pattern here is to create a second type with the same name, but without type parameters, and put the methods in it:

type WrappedFunction<'a,'b> = 
    {
        Function:'a -> 'b
    }

type WrappedFunction =
    static member public Make (f:'a -> int) = {Function = f}
    static member public Make (f:'a -> string) = {Function = f}

But of course, if that case you can't have access to the private constructor.

Related